00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "alloc-pool.h"
00026 #include "hashtab.h"
00027
00028 #define align_eight(x) (((x+7) >> 3) << 3)
00029
00030
00031 typedef struct allocation_object_def
00032 {
00033 #ifdef ENABLE_CHECKING
00034
00035 ALLOC_POOL_ID_TYPE id;
00036 #endif
00037
00038 union
00039 {
00040
00041 char data[1];
00042
00043
00044
00045
00046 char *align_p;
00047 HOST_WIDEST_INT align_i;
00048 long double align_ld;
00049 } u;
00050 } allocation_object;
00051
00052
00053 #define ALLOCATION_OBJECT_PTR_FROM_USER_PTR(X) \
00054 ((allocation_object *) (((char *) (X)) \
00055 - offsetof (allocation_object, u.data)))
00056
00057
00058 #define USER_PTR_FROM_ALLOCATION_OBJECT_PTR(X) \
00059 ((void *) (((allocation_object *) (X))->u.data))
00060
00061 #ifdef ENABLE_CHECKING
00062
00063 static ALLOC_POOL_ID_TYPE last_id;
00064 #endif
00065
00066 #ifdef GATHER_STATISTICS
00067
00068
00069 struct alloc_pool_descriptor
00070 {
00071 const char *name;
00072 int allocated;
00073 int created;
00074 int peak;
00075 int current;
00076 };
00077
00078
00079 static htab_t alloc_pool_hash;
00080
00081
00082 static hashval_t
00083 hash_descriptor (const void *p)
00084 {
00085 const struct alloc_pool_descriptor *d = p;
00086 return htab_hash_pointer (d->name);
00087 }
00088 static int
00089 eq_descriptor (const void *p1, const void *p2)
00090 {
00091 const struct alloc_pool_descriptor *d = p1;
00092 return d->name == p2;
00093 }
00094
00095
00096 static struct alloc_pool_descriptor *
00097 alloc_pool_descriptor (const char *name)
00098 {
00099 struct alloc_pool_descriptor **slot;
00100
00101 if (!alloc_pool_hash)
00102 alloc_pool_hash = htab_create (10, hash_descriptor, eq_descriptor, NULL);
00103
00104 slot = (struct alloc_pool_descriptor **)
00105 htab_find_slot_with_hash (alloc_pool_hash, name,
00106 htab_hash_pointer (name),
00107 1);
00108 if (*slot)
00109 return *slot;
00110 *slot = xcalloc (sizeof (**slot), 1);
00111 (*slot)->name = name;
00112 return *slot;
00113 }
00114 #endif
00115
00116
00117
00118
00119 alloc_pool
00120 create_alloc_pool (const char *name, size_t size, size_t num)
00121 {
00122 alloc_pool pool;
00123 size_t pool_size, header_size;
00124 #ifdef GATHER_STATISTICS
00125 struct alloc_pool_descriptor *desc;
00126 #endif
00127
00128 gcc_assert (name);
00129
00130
00131 if (size < sizeof (alloc_pool_list))
00132 size = sizeof (alloc_pool_list);
00133
00134
00135 size = align_eight (size);
00136
00137 #ifdef ENABLE_CHECKING
00138
00139 size += offsetof (allocation_object, u.data);
00140 #endif
00141
00142
00143 gcc_assert (num);
00144
00145
00146 pool_size = sizeof (struct alloc_pool_def);
00147
00148
00149 pool = xmalloc (pool_size);
00150
00151
00152 pool->name = name;
00153 #ifdef GATHER_STATISTICS
00154 desc = alloc_pool_descriptor (name);
00155 desc->created++;
00156 #endif
00157 pool->elt_size = size;
00158 pool->elts_per_block = num;
00159
00160
00161 header_size = align_eight (sizeof (struct alloc_pool_list_def));
00162
00163 pool->block_size = (size * num) + header_size;
00164 pool->free_list = NULL;
00165 pool->elts_allocated = 0;
00166 pool->elts_free = 0;
00167 pool->blocks_allocated = 0;
00168 pool->block_list = NULL;
00169
00170 #ifdef ENABLE_CHECKING
00171
00172
00173 last_id++;
00174 if (last_id == 0)
00175 last_id++;
00176
00177 pool->id = last_id;
00178 #endif
00179
00180 return (pool);
00181 }
00182
00183
00184 void
00185 free_alloc_pool (alloc_pool pool)
00186 {
00187 alloc_pool_list block, next_block;
00188 #ifdef GATHER_STATISTICS
00189 struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name);
00190 #endif
00191
00192 gcc_assert (pool);
00193
00194
00195 for (block = pool->block_list; block != NULL; block = next_block)
00196 {
00197 next_block = block->next;
00198 free (block);
00199 #ifdef GATHER_STATISTICS
00200 desc->current -= pool->block_size;
00201 #endif
00202 }
00203 #ifdef ENABLE_CHECKING
00204 memset (pool, 0xaf, sizeof (*pool));
00205 #endif
00206
00207 free (pool);
00208 }
00209
00210
00211 void *
00212 pool_alloc (alloc_pool pool)
00213 {
00214 alloc_pool_list header;
00215 char *block;
00216 #ifdef GATHER_STATISTICS
00217 struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name);
00218
00219 desc->allocated+=pool->elt_size;
00220 #endif
00221
00222 gcc_assert (pool);
00223
00224
00225 if (!pool->free_list)
00226 {
00227 size_t i;
00228 alloc_pool_list block_header;
00229
00230
00231 block = xmalloc (pool->block_size);
00232 block_header = (alloc_pool_list) block;
00233 block += align_eight (sizeof (struct alloc_pool_list_def));
00234 #ifdef GATHER_STATISTICS
00235 desc->current += pool->block_size;
00236 if (desc->peak < desc->current)
00237 desc->peak = desc->current;
00238 #endif
00239
00240
00241 block_header->next = pool->block_list;
00242 pool->block_list = block_header;
00243
00244
00245 for (i = 0; i < pool->elts_per_block; i++, block += pool->elt_size)
00246 {
00247 #ifdef ENABLE_CHECKING
00248
00249 ((allocation_object *) block)->id = 0;
00250 #endif
00251 header = (alloc_pool_list) USER_PTR_FROM_ALLOCATION_OBJECT_PTR (block);
00252 header->next = pool->free_list;
00253 pool->free_list = header;
00254 }
00255
00256
00257 pool->elts_allocated += pool->elts_per_block;
00258 pool->elts_free += pool->elts_per_block;
00259 pool->blocks_allocated += 1;
00260 }
00261
00262
00263 header = pool->free_list;
00264 pool->free_list = header->next;
00265 pool->elts_free--;
00266
00267 #ifdef ENABLE_CHECKING
00268
00269 ALLOCATION_OBJECT_PTR_FROM_USER_PTR (header)->id = pool->id;
00270 #endif
00271
00272 return ((void *) header);
00273 }
00274
00275
00276 void
00277 pool_free (alloc_pool pool, void *ptr)
00278 {
00279 alloc_pool_list header;
00280
00281 gcc_assert (ptr);
00282
00283 #ifdef ENABLE_CHECKING
00284 memset (ptr, 0xaf, pool->elt_size - offsetof (allocation_object, u.data));
00285
00286
00287 gcc_assert (pool->id == ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id);
00288
00289
00290 ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id = 0;
00291 #else
00292
00293 gcc_assert (pool->elts_free < pool->elts_allocated);
00294 #endif
00295
00296 header = (alloc_pool_list) ptr;
00297 header->next = pool->free_list;
00298 pool->free_list = header;
00299 pool->elts_free++;
00300 }
00301
00302 #ifdef GATHER_STATISTICS
00303
00304
00305 struct output_info
00306 {
00307 int count;
00308 int size;
00309 };
00310
00311
00312
00313 static int
00314 print_statistics (void **slot, void *b)
00315 {
00316 struct alloc_pool_descriptor *d = (struct alloc_pool_descriptor *) *slot;
00317 struct output_info *i = (struct output_info *) b;
00318
00319 if (d->allocated)
00320 {
00321 fprintf (stderr, "%-21s %6d %10d %10d %10d\n", d->name,
00322 d->created, d->allocated, d->peak, d->current);
00323 i->size += d->allocated;
00324 i->count += d->created;
00325 }
00326 return 1;
00327 }
00328 #endif
00329
00330
00331 void dump_alloc_pool_statistics (void)
00332 {
00333 #ifdef GATHER_STATISTICS
00334 struct output_info info;
00335
00336 fprintf (stderr, "\nAlloc-pool Kind Pools Allocated Peak Leak\n");
00337 fprintf (stderr, "-------------------------------------------------------------\n");
00338 info.count = 0;
00339 info.size = 0;
00340 htab_traverse (alloc_pool_hash, print_statistics, &info);
00341 fprintf (stderr, "-------------------------------------------------------------\n");
00342 fprintf (stderr, "%-20s %7d %10d\n",
00343 "Total", info.count, info.size);
00344 fprintf (stderr, "-------------------------------------------------------------\n");
00345 #endif
00346 }