OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.2.2/] [gcc/] [alloc-pool.c] - Blame information for rev 193

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 38 julius
/* Functions to support a pool of allocatable objects.
2
   Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006,
3
   2007  Free Software Foundation, Inc.
4
   Contributed by Daniel Berlin <dan@cgsoftware.com>
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under
9
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
12
 
13
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "alloc-pool.h"
25
#include "hashtab.h"
26
 
27
#define align_eight(x) (((x+7) >> 3) << 3)
28
 
29
/* The internal allocation object.  */
30
typedef struct allocation_object_def
31
{
32
#ifdef ENABLE_CHECKING
33
  /* The ID of alloc pool which the object was allocated from.  */
34
  ALLOC_POOL_ID_TYPE id;
35
#endif
36
 
37
  union
38
    {
39
      /* The data of the object.  */
40
      char data[1];
41
 
42
      /* Because we want any type of data to be well aligned after the ID,
43
         the following elements are here.  They are never accessed so
44
         the allocated object may be even smaller than this structure.  */
45
      char *align_p;
46
      HOST_WIDEST_INT align_i;
47
      long double align_ld;
48
    } u;
49
} allocation_object;
50
 
51
/* Convert a pointer to allocation_object from a pointer to user data.  */
52
#define ALLOCATION_OBJECT_PTR_FROM_USER_PTR(X)                          \
53
   ((allocation_object *) (((char *) (X))                               \
54
                           - offsetof (allocation_object, u.data)))
55
 
56
/* Convert a pointer to user data from a pointer to allocation_object.  */
57
#define USER_PTR_FROM_ALLOCATION_OBJECT_PTR(X)                          \
58
   ((void *) (((allocation_object *) (X))->u.data))
59
 
60
#ifdef ENABLE_CHECKING
61
/* Last used ID.  */
62
static ALLOC_POOL_ID_TYPE last_id;
63
#endif
64
 
65
#ifdef GATHER_STATISTICS
66
 
67
/* Store information about each particular alloc_pool.  */
68
struct alloc_pool_descriptor
69
{
70
  const char *name;
71
  int allocated;
72
  int created;
73
  int peak;
74
  int current;
75
};
76
 
77
/* Hashtable mapping alloc_pool names to descriptors.  */
78
static htab_t alloc_pool_hash;
79
 
80
/* Hashtable helpers.  */
81
static hashval_t
82
hash_descriptor (const void *p)
83
{
84
  const struct alloc_pool_descriptor *d = p;
85
  return htab_hash_pointer (d->name);
86
}
87
static int
88
eq_descriptor (const void *p1, const void *p2)
89
{
90
  const struct alloc_pool_descriptor *d = p1;
91
  return d->name == p2;
92
}
93
 
94
/* For given name, return descriptor, create new if needed.  */
95
static struct alloc_pool_descriptor *
96
alloc_pool_descriptor (const char *name)
97
{
98
  struct alloc_pool_descriptor **slot;
99
 
100
  if (!alloc_pool_hash)
101
    alloc_pool_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
102
 
103
  slot = (struct alloc_pool_descriptor **)
104
    htab_find_slot_with_hash (alloc_pool_hash, name,
105
                              htab_hash_pointer (name),
106
                              1);
107
  if (*slot)
108
    return *slot;
109
  *slot = xcalloc (sizeof (**slot), 1);
110
  (*slot)->name = name;
111
  return *slot;
112
}
113
#endif
114
 
115
/* Create a pool of things of size SIZE, with NUM in each block we
116
   allocate.  */
117
 
118
alloc_pool
119
create_alloc_pool (const char *name, size_t size, size_t num)
120
{
121
  alloc_pool pool;
122
  size_t pool_size, header_size;
123
#ifdef GATHER_STATISTICS
124
  struct alloc_pool_descriptor *desc;
125
#endif
126
 
127
  gcc_assert (name);
128
 
129
  /* Make size large enough to store the list header.  */
130
  if (size < sizeof (alloc_pool_list))
131
    size = sizeof (alloc_pool_list);
132
 
133
  /* Now align the size to a multiple of 4.  */
134
  size = align_eight (size);
135
 
136
#ifdef ENABLE_CHECKING
137
  /* Add the aligned size of ID.  */
138
  size += offsetof (allocation_object, u.data);
139
#endif
140
 
141
  /* Um, we can't really allocate 0 elements per block.  */
142
  gcc_assert (num);
143
 
144
  /* Find the size of the pool structure, and the name.  */
145
  pool_size = sizeof (struct alloc_pool_def);
146
 
147
  /* and allocate that much memory.  */
148
  pool = xmalloc (pool_size);
149
 
150
  /* Now init the various pieces of our pool structure.  */
151
  pool->name = /*xstrdup (name)*/name;
152
#ifdef GATHER_STATISTICS
153
  desc = alloc_pool_descriptor (name);
154
  desc->created++;
155
#endif
156
  pool->elt_size = size;
157
  pool->elts_per_block = num;
158
 
159
  /* List header size should be a multiple of 8.  */
160
  header_size = align_eight (sizeof (struct alloc_pool_list_def));
161
 
162
  pool->block_size = (size * num) + header_size;
163
  pool->free_list = NULL;
164
  pool->elts_allocated = 0;
165
  pool->elts_free = 0;
166
  pool->blocks_allocated = 0;
167
  pool->block_list = NULL;
168
 
169
#ifdef ENABLE_CHECKING
170
  /* Increase the last used ID and use it for this pool.
171
     ID == 0 is used for free elements of pool so skip it.  */
172
  last_id++;
173
  if (last_id == 0)
174
    last_id++;
175
 
176
  pool->id = last_id;
177
#endif
178
 
179
  return (pool);
180
}
181
 
182
/* Free all memory allocated for the given memory pool.  */
183
void
184
free_alloc_pool (alloc_pool pool)
185
{
186
  alloc_pool_list block, next_block;
187
#ifdef GATHER_STATISTICS
188
  struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name);
189
#endif
190
 
191
  gcc_assert (pool);
192
 
193
  /* Free each block allocated to the pool.  */
194
  for (block = pool->block_list; block != NULL; block = next_block)
195
    {
196
      next_block = block->next;
197
      free (block);
198
#ifdef GATHER_STATISTICS
199
      desc->current -= pool->block_size;
200
#endif
201
    }
202
#ifdef ENABLE_CHECKING
203
  memset (pool, 0xaf, sizeof (*pool));
204
#endif
205
  /* Lastly, free the pool.  */
206
  free (pool);
207
}
208
 
209
/* Frees the alloc_pool, if it is empty and zero *POOL in this case.  */
210
void
211
free_alloc_pool_if_empty (alloc_pool *pool)
212
{
213
  if ((*pool)->elts_free == (*pool)->elts_allocated)
214
    {
215
      free_alloc_pool (*pool);
216
      *pool = NULL;
217
    }
218
}
219
 
220
/* Allocates one element from the pool specified.  */
221
void *
222
pool_alloc (alloc_pool pool)
223
{
224
  alloc_pool_list header;
225
  char *block;
226
#ifdef GATHER_STATISTICS
227
  struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name);
228
 
229
  desc->allocated+=pool->elt_size;
230
#endif
231
 
232
  gcc_assert (pool);
233
 
234
  /* If there are no more free elements, make some more!.  */
235
  if (!pool->free_list)
236
    {
237
      size_t i;
238
      alloc_pool_list block_header;
239
 
240
      /* Make the block.  */
241
      block = XNEWVEC (char, pool->block_size);
242
      block_header = (alloc_pool_list) block;
243
      block += align_eight (sizeof (struct alloc_pool_list_def));
244
#ifdef GATHER_STATISTICS
245
      desc->current += pool->block_size;
246
      if (desc->peak < desc->current)
247
        desc->peak = desc->current;
248
#endif
249
 
250
      /* Throw it on the block list.  */
251
      block_header->next = pool->block_list;
252
      pool->block_list = block_header;
253
 
254
      /* Now put the actual block pieces onto the free list.  */
255
      for (i = 0; i < pool->elts_per_block; i++, block += pool->elt_size)
256
      {
257
#ifdef ENABLE_CHECKING
258
        /* Mark the element to be free.  */
259
        ((allocation_object *) block)->id = 0;
260
#endif
261
        header = (alloc_pool_list) USER_PTR_FROM_ALLOCATION_OBJECT_PTR (block);
262
        header->next = pool->free_list;
263
        pool->free_list = header;
264
      }
265
      /* Also update the number of elements we have free/allocated, and
266
         increment the allocated block count.  */
267
      pool->elts_allocated += pool->elts_per_block;
268
      pool->elts_free += pool->elts_per_block;
269
      pool->blocks_allocated += 1;
270
    }
271
 
272
  /* Pull the first free element from the free list, and return it.  */
273
  header = pool->free_list;
274
  pool->free_list = header->next;
275
  pool->elts_free--;
276
 
277
#ifdef ENABLE_CHECKING
278
  /* Set the ID for element.  */
279
  ALLOCATION_OBJECT_PTR_FROM_USER_PTR (header)->id = pool->id;
280
#endif
281
 
282
  return ((void *) header);
283
}
284
 
285
/* Puts PTR back on POOL's free list.  */
286
void
287
pool_free (alloc_pool pool, void *ptr)
288
{
289
  alloc_pool_list header;
290
 
291
  gcc_assert (ptr);
292
 
293
#ifdef ENABLE_CHECKING
294
  memset (ptr, 0xaf, pool->elt_size - offsetof (allocation_object, u.data));
295
 
296
  /* Check whether the PTR was allocated from POOL.  */
297
  gcc_assert (pool->id == ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id);
298
 
299
  /* Mark the element to be free.  */
300
  ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id = 0;
301
#else
302
  /* Check if we free more than we allocated, which is Bad (TM).  */
303
  gcc_assert (pool->elts_free < pool->elts_allocated);
304
#endif
305
 
306
  header = (alloc_pool_list) ptr;
307
  header->next = pool->free_list;
308
  pool->free_list = header;
309
  pool->elts_free++;
310
}
311
/* Output per-alloc_pool statistics.  */
312
#ifdef GATHER_STATISTICS
313
 
314
/* Used to accumulate statistics about alloc_pool sizes.  */
315
struct output_info
316
{
317
  int count;
318
  int size;
319
};
320
 
321
/* Called via htab_traverse.  Output alloc_pool descriptor pointed out by SLOT
322
   and update statistics.  */
323
static int
324
print_statistics (void **slot, void *b)
325
{
326
  struct alloc_pool_descriptor *d = (struct alloc_pool_descriptor *) *slot;
327
  struct output_info *i = (struct output_info *) b;
328
 
329
  if (d->allocated)
330
    {
331
      fprintf (stderr, "%-21s %6d %10d %10d %10d\n", d->name,
332
               d->created, d->allocated, d->peak, d->current);
333
      i->size += d->allocated;
334
      i->count += d->created;
335
    }
336
  return 1;
337
}
338
#endif
339
 
340
/* Output per-alloc_pool memory usage statistics.  */
341
void
342
dump_alloc_pool_statistics (void)
343
{
344
#ifdef GATHER_STATISTICS
345
  struct output_info info;
346
 
347
  if (!alloc_pool_hash)
348
    return;
349
 
350
  fprintf (stderr, "\nAlloc-pool Kind        Pools  Allocated      Peak        Leak\n");
351
  fprintf (stderr, "-------------------------------------------------------------\n");
352
  info.count = 0;
353
  info.size = 0;
354
  htab_traverse (alloc_pool_hash, print_statistics, &info);
355
  fprintf (stderr, "-------------------------------------------------------------\n");
356
  fprintf (stderr, "%-20s %7d %10d\n",
357
           "Total", info.count, info.size);
358
  fprintf (stderr, "-------------------------------------------------------------\n");
359
#endif
360
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.