00001
00002
00003
00004
00005
00006
00007
00008 #undef PRE_INIT_BLOCK
00009 #undef DO_PRE_INIT_BLOCK
00010 #undef INIT_BLOCK
00011 #undef EXIT_BLOCK
00012 #undef BLOCK_ALLOC
00013 #undef LOW_PTR_HASH_ALLOC
00014 #undef PTR_HASH_ALLOC_FIXED
00015 #undef PTR_HASH_ALLOC
00016 #undef COUNT_BLOCK
00017 #undef COUNT_OTHER
00018 #undef DMALLOC_DESCRIBE_BLOCK
00019 #undef BLOCK_ALLOC_HSIZE_SHIFT
00020 #undef MAX_EMPTY_BLOCKS
00021 #undef BLOCK_ALLOC_FILL_PAGES
00022 #undef PTR_HASH_ALLOC_FILL_PAGES
00023 #undef PTR_HASH_ALLOC_FIXED_FILL_PAGES
00024
00025
00026 #define PRE_INIT_BLOCK(X)
00027 #define INIT_BLOCK(X)
00028 #define EXIT_BLOCK(X)
00029 #define COUNT_BLOCK(X)
00030 #define COUNT_OTHER()
00031 #define DMALLOC_DESCRIBE_BLOCK(X)
00032 #define BLOCK_ALLOC_HSIZE_SHIFT 2
00033 #define MAX_EMPTY_BLOCKS 4
00034
00035 #ifndef BLOCK_ALLOC_USED
00036 #define BLOCK_ALLOC_USED DO_IF_DMALLOC(real_used) DO_IF_NOT_DMALLOC(used)
00037 #endif
00038
00039
00040
00041 #define DO_PRE_INIT_BLOCK(X) do { \
00042 DO_IF_DMALLOC(MEMSET((X), 0x55, sizeof(*(X)))); \
00043 PRE_INIT_BLOCK(X); \
00044 } while (0)
00045
00046 #ifndef PIKE_HASH_T
00047 #define PIKE_HASH_T size_t
00048 #endif
00049
00050 #ifdef PIKE_RUN_UNLOCKED
00051 #include "threads.h"
00052
00053
00054 #define BA_UL(X) PIKE_CONCAT(X,_unlocked)
00055 #define BA_STATIC static
00056 #define BA_INLINE INLINE
00057 #else
00058 #define BA_UL(X) X
00059 #define BA_STATIC
00060 #define BA_INLINE
00061 #endif
00062
00063 #define BLOCK_ALLOC_FILL_PAGES(DATA, PAGES) \
00064 BLOCK_ALLOC(DATA, \
00065 ((PIKE_MALLOC_PAGE_SIZE * (PAGES)) \
00066 - PIKE_MALLOC_OVERHEAD - BLOCK_HEADER_SIZE) / \
00067 sizeof (struct DATA))
00068
00069 #define PTR_HASH_ALLOC_FILL_PAGES(DATA, PAGES) \
00070 PTR_HASH_ALLOC(DATA, \
00071 ((PIKE_MALLOC_PAGE_SIZE * (PAGES)) \
00072 - PIKE_MALLOC_OVERHEAD - BLOCK_HEADER_SIZE) / \
00073 sizeof (struct DATA))
00074
00075 #define PTR_HASH_ALLOC_FIXED_FILL_PAGES(DATA, PAGES) \
00076 PTR_HASH_ALLOC_FIXED(DATA, \
00077 ((PIKE_MALLOC_PAGE_SIZE * (PAGES)) \
00078 - PIKE_MALLOC_OVERHEAD - BLOCK_HEADER_SIZE) / \
00079 sizeof (struct DATA))
00080
00081
00082
00083
00084 #ifndef BLOCK_HEADER_SIZE
00085 #define BLOCK_HEADER_SIZE (3 * sizeof (void *) + sizeof (INT32))
00086 #endif
00087
00088 #define BLOCK_ALLOC(DATA,BSIZE) \
00089 \
00090 struct PIKE_CONCAT(DATA,_block) \
00091 { \
00092 struct PIKE_CONCAT(DATA,_block) *next; \
00093 struct PIKE_CONCAT(DATA,_block) *prev; \
00094 struct DATA *PIKE_CONCAT3(free_,DATA,s); \
00095 INT32 used; \
00096 DO_IF_DMALLOC(INT32 real_used;) \
00097 struct DATA x[BSIZE]; \
00098 }; \
00099 struct PIKE_CONCAT(DATA,_context) \
00100 { \
00101 struct PIKE_CONCAT(DATA,_context) *next; \
00102 struct PIKE_CONCAT(DATA, _block) *blocks, *free_blocks; \
00103 INT32 num_empty_blocks; \
00104 }; \
00105 \
00106 static struct PIKE_CONCAT(DATA,_context) *PIKE_CONCAT(DATA,_ctxs)=0; \
00107 static struct PIKE_CONCAT(DATA,_block) *PIKE_CONCAT(DATA,_blocks)=0; \
00108 static struct PIKE_CONCAT(DATA,_block) *PIKE_CONCAT(DATA,_free_blocks)= \
00109 (void*)-1; \
00110 static INT32 PIKE_CONCAT3(num_empty_,DATA,_blocks)=0; \
00111 DO_IF_RUN_UNLOCKED(static PIKE_MUTEX_T PIKE_CONCAT(DATA,_mutex);) \
00112 DO_IF_DMALLOC( \
00113 static struct DATA *PIKE_CONCAT(DATA,s_to_free)[4 * (BSIZE)]; \
00114 static size_t PIKE_CONCAT(DATA,s_to_free_ptr) = 0; \
00115 ) \
00116 \
00117 void PIKE_CONCAT3(new_,DATA,_context)(void) \
00118 { \
00119 struct PIKE_CONCAT(DATA, _context) *ctx = \
00120 (struct PIKE_CONCAT(DATA, _context) *) \
00121 malloc(sizeof(struct PIKE_CONCAT(DATA, _context))); \
00122 if (!ctx) { \
00123 fprintf(stderr, "Fatal: out of memory.\n"); \
00124 exit(17); \
00125 } \
00126 ctx->next = PIKE_CONCAT(DATA, _ctxs); \
00127 PIKE_CONCAT(DATA, _ctxs) = ctx; \
00128 ctx->blocks = PIKE_CONCAT(DATA,_blocks); \
00129 ctx->free_blocks = PIKE_CONCAT(DATA,_free_blocks); \
00130 ctx->num_empty_blocks = PIKE_CONCAT3(num_empty_,DATA,_blocks); \
00131 PIKE_CONCAT(DATA,_blocks) = 0; \
00132 PIKE_CONCAT(DATA,_free_blocks) = 0; \
00133 PIKE_CONCAT3(num_empty_,DATA,_blocks) = 0; \
00134 } \
00135 \
00136 static void PIKE_CONCAT(alloc_more_,DATA)(void) \
00137 { \
00138 struct PIKE_CONCAT(DATA,_block) *n; \
00139 size_t e; \
00140 n=(struct PIKE_CONCAT(DATA,_block) *) \
00141 malloc(sizeof(struct PIKE_CONCAT(DATA,_block))); \
00142 if(!n) \
00143 { \
00144 fprintf(stderr,"Fatal: out of memory.\n"); \
00145 exit(17); \
00146 } \
00147 if((n->next=PIKE_CONCAT(DATA,_blocks))) \
00148 n->next->prev=n; \
00149 n->prev=NULL; \
00150 n->used=0; \
00151 DO_IF_DMALLOC(n->real_used = 0); \
00152 PIKE_CONCAT(DATA,_blocks)=n; \
00153 PIKE_CONCAT(DATA,_free_blocks)=n; \
00154 \
00155 DO_PRE_INIT_BLOCK( n->x ); \
00156 n->x[0].BLOCK_ALLOC_NEXT=NULL; \
00157 for(e=1;e<(BSIZE);e++) \
00158 { \
00159 DO_PRE_INIT_BLOCK( (n->x+e) ); \
00160 n->x[e].BLOCK_ALLOC_NEXT=(void *)&n->x[e-1]; \
00161 } \
00162 n->PIKE_CONCAT3(free_,DATA,s)=&n->x[(BSIZE)-1]; \
00163 \
00164 PIKE_MEM_NA(n->x); \
00165 } \
00166 \
00167 BA_STATIC BA_INLINE struct DATA *BA_UL(PIKE_CONCAT(alloc_,DATA))(void) \
00168 { \
00169 struct DATA *tmp; \
00170 struct PIKE_CONCAT(DATA,_block) *blk; \
00171 \
00172 if(!(blk = PIKE_CONCAT(DATA,_free_blocks))) { \
00173 PIKE_CONCAT(alloc_more_,DATA)(); \
00174 blk = PIKE_CONCAT(DATA,_blocks); \
00175 blk->BLOCK_ALLOC_USED++; \
00176 } \
00177 DO_IF_DEBUG( \
00178 else if (PIKE_CONCAT(DATA,_free_blocks) == (void *)-1) \
00179 Pike_fatal("Block alloc " #DATA " not initialized.\n"); \
00180 ) \
00181 else if(!blk->BLOCK_ALLOC_USED++) \
00182 --PIKE_CONCAT3(num_empty_,DATA,_blocks); \
00183 DO_IF_DMALLOC(blk->used++); \
00184 \
00185 tmp = blk->PIKE_CONCAT3(free_,DATA,s); \
00186 \
00187 PIKE_MEM_RW(*tmp); \
00188 if(!(blk->PIKE_CONCAT3(free_,DATA,s) = (void *)tmp->BLOCK_ALLOC_NEXT)) \
00189 PIKE_CONCAT(DATA,_free_blocks) = blk->prev; \
00190 DO_IF_DMALLOC( \
00191 dmalloc_unregister(tmp, 1); \
00192 dmalloc_register(tmp,sizeof(struct DATA), DMALLOC_LOCATION()); \
00193 ) \
00194 \
00195 PIKE_MEM_WO(*tmp); \
00196 INIT_BLOCK(tmp); \
00197 return tmp; \
00198 } \
00199 \
00200 DO_IF_RUN_UNLOCKED( \
00201 struct DATA *PIKE_CONCAT(alloc_,DATA)(void) \
00202 { \
00203 struct DATA *ret; \
00204 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00205 ret=PIKE_CONCAT3(alloc_,DATA,_unlocked)(); \
00206 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00207 return ret; \
00208 }) \
00209 \
00210 DO_IF_DMALLOC( \
00211 static void PIKE_CONCAT(check_free_,DATA)(struct DATA *d) \
00212 { \
00213 struct PIKE_CONCAT(DATA,_block) *tmp; \
00214 struct PIKE_CONCAT(DATA,_context) *ctx = PIKE_CONCAT(DATA,_ctxs); \
00215 for(tmp=PIKE_CONCAT(DATA,_blocks);tmp;tmp=tmp->next) \
00216 { \
00217 if( (char *)d < (char *)tmp) continue; \
00218 if( (char *)d >= (char *)(tmp->x+(BSIZE))) continue; \
00219 if ((char *) d - (char *) tmp->x != \
00220 (d - tmp->x) * (ptrdiff_t) sizeof (struct DATA)) break; \
00221 return; \
00222 } \
00223 while (ctx) { \
00224 for(tmp=ctx->blocks; tmp; tmp=tmp->next) \
00225 { \
00226 if( (char *)d < (char *)tmp) continue; \
00227 if( (char *)d >= (char *)(tmp->x+(BSIZE))) continue; \
00228 if ((char *) d - (char *) tmp->x != \
00229 (d - tmp->x) * (ptrdiff_t) sizeof (struct DATA)) break; \
00230 return; \
00231 } \
00232 ctx = ctx->next; \
00233 } \
00234 Pike_fatal("really_free_%s called on non-block_alloc region (%p).\n", \
00235 #DATA, d); \
00236 } \
00237 \
00238 static void PIKE_CONCAT (dmalloc_describe_, DATA) (struct DATA *d) \
00239 { \
00240 DMALLOC_DESCRIBE_BLOCK (d); \
00241 } \
00242 ) \
00243 \
00244 void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \
00245 { \
00246 struct PIKE_CONCAT(DATA,_block) *blk; \
00247 \
00248 EXIT_BLOCK(d); \
00249 \
00250 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00251 \
00252 DO_IF_DMALLOC({ \
00253 struct DATA *d2; \
00254 PIKE_CONCAT(check_free_,DATA)(d); \
00255 dmalloc_mark_as_free(d, 1); \
00256 blk = PIKE_CONCAT(DATA,_free_blocks); \
00257 if(blk == NULL || (char *)d < (char *)blk || \
00258 (char *)d >= (char *)(blk->x+(BSIZE))) { \
00259 blk = PIKE_CONCAT(DATA,_blocks); \
00260 while((char *)d < (char *)blk || \
00261 (char *)d >= (char *)(blk->x+(BSIZE))) \
00262 blk = blk->next; \
00263 } \
00264 blk->used--; \
00265 PIKE_MEM_NA(*d); \
00266 d2 = PIKE_CONCAT(DATA,s_to_free)[PIKE_CONCAT(DATA,s_to_free_ptr)]; \
00267 PIKE_CONCAT(DATA,s_to_free)[PIKE_CONCAT(DATA,s_to_free_ptr)] = d; \
00268 PIKE_CONCAT(DATA,s_to_free_ptr) = \
00269 (PIKE_CONCAT(DATA,s_to_free_ptr) + 1) % \
00270 NELEM(PIKE_CONCAT(DATA,s_to_free)); \
00271 if ((d = d2)) \
00272 PIKE_MEM_WO(*d); \
00273 else \
00274 return; \
00275 }); \
00276 \
00277 blk = PIKE_CONCAT(DATA,_free_blocks); \
00278 if(blk == NULL || (char *)d < (char *)blk || \
00279 (char *)d >= (char *)(blk->x+(BSIZE))) { \
00280 blk = PIKE_CONCAT(DATA,_blocks); \
00281 if((char *)d < (char *)blk || \
00282 (char *)d >= (char *)(blk->x+(BSIZE))) { \
00283 do { \
00284 blk = blk->next; \
00285 } while((char *)d < (char *)blk || \
00286 (char *)d >= (char *)(blk->x+(BSIZE))); \
00287 if(blk == PIKE_CONCAT(DATA,_free_blocks)) \
00288 PIKE_CONCAT(DATA,_free_blocks) = blk->prev; \
00289 blk->prev->next = blk->next; \
00290 if(blk->next) \
00291 blk->next->prev = blk->prev; \
00292 blk->prev = NULL; \
00293 blk->next = PIKE_CONCAT(DATA,_blocks); \
00294 blk->next->prev = blk; \
00295 PIKE_CONCAT(DATA,_blocks) = blk; \
00296 } \
00297 if(PIKE_CONCAT(DATA,_free_blocks) == NULL) \
00298 PIKE_CONCAT(DATA,_free_blocks) = blk; \
00299 } \
00300 \
00301 DO_PRE_INIT_BLOCK(d); \
00302 d->BLOCK_ALLOC_NEXT = (void *)blk->PIKE_CONCAT3(free_,DATA,s); \
00303 blk->PIKE_CONCAT3(free_,DATA,s)=d; \
00304 \
00305 PIKE_MEM_NA(*d); \
00306 \
00307 if(!--blk->BLOCK_ALLOC_USED && \
00308 ++PIKE_CONCAT3(num_empty_,DATA,_blocks) > MAX_EMPTY_BLOCKS) { \
00309 if(blk == PIKE_CONCAT(DATA,_free_blocks)) { \
00310 if((blk->prev->next = blk->next)) \
00311 blk->next->prev = blk->prev; \
00312 PIKE_CONCAT(DATA,_free_blocks) = blk->prev; \
00313 } else { \
00314 PIKE_CONCAT(DATA,_blocks) = blk->next; \
00315 blk->next->prev = NULL; \
00316 } \
00317 \
00318 DO_IF_DMALLOC({ \
00319 size_t i; \
00320 for (i = 0; i < (BSIZE); i++) { \
00321 dmalloc_check_block_free( \
00322 blk->x + i, DMALLOC_LOCATION(), #DATA, \
00323 (describe_block_fn *) PIKE_CONCAT (dmalloc_describe_, DATA)); \
00324 dmalloc_unregister(blk->x + i, 1); \
00325 } \
00326 }); \
00327 \
00328 \
00329 PIKE_MEM_RW(*blk); \
00330 free(blk); \
00331 --PIKE_CONCAT3(num_empty_,DATA,_blocks); \
00332 } \
00333 \
00334 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00335 } \
00336 \
00337 static void PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(void) \
00338 { \
00339 struct PIKE_CONCAT(DATA,_block) *tmp; \
00340 DO_IF_DMALLOC( \
00341 MEMSET(PIKE_CONCAT(DATA,s_to_free), 0, sizeof(PIKE_CONCAT(DATA,s_to_free))); \
00342 for(tmp=PIKE_CONCAT(DATA,_blocks);tmp;tmp=tmp->next) \
00343 { \
00344 size_t tmp2; \
00345 for(tmp2=0;tmp2<(BSIZE);tmp2++) \
00346 { \
00347 dmalloc_check_block_free( \
00348 tmp->x+tmp2, DMALLOC_LOCATION(), #DATA, \
00349 (describe_block_fn *) PIKE_CONCAT (dmalloc_describe_, DATA)); \
00350 dmalloc_unregister(tmp->x+tmp2, 1); \
00351 } \
00352 } \
00353 ) \
00354 while((tmp=PIKE_CONCAT(DATA,_blocks))) \
00355 { \
00356 PIKE_CONCAT(DATA,_blocks)=tmp->next; \
00357 \
00358 PIKE_MEM_RW(tmp->x); \
00359 free((char *)tmp); \
00360 } \
00361 if (PIKE_CONCAT(DATA,_ctxs)) { \
00362 struct PIKE_CONCAT(DATA, _context) *ctx = PIKE_CONCAT(DATA,_ctxs); \
00363 PIKE_CONCAT(DATA,_blocks)=ctx->blocks; \
00364 PIKE_CONCAT(DATA,_free_blocks)=ctx->free_blocks; \
00365 PIKE_CONCAT3(num_empty_,DATA,_blocks)=ctx->num_empty_blocks; \
00366 PIKE_CONCAT(DATA,_ctxs) = ctx->next; \
00367 free(ctx); \
00368 } else { \
00369 PIKE_CONCAT(DATA,_blocks)=0; \
00370 PIKE_CONCAT(DATA,_free_blocks)=0; \
00371 PIKE_CONCAT3(num_empty_,DATA,_blocks)=0; \
00372 } \
00373 } \
00374 \
00375 void PIKE_CONCAT3(free_all_,DATA,_blocks)(void) \
00376 { \
00377 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00378 PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(); \
00379 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00380 } \
00381 \
00382 void PIKE_CONCAT3(count_memory_in_,DATA,s)(INT32 *num_, INT32 *size_) \
00383 { \
00384 INT32 num=0, size=0; \
00385 struct PIKE_CONCAT(DATA,_block) *tmp; \
00386 struct PIKE_CONCAT(DATA,_context) *ctx = PIKE_CONCAT(DATA,_ctxs); \
00387 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00388 for(tmp=PIKE_CONCAT(DATA,_blocks);tmp;tmp=tmp->next) \
00389 { \
00390 size+=sizeof(struct PIKE_CONCAT(DATA,_block)); \
00391 num+=tmp->used; \
00392 COUNT_BLOCK(tmp); \
00393 } \
00394 while (ctx) { \
00395 for(tmp=ctx->blocks;tmp;tmp=tmp->next) \
00396 { \
00397 size+=sizeof(struct PIKE_CONCAT(DATA,_block)); \
00398 num+=tmp->used; \
00399 COUNT_BLOCK(tmp); \
00400 } \
00401 ctx = ctx->next; \
00402 } \
00403 COUNT_OTHER(); \
00404 *num_=num; \
00405 *size_=size; \
00406 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00407 } \
00408 \
00409 \
00410 void PIKE_CONCAT3(init_,DATA,_blocks)(void) \
00411 { \
00412 \
00413 DO_IF_RUN_UNLOCKED(mt_init(&PIKE_CONCAT(DATA,_mutex))); \
00414 PIKE_CONCAT(DATA,_free_blocks)=0; \
00415 }
00416
00417
00418
00419 #define LOW_PTR_HASH_ALLOC(DATA,BSIZE) \
00420 \
00421 BLOCK_ALLOC(DATA,BSIZE) \
00422 \
00423 struct DATA **PIKE_CONCAT(DATA,_hash_table)=0; \
00424 size_t PIKE_CONCAT(DATA,_hash_table_size)=0; \
00425 size_t PIKE_CONCAT(DATA,_hash_table_magnitude)=0; \
00426 static size_t PIKE_CONCAT(num_,DATA)=0; \
00427 \
00428 static INLINE struct DATA * \
00429 PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(void *ptr, \
00430 PIKE_HASH_T hval) \
00431 { \
00432 struct DATA *p,**pp; \
00433 p=PIKE_CONCAT(DATA,_hash_table)[hval]; \
00434 if(!p || p->PTR_HASH_ALLOC_DATA == ptr) \
00435 { \
00436 return p; \
00437 } \
00438 while((p=*(pp=&p->BLOCK_ALLOC_NEXT))) \
00439 { \
00440 if(p->PTR_HASH_ALLOC_DATA==ptr) \
00441 { \
00442 *pp=p->BLOCK_ALLOC_NEXT; \
00443 p->BLOCK_ALLOC_NEXT=PIKE_CONCAT(DATA,_hash_table)[hval]; \
00444 PIKE_CONCAT(DATA,_hash_table)[hval]=p; \
00445 return p; \
00446 } \
00447 } \
00448 return 0; \
00449 } \
00450 \
00451 struct DATA *PIKE_CONCAT(find_,DATA)(void *ptr) \
00452 { \
00453 struct DATA *p; \
00454 PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
00455 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00456 if(!PIKE_CONCAT(DATA,_hash_table_size)) { \
00457 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00458 return 0; \
00459 } \
00460 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00461 p=PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(ptr, hval); \
00462 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00463 return p; \
00464 } \
00465 \
00466 static INLINE struct DATA * \
00467 PIKE_CONCAT3(just_find_,DATA,_unlocked)(void *ptr, \
00468 PIKE_HASH_T hval) \
00469 { \
00470 struct DATA *p,**pp; \
00471 p=PIKE_CONCAT(DATA,_hash_table)[hval]; \
00472 if(!p || p->PTR_HASH_ALLOC_DATA == ptr) \
00473 { \
00474 return p; \
00475 } \
00476 while((p=p->BLOCK_ALLOC_NEXT)) \
00477 { \
00478 if(p->PTR_HASH_ALLOC_DATA==ptr) return p; \
00479 } \
00480 return 0; \
00481 } \
00482 \
00483 static struct DATA *PIKE_CONCAT(just_find_,DATA)(void *ptr) \
00484 { \
00485 struct DATA *p; \
00486 PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
00487 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00488 if(!PIKE_CONCAT(DATA,_hash_table_size)) { \
00489 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00490 return 0; \
00491 } \
00492 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00493 p=PIKE_CONCAT3(just_find_,DATA,_unlocked)(ptr, hval); \
00494 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00495 return p; \
00496 } \
00497 \
00498 \
00499 \
00500 struct DATA *PIKE_CONCAT(make_,DATA)(void *ptr) \
00501 { \
00502 struct DATA *p; \
00503 PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
00504 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00505 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00506 p=PIKE_CONCAT3(make_,DATA,_unlocked)(ptr,hval); \
00507 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00508 return p; \
00509 } \
00510 \
00511 struct DATA *PIKE_CONCAT(get_,DATA)(void *ptr) \
00512 { \
00513 struct DATA *p; \
00514 PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
00515 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00516 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00517 if(!(p=PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(ptr, hval))) \
00518 p=PIKE_CONCAT3(make_,DATA,_unlocked)(ptr, hval); \
00519 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00520 return p; \
00521 } \
00522 \
00523 int PIKE_CONCAT3(check_,DATA,_semafore)(void *ptr) \
00524 { \
00525 struct DATA *p; \
00526 PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
00527 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00528 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00529 if((p=PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(ptr, hval))) \
00530 { \
00531 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00532 return 0; \
00533 } \
00534 \
00535 PIKE_CONCAT3(make_,DATA,_unlocked)(ptr, hval); \
00536 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00537 return 1; \
00538 } \
00539 \
00540 void PIKE_CONCAT(move_,DATA)(struct DATA *block, void *new_ptr) \
00541 { \
00542 PIKE_HASH_T hval = \
00543 (PIKE_HASH_T)PTR_TO_INT(block->PTR_HASH_ALLOC_DATA); \
00544 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00545 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00546 if (!PIKE_CONCAT3(really_low_find_,DATA,_unlocked)( \
00547 block->PTR_HASH_ALLOC_DATA, hval)) \
00548 Pike_fatal("The block to move wasn't found.\n"); \
00549 DO_IF_DEBUG( \
00550 if (PIKE_CONCAT(DATA,_hash_table)[hval] != block) \
00551 Pike_fatal("Expected the block to be at the top of the hash chain.\n"); \
00552 ); \
00553 PIKE_CONCAT(DATA,_hash_table)[hval] = block->BLOCK_ALLOC_NEXT; \
00554 block->PTR_HASH_ALLOC_DATA = new_ptr; \
00555 hval = (PIKE_HASH_T)PTR_TO_INT(new_ptr) % \
00556 (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00557 block->BLOCK_ALLOC_NEXT = PIKE_CONCAT(DATA,_hash_table)[hval]; \
00558 PIKE_CONCAT(DATA,_hash_table)[hval] = block; \
00559 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00560 } \
00561 \
00562 int PIKE_CONCAT(remove_,DATA)(void *ptr) \
00563 { \
00564 struct DATA *p; \
00565 PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
00566 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00567 if(!PIKE_CONCAT(DATA,_hash_table)) \
00568 { \
00569 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00570 return 0; \
00571 } \
00572 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00573 if((p=PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(ptr, hval))) \
00574 { \
00575 PIKE_CONCAT(num_,DATA)--; \
00576 DO_IF_DEBUG( if(PIKE_CONCAT(DATA,_hash_table)[hval]!=p) \
00577 Pike_fatal("GAOssdf\n"); ); \
00578 PIKE_CONCAT(DATA,_hash_table)[hval]=p->BLOCK_ALLOC_NEXT; \
00579 BA_UL(PIKE_CONCAT(really_free_,DATA))(p); \
00580 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00581 return 1; \
00582 } \
00583 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00584 return 0; \
00585 } \
00586 \
00587 void PIKE_CONCAT3(low_init_,DATA,_hash)(size_t size) \
00588 { \
00589 extern const INT32 hashprimes[32]; \
00590 extern int my_log2(size_t x); \
00591 PIKE_CONCAT3(init_,DATA,_blocks)(); \
00592 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00593 PIKE_CONCAT(DATA,_hash_table_size)= \
00594 hashprimes[PIKE_CONCAT(DATA,_hash_table_magnitude)=my_log2(size)]; \
00595 \
00596 PIKE_CONCAT(DATA,_hash_table)=(struct DATA **) \
00597 malloc(sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size)); \
00598 if(!PIKE_CONCAT(DATA,_hash_table)) \
00599 { \
00600 fprintf(stderr,"Fatal: out of memory.\n"); \
00601 exit(17); \
00602 } \
00603 MEMSET(PIKE_CONCAT(DATA,_hash_table),0, \
00604 sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size)); \
00605 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00606 } \
00607 \
00608 \
00609 void PIKE_CONCAT3(init_,DATA,_hash)(void) \
00610 { \
00611 PIKE_CONCAT3(low_init_,DATA,_hash)(BSIZE); \
00612 } \
00613 \
00614 void PIKE_CONCAT3(exit_,DATA,_hash)(void) \
00615 { \
00616 DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
00617 PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(); \
00618 free(PIKE_CONCAT(DATA,_hash_table)); \
00619 PIKE_CONCAT(DATA,_hash_table)=0; \
00620 PIKE_CONCAT(num_,DATA)=0; \
00621 DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
00622 }
00623
00624 #define PTR_HASH_ALLOC_FIXED(DATA,BSIZE) \
00625 struct DATA *PIKE_CONCAT3(make_,DATA,_unlocked)(void *ptr, PIKE_HASH_T hval);\
00626 LOW_PTR_HASH_ALLOC(DATA,BSIZE) \
00627 \
00628 struct DATA *PIKE_CONCAT3(make_,DATA,_unlocked)(void *ptr, PIKE_HASH_T hval) \
00629 { \
00630 struct DATA *p; \
00631 \
00632 DO_IF_DEBUG( if(!PIKE_CONCAT(DATA,_hash_table)) \
00633 Pike_fatal("Hash table error!\n"); ) \
00634 PIKE_CONCAT(num_,DATA)++; \
00635 \
00636 p=BA_UL(PIKE_CONCAT(alloc_,DATA))(); \
00637 p->PTR_HASH_ALLOC_DATA=ptr; \
00638 p->BLOCK_ALLOC_NEXT=PIKE_CONCAT(DATA,_hash_table)[hval]; \
00639 PIKE_CONCAT(DATA,_hash_table)[hval]=p; \
00640 return p; \
00641 }
00642
00643
00644 #define PTR_HASH_ALLOC(DATA,BSIZE) \
00645 struct DATA *PIKE_CONCAT3(make_,DATA,_unlocked)(void *ptr, \
00646 PIKE_HASH_T hval); \
00647 LOW_PTR_HASH_ALLOC(DATA,BSIZE) \
00648 \
00649 static void PIKE_CONCAT(DATA,_rehash)(void) \
00650 { \
00651 \
00652 extern const INT32 hashprimes[32]; \
00653 struct DATA **old_hash; \
00654 struct DATA *p; \
00655 PIKE_HASH_T hval; \
00656 size_t e; \
00657 \
00658 old_hash= PIKE_CONCAT(DATA,_hash_table); \
00659 e=PIKE_CONCAT(DATA,_hash_table_size); \
00660 \
00661 PIKE_CONCAT(DATA,_hash_table_magnitude)++; \
00662 PIKE_CONCAT(DATA,_hash_table_size)= \
00663 hashprimes[PIKE_CONCAT(DATA,_hash_table_magnitude)]; \
00664 if((PIKE_CONCAT(DATA,_hash_table)=(struct DATA **) \
00665 malloc(PIKE_CONCAT(DATA,_hash_table_size)* \
00666 sizeof(struct DATA *)))) \
00667 { \
00668 MEMSET(PIKE_CONCAT(DATA,_hash_table),0, \
00669 sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size)); \
00670 while(e-- > 0) \
00671 { \
00672 while((p=old_hash[e])) \
00673 { \
00674 old_hash[e]=p->BLOCK_ALLOC_NEXT; \
00675 hval = (PIKE_HASH_T)PTR_TO_INT(p->PTR_HASH_ALLOC_DATA); \
00676 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00677 p->BLOCK_ALLOC_NEXT=PIKE_CONCAT(DATA,_hash_table)[hval]; \
00678 PIKE_CONCAT(DATA,_hash_table)[hval]=p; \
00679 } \
00680 } \
00681 free((char *)old_hash); \
00682 }else{ \
00683 PIKE_CONCAT(DATA,_hash_table)=old_hash; \
00684 PIKE_CONCAT(DATA,_hash_table_size)=e; \
00685 } \
00686 } \
00687 \
00688 struct DATA *PIKE_CONCAT3(make_,DATA,_unlocked)(void *ptr, \
00689 PIKE_HASH_T hval) \
00690 { \
00691 struct DATA *p; \
00692 \
00693 DO_IF_DEBUG( if(!PIKE_CONCAT(DATA,_hash_table)) \
00694 Pike_fatal("Hash table error!\n"); ) \
00695 PIKE_CONCAT(num_,DATA)++; \
00696 \
00697 if(( PIKE_CONCAT(num_,DATA)>>BLOCK_ALLOC_HSIZE_SHIFT ) >= \
00698 PIKE_CONCAT(DATA,_hash_table_size)) \
00699 { \
00700 PIKE_CONCAT(DATA,_rehash)(); \
00701 hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
00702 hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
00703 } \
00704 \
00705 p=BA_UL(PIKE_CONCAT(alloc_,DATA))(); \
00706 p->PTR_HASH_ALLOC_DATA=ptr; \
00707 p->BLOCK_ALLOC_NEXT=PIKE_CONCAT(DATA,_hash_table)[hval]; \
00708 PIKE_CONCAT(DATA,_hash_table)[hval]=p; \
00709 return p; \
00710 }