Main Page | Class List | Directories | File List | Class Members | File Members

block_alloc.h

Go to the documentation of this file.
00001 /*
00002 || This file is part of Pike. For copyright information see COPYRIGHT.
00003 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
00004 || for more information.
00005 || $Id: block_alloc.h,v 1.77 2005/04/09 10:54:25 grubba Exp $
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 /* Note: The block_alloc mutex is held while PRE_INIT_BLOCK runs. */
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 /* Invalidate the block as far as possible if running with dmalloc.
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 /* !PIKE_HASH_T */
00049 
00050 #ifdef PIKE_RUN_UNLOCKED
00051 #include "threads.h"
00052 
00053 /* Block Alloc UnLocked */
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 /* Size of the members in the block struct below that don't contain
00082  * the payload data (i.e. that aren't x). This can be used in BSIZE to
00083  * make the block fit within a page. */
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   /* Mark the new blocks as unavailable for now... */                   \
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   /* Mark the new block as available. */                                \
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   /* Mark the new block as available but uninitialized. */              \
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   /* Mark block as unavailable. */                                      \
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     /* Mark meta-block as available, since libc will mess with it. */   \
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     /* Mark meta-block as available, since libc will mess with it. */   \
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 /*  DO_IF_RUN_UNLOCKED(mt_init_recursive(&PIKE_CONCAT(DATA,_mutex)));*/ \
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   /* Time to re-hash */                                                      \
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 }

Generated on Fri Jul 22 23:44:24 2005 for Pike by  doxygen 1.3.9.1