e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information.
f757d02008-05-01Martin Stjernholm || $Id: block_alloc.h,v 1.85 2008/05/01 21:44:32 mast Exp $
e576bb2002-10-11Martin Nilsson */
1b10db2002-10-08Martin Nilsson 
4218011999-01-31Fredrik Hübinette (Hubbe) #undef PRE_INIT_BLOCK
f588b42003-03-15Henrik Grubbström (Grubba) #undef DO_PRE_INIT_BLOCK
4218011999-01-31Fredrik Hübinette (Hubbe) #undef INIT_BLOCK #undef EXIT_BLOCK #undef BLOCK_ALLOC
afbc722001-09-06Fredrik Hübinette (Hubbe) #undef LOW_PTR_HASH_ALLOC #undef PTR_HASH_ALLOC_FIXED
fc2c831999-04-01Fredrik Hübinette (Hubbe) #undef PTR_HASH_ALLOC
cfa7d82000-01-27Fredrik Hübinette (Hubbe) #undef COUNT_BLOCK #undef COUNT_OTHER
886a8e2004-04-03Martin Stjernholm #undef DMALLOC_DESCRIBE_BLOCK
7d63aa2001-11-08Fredrik Hübinette (Hubbe) #undef BLOCK_ALLOC_HSIZE_SHIFT
379b682002-09-30Marcus Comstedt #undef MAX_EMPTY_BLOCKS
db1aac2002-11-24Martin Stjernholm #undef BLOCK_ALLOC_FILL_PAGES #undef PTR_HASH_ALLOC_FILL_PAGES #undef PTR_HASH_ALLOC_FIXED_FILL_PAGES
4218011999-01-31Fredrik Hübinette (Hubbe) 
2fa1bf2002-12-02Martin Stjernholm /* Note: The block_alloc mutex is held while PRE_INIT_BLOCK runs. */
2bfcfe1998-03-27Fredrik Hübinette (Hubbe) #define PRE_INIT_BLOCK(X)
21ed0e1998-02-19Fredrik Hübinette (Hubbe) #define INIT_BLOCK(X) #define EXIT_BLOCK(X)
cfa7d82000-01-27Fredrik Hübinette (Hubbe) #define COUNT_BLOCK(X) #define COUNT_OTHER()
886a8e2004-04-03Martin Stjernholm #define DMALLOC_DESCRIBE_BLOCK(X)
7d63aa2001-11-08Fredrik Hübinette (Hubbe) #define BLOCK_ALLOC_HSIZE_SHIFT 2
5fd2b42006-01-24Martin Stjernholm #define MAX_EMPTY_BLOCKS 4 /* Must be >= 1. */
4218011999-01-31Fredrik Hübinette (Hubbe) 
b0a2362002-12-01Martin Stjernholm #ifndef BLOCK_ALLOC_USED #define BLOCK_ALLOC_USED DO_IF_DMALLOC(real_used) DO_IF_NOT_DMALLOC(used) #endif
f588b42003-03-15Henrik Grubbström (Grubba) /* Invalidate the block as far as possible if running with dmalloc. */ #define DO_PRE_INIT_BLOCK(X) do { \ DO_IF_DMALLOC(MEMSET((X), 0x55, sizeof(*(X)))); \ PRE_INIT_BLOCK(X); \ } while (0)
c473222003-02-24Henrik Grubbström (Grubba) #ifndef PIKE_HASH_T
322f892003-03-16Henrik Grubbström (Grubba) #define PIKE_HASH_T size_t
c473222003-02-24Henrik Grubbström (Grubba) #endif /* !PIKE_HASH_T */
aad99b2001-03-28Fredrik Hübinette (Hubbe) #ifdef PIKE_RUN_UNLOCKED #include "threads.h"
b076ce2001-08-31Fredrik Hübinette (Hubbe)  /* Block Alloc UnLocked */ #define BA_UL(X) PIKE_CONCAT(X,_unlocked) #define BA_STATIC static
54a1302004-06-02Martin Nilsson #define BA_INLINE INLINE
b076ce2001-08-31Fredrik Hübinette (Hubbe) #else #define BA_UL(X) X #define BA_STATIC
0f5ac12001-09-02Henrik Grubbström (Grubba) #define BA_INLINE
aad99b2001-03-28Fredrik Hübinette (Hubbe) #endif
db1aac2002-11-24Martin Stjernholm #define BLOCK_ALLOC_FILL_PAGES(DATA, PAGES) \ BLOCK_ALLOC(DATA, \ ((PIKE_MALLOC_PAGE_SIZE * (PAGES)) \ - PIKE_MALLOC_OVERHEAD - BLOCK_HEADER_SIZE) / \ sizeof (struct DATA)) #define PTR_HASH_ALLOC_FILL_PAGES(DATA, PAGES) \ PTR_HASH_ALLOC(DATA, \ ((PIKE_MALLOC_PAGE_SIZE * (PAGES)) \ - PIKE_MALLOC_OVERHEAD - BLOCK_HEADER_SIZE) / \ sizeof (struct DATA)) #define PTR_HASH_ALLOC_FIXED_FILL_PAGES(DATA, PAGES) \ PTR_HASH_ALLOC_FIXED(DATA, \ ((PIKE_MALLOC_PAGE_SIZE * (PAGES)) \ - PIKE_MALLOC_OVERHEAD - BLOCK_HEADER_SIZE) / \ sizeof (struct DATA)) /* Size of the members in the block struct below that don't contain * the payload data (i.e. that aren't x). This can be used in BSIZE to * make the block fit within a page. */ #ifndef BLOCK_HEADER_SIZE
99b5ff2002-11-24Martin Stjernholm #define BLOCK_HEADER_SIZE (3 * sizeof (void *) + sizeof (INT32))
db1aac2002-11-24Martin Stjernholm #endif
99b5ff2002-11-24Martin Stjernholm 
fc2c831999-04-01Fredrik Hübinette (Hubbe) #define BLOCK_ALLOC(DATA,BSIZE) \ \ struct PIKE_CONCAT(DATA,_block) \ { \ struct PIKE_CONCAT(DATA,_block) *next; \
379b682002-09-30Marcus Comstedt  struct PIKE_CONCAT(DATA,_block) *prev; \ struct DATA *PIKE_CONCAT3(free_,DATA,s); \ INT32 used; \
b0a2362002-12-01Martin Stjernholm  DO_IF_DMALLOC(INT32 real_used;) \
fc2c831999-04-01Fredrik Hübinette (Hubbe)  struct DATA x[BSIZE]; \
c9f7ef2004-12-07Henrik Grubbström (Grubba) }; \ struct PIKE_CONCAT(DATA,_context) \ { \ struct PIKE_CONCAT(DATA,_context) *next; \ struct PIKE_CONCAT(DATA, _block) *blocks, *free_blocks; \ INT32 num_empty_blocks; \
fc2c831999-04-01Fredrik Hübinette (Hubbe) }; \ \
c9f7ef2004-12-07Henrik Grubbström (Grubba) static struct PIKE_CONCAT(DATA,_context) *PIKE_CONCAT(DATA,_ctxs)=0; \
5fd2b42006-01-24Martin Stjernholm  \ /* Points to a double linked list of the meta-blocks. */ \ /* Full meta-blocks are last on this list. */ \
fc2c831999-04-01Fredrik Hübinette (Hubbe) static struct PIKE_CONCAT(DATA,_block) *PIKE_CONCAT(DATA,_blocks)=0; \
5fd2b42006-01-24Martin Stjernholm  \ /* Points to the last meta-block in the DATA,_block list that isn't full. */ \
09dd832006-01-24Martin Stjernholm /* -1 when the block alloc isn't initialized. */ \
c9f7ef2004-12-07Henrik Grubbström (Grubba) static struct PIKE_CONCAT(DATA,_block) *PIKE_CONCAT(DATA,_free_blocks)= \ (void*)-1; \
5fd2b42006-01-24Martin Stjernholm  \
379b682002-09-30Marcus Comstedt static INT32 PIKE_CONCAT3(num_empty_,DATA,_blocks)=0; \
aad99b2001-03-28Fredrik Hübinette (Hubbe) DO_IF_RUN_UNLOCKED(static PIKE_MUTEX_T PIKE_CONCAT(DATA,_mutex);) \
b0a2362002-12-01Martin Stjernholm DO_IF_DMALLOC( \ static struct DATA *PIKE_CONCAT(DATA,s_to_free)[4 * (BSIZE)]; \ static size_t PIKE_CONCAT(DATA,s_to_free_ptr) = 0; \ ) \
fc2c831999-04-01Fredrik Hübinette (Hubbe)  \
c9f7ef2004-12-07Henrik Grubbström (Grubba) void PIKE_CONCAT3(new_,DATA,_context)(void) \ { \ struct PIKE_CONCAT(DATA, _context) *ctx = \ (struct PIKE_CONCAT(DATA, _context) *) \ malloc(sizeof(struct PIKE_CONCAT(DATA, _context))); \ if (!ctx) { \ fprintf(stderr, "Fatal: out of memory.\n"); \ exit(17); \ } \ ctx->next = PIKE_CONCAT(DATA, _ctxs); \ PIKE_CONCAT(DATA, _ctxs) = ctx; \ ctx->blocks = PIKE_CONCAT(DATA,_blocks); \ ctx->free_blocks = PIKE_CONCAT(DATA,_free_blocks); \ ctx->num_empty_blocks = PIKE_CONCAT3(num_empty_,DATA,_blocks); \ PIKE_CONCAT(DATA,_blocks) = 0; \
1fa7af2004-12-08Henrik Grubbström (Grubba)  PIKE_CONCAT(DATA,_free_blocks) = 0; \
c9f7ef2004-12-07Henrik Grubbström (Grubba)  PIKE_CONCAT3(num_empty_,DATA,_blocks) = 0; \ } \ \
ed3a5b2001-09-01Fredrik Hübinette (Hubbe) static void PIKE_CONCAT(alloc_more_,DATA)(void) \ { \ struct PIKE_CONCAT(DATA,_block) *n; \
3d3cfa2002-11-23Martin Stjernholm  size_t e; \
ed3a5b2001-09-01Fredrik Hübinette (Hubbe)  n=(struct PIKE_CONCAT(DATA,_block) *) \ malloc(sizeof(struct PIKE_CONCAT(DATA,_block))); \ if(!n) \
fc2c831999-04-01Fredrik Hübinette (Hubbe)  { \
ed3a5b2001-09-01Fredrik Hübinette (Hubbe)  fprintf(stderr,"Fatal: out of memory.\n"); \ exit(17); \ } \
379b682002-09-30Marcus Comstedt  if((n->next=PIKE_CONCAT(DATA,_blocks))) \ n->next->prev=n; \ n->prev=NULL; \ n->used=0; \
b0a2362002-12-01Martin Stjernholm  DO_IF_DMALLOC(n->real_used = 0); \
ed3a5b2001-09-01Fredrik Hübinette (Hubbe)  PIKE_CONCAT(DATA,_blocks)=n; \
379b682002-09-30Marcus Comstedt  PIKE_CONCAT(DATA,_free_blocks)=n; \
fc2c831999-04-01Fredrik Hübinette (Hubbe)  \
f588b42003-03-15Henrik Grubbström (Grubba)  DO_PRE_INIT_BLOCK( n->x ); \
379b682002-09-30Marcus Comstedt  n->x[0].BLOCK_ALLOC_NEXT=NULL; \
883cf92002-11-19Martin Stjernholm  for(e=1;e<(BSIZE);e++) \
ed3a5b2001-09-01Fredrik Hübinette (Hubbe)  { \
f588b42003-03-15Henrik Grubbström (Grubba)  DO_PRE_INIT_BLOCK( (n->x+e) ); \
379b682002-09-30Marcus Comstedt  n->x[e].BLOCK_ALLOC_NEXT=(void *)&n->x[e-1]; \
fc2c831999-04-01Fredrik Hübinette (Hubbe)  } \
883cf92002-11-19Martin Stjernholm  n->PIKE_CONCAT3(free_,DATA,s)=&n->x[(BSIZE)-1]; \
f9a2e32002-11-20Henrik Grubbström (Grubba)  /* Mark the new blocks as unavailable for now... */ \
7ca8592002-11-23Martin Stjernholm  PIKE_MEM_NA(n->x); \
ed3a5b2001-09-01Fredrik Hübinette (Hubbe) } \ \
0f5ac12001-09-02Henrik Grubbström (Grubba) BA_STATIC BA_INLINE struct DATA *BA_UL(PIKE_CONCAT(alloc_,DATA))(void) \
ed3a5b2001-09-01Fredrik Hübinette (Hubbe) { \ struct DATA *tmp; \
379b682002-09-30Marcus Comstedt  struct PIKE_CONCAT(DATA,_block) *blk; \ \ if(!(blk = PIKE_CONCAT(DATA,_free_blocks))) { \
ed3a5b2001-09-01Fredrik Hübinette (Hubbe)  PIKE_CONCAT(alloc_more_,DATA)(); \
379b682002-09-30Marcus Comstedt  blk = PIKE_CONCAT(DATA,_blocks); \
b0a2362002-12-01Martin Stjernholm  blk->BLOCK_ALLOC_USED++; \
379b682002-09-30Marcus Comstedt  } \
9820432001-07-01Martin Stjernholm  DO_IF_DEBUG( \
379b682002-09-30Marcus Comstedt  else if (PIKE_CONCAT(DATA,_free_blocks) == (void *)-1) \
335e422002-10-11Henrik Grubbström (Grubba)  Pike_fatal("Block alloc " #DATA " not initialized.\n"); \
9820432001-07-01Martin Stjernholm  ) \
b0a2362002-12-01Martin Stjernholm  else if(!blk->BLOCK_ALLOC_USED++) \
379b682002-09-30Marcus Comstedt  --PIKE_CONCAT3(num_empty_,DATA,_blocks); \
b0a2362002-12-01Martin Stjernholm  DO_IF_DMALLOC(blk->used++); \
fc2c831999-04-01Fredrik Hübinette (Hubbe)  \
379b682002-09-30Marcus Comstedt  tmp = blk->PIKE_CONCAT3(free_,DATA,s); \
f9a2e32002-11-20Henrik Grubbström (Grubba)  /* Mark the new block as available. */ \
7ca8592002-11-23Martin Stjernholm  PIKE_MEM_RW(*tmp); \
b0a2362002-12-01Martin Stjernholm  if(!(blk->PIKE_CONCAT3(free_,DATA,s) = (void *)tmp->BLOCK_ALLOC_NEXT)) \
379b682002-09-30Marcus Comstedt  PIKE_CONCAT(DATA,_free_blocks) = blk->prev; \
7d63aa2001-11-08Fredrik Hübinette (Hubbe)  DO_IF_DMALLOC( \ dmalloc_unregister(tmp, 1); \ dmalloc_register(tmp,sizeof(struct DATA), DMALLOC_LOCATION()); \ ) \
f9a2e32002-11-20Henrik Grubbström (Grubba)  /* Mark the new block as available but uninitialized. */ \
7ca8592002-11-23Martin Stjernholm  PIKE_MEM_WO(*tmp); \
fc2c831999-04-01Fredrik Hübinette (Hubbe)  INIT_BLOCK(tmp); \ return tmp; \ } \ \
b076ce2001-08-31Fredrik Hübinette (Hubbe) DO_IF_RUN_UNLOCKED( \
0f5ac12001-09-02Henrik Grubbström (Grubba) struct DATA *PIKE_CONCAT(alloc_,DATA)(void) \
805f812001-03-30Fredrik Hübinette (Hubbe) { \ struct DATA *ret; \ DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \ ret=PIKE_CONCAT3(alloc_,DATA,_unlocked)(); \ DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ return ret; \
b076ce2001-08-31Fredrik Hübinette (Hubbe) }) \
805f812001-03-30Fredrik Hübinette (Hubbe)  \
fd46f52001-09-25Fredrik Hübinette (Hubbe) DO_IF_DMALLOC( \
09dd832006-01-24Martin Stjernholm static void PIKE_CONCAT3(dmalloc_,DATA,_not_freed) (struct DATA *d, \ const char *msg) \ { \ /* Separate function to allow gdb breakpoints. */ \ fprintf (stderr, "struct " TOSTR(DATA) \ " at %p is still in use %s\n", d, msg); \ } \
886a8e2004-04-03Martin Stjernholm  \
09dd832006-01-24Martin Stjernholm static void PIKE_CONCAT(dmalloc_late_free_,DATA) (struct DATA *d) \
886a8e2004-04-03Martin Stjernholm { \
09dd832006-01-24Martin Stjernholm  /* Separate function to allow gdb breakpoints. */ \ fprintf (stderr, "struct " TOSTR(DATA) " at %p freed now (too late)\n", d); \ dmalloc_mark_as_free (d, 1); \ dmalloc_unregister (d, 1); \ PIKE_MEM_NA (*d); \ } \ \ static void PIKE_CONCAT3(dmalloc_free_,DATA,_block) ( \ struct PIKE_CONCAT(DATA,_block) *blk, const char *msg) \ { \ int dont_free = 0; \ size_t i; \ for (i = 0; i < (BSIZE); i++) { \
e1bb782006-01-25Martin Stjernholm  if (!dmalloc_check_allocated (blk->x + i, 0)) \ dmalloc_unregister (blk->x + i, 1); \ else if (dmalloc_check_allocated (blk->x + i, 1)) { \
09dd832006-01-24Martin Stjernholm  PIKE_CONCAT3(dmalloc_,DATA,_not_freed) (blk->x + i, msg); \ DMALLOC_DESCRIBE_BLOCK ((blk->x + i)); \ debug_malloc_dump_references (blk->x + i, 0, 2, 0); \
e1bb782006-01-25Martin Stjernholm  dont_free = 1; \
09dd832006-01-24Martin Stjernholm  } \ } \ if (dont_free) { \ /* If a block still is in use we conciously leak this */ \ /* meta-block to allow access to it later. That way we can */ \ /* avoid fatals before the leak report. */ \ dmalloc_accept_leak (blk); \ } \ else { \ /* Mark meta-block as available, since libc will mess with it. */ \ PIKE_MEM_RW (blk->x); \ free ((char *) blk); \ } \
886a8e2004-04-03Martin Stjernholm } \
fd46f52001-09-25Fredrik Hübinette (Hubbe) ) \ \
fc2c831999-04-01Fredrik Hübinette (Hubbe) void PIKE_CONCAT(really_free_,DATA)(struct DATA *d) \ { \
379b682002-09-30Marcus Comstedt  struct PIKE_CONCAT(DATA,_block) *blk; \
b0a2362002-12-01Martin Stjernholm  \
fc2c831999-04-01Fredrik Hübinette (Hubbe)  EXIT_BLOCK(d); \
b0a2362002-12-01Martin Stjernholm  \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
b0a2362002-12-01Martin Stjernholm  \ DO_IF_DMALLOC({ \ struct DATA *d2; \ blk = PIKE_CONCAT(DATA,_free_blocks); \ if(blk == NULL || (char *)d < (char *)blk || \ (char *)d >= (char *)(blk->x+(BSIZE))) { \ blk = PIKE_CONCAT(DATA,_blocks); \
09dd832006-01-24Martin Stjernholm  while (blk && ((char *)d < (char *)blk || \ (char *)d >= (char *)(blk->x+(BSIZE)))) \
b0a2362002-12-01Martin Stjernholm  blk = blk->next; \ } \
09dd832006-01-24Martin Stjernholm  if (blk) { \
3c83ce2007-04-02Henrik Grubbström (Grubba)  if (!dmalloc_check_allocated (d, 0)) { \ debug_malloc_dump_references(d, 0, 2, 0); \
09dd832006-01-24Martin Stjernholm  Pike_fatal ("really_free_" TOSTR(DATA) " called with " \ "unknown pointer %p (probably already freed)\n", d); \
3c83ce2007-04-02Henrik Grubbström (Grubba)  } \
09dd832006-01-24Martin Stjernholm  blk->used--; \ dmalloc_mark_as_free(d, 1); \ PIKE_MEM_NA(*d); \ d2 = PIKE_CONCAT(DATA,s_to_free)[PIKE_CONCAT(DATA,s_to_free_ptr)]; \ PIKE_CONCAT(DATA,s_to_free)[PIKE_CONCAT(DATA,s_to_free_ptr)] = d; \ PIKE_CONCAT(DATA,s_to_free_ptr) = \ (PIKE_CONCAT(DATA,s_to_free_ptr) + 1) % \ NELEM(PIKE_CONCAT(DATA,s_to_free)); \ if ((d = d2)) \ PIKE_MEM_WO(*d); \ else \ return; \ } \ else if (dmalloc_check_allocated (d, 0)) { \ PIKE_CONCAT(dmalloc_late_free_,DATA) (d); \
b0a2362002-12-01Martin Stjernholm  return; \
09dd832006-01-24Martin Stjernholm  } \
b0a2362002-12-01Martin Stjernholm  }); \ \
379b682002-09-30Marcus Comstedt  blk = PIKE_CONCAT(DATA,_free_blocks); \
d80f742002-10-01Marcus Comstedt  if(blk == NULL || (char *)d < (char *)blk || \
883cf92002-11-19Martin Stjernholm  (char *)d >= (char *)(blk->x+(BSIZE))) { \
379b682002-09-30Marcus Comstedt  blk = PIKE_CONCAT(DATA,_blocks); \
09dd832006-01-24Martin Stjernholm  DO_IF_DEBUG ( \ if (!blk) Pike_fatal ("really_free_" TOSTR(DATA) \ " got invalid pointer %p\n", d) \ ); \
379b682002-09-30Marcus Comstedt  if((char *)d < (char *)blk || \
883cf92002-11-19Martin Stjernholm  (char *)d >= (char *)(blk->x+(BSIZE))) { \
40fb042002-11-20Henrik Grubbström (Grubba)  do { \
379b682002-09-30Marcus Comstedt  blk = blk->next; \
09dd832006-01-24Martin Stjernholm  DO_IF_DEBUG ( \ if (!blk) Pike_fatal ("really_free_" TOSTR(DATA) \ " got invalid pointer %p\n", d) \ ); \
40fb042002-11-20Henrik Grubbström (Grubba)  } while((char *)d < (char *)blk || \ (char *)d >= (char *)(blk->x+(BSIZE))); \
379b682002-09-30Marcus Comstedt  if(blk == PIKE_CONCAT(DATA,_free_blocks)) \ PIKE_CONCAT(DATA,_free_blocks) = blk->prev; \ blk->prev->next = blk->next; \ if(blk->next) \ blk->next->prev = blk->prev; \ blk->prev = NULL; \ blk->next = PIKE_CONCAT(DATA,_blocks); \ blk->next->prev = blk; \ PIKE_CONCAT(DATA,_blocks) = blk; \ } \
d80f742002-10-01Marcus Comstedt  if(PIKE_CONCAT(DATA,_free_blocks) == NULL) \ PIKE_CONCAT(DATA,_free_blocks) = blk; \
379b682002-09-30Marcus Comstedt  } \
b0a2362002-12-01Martin Stjernholm  \
09dd832006-01-24Martin Stjernholm  DO_IF_DEBUG ( \ if ((char *) d < (char *) &blk->x || \ ((char *) d - (char *) &blk->x) % sizeof (struct DATA)) \ Pike_fatal ("really_free_" TOSTR(DATA) \ " got misaligned pointer %p\n", d); \ ); \ \
f588b42003-03-15Henrik Grubbström (Grubba)  DO_PRE_INIT_BLOCK(d); \
3c83ce2007-04-02Henrik Grubbström (Grubba)  DO_IF_DMALLOC({ \ struct DATA *d2 = (void *)blk->PIKE_CONCAT3(free_,DATA,s); \ d->BLOCK_ALLOC_NEXT = NULL; \ if (d2) { \ while (d2->BLOCK_ALLOC_NEXT) { \ if (PTR_TO_INT(d2->BLOCK_ALLOC_NEXT) == 0x55555555) { \ debug_malloc_dump_references(d2, 0, 2, 0); \ Pike_fatal("Bad next pointer in free list.\n"); \ } \ d2 = (void *)d2->BLOCK_ALLOC_NEXT; \ } \ d2->BLOCK_ALLOC_NEXT = (void *)d; \ } else { \ blk->PIKE_CONCAT3(free_,DATA,s)=d; \ } \ }); \ DO_IF_NOT_DMALLOC({ \ d->BLOCK_ALLOC_NEXT = (void *)blk->PIKE_CONCAT3(free_,DATA,s); \ blk->PIKE_CONCAT3(free_,DATA,s)=d; \ }); \
f9a2e32002-11-20Henrik Grubbström (Grubba)  /* Mark block as unavailable. */ \
7ca8592002-11-23Martin Stjernholm  PIKE_MEM_NA(*d); \
b0a2362002-12-01Martin Stjernholm  \ if(!--blk->BLOCK_ALLOC_USED && \
d80f742002-10-01Marcus Comstedt  ++PIKE_CONCAT3(num_empty_,DATA,_blocks) > MAX_EMPTY_BLOCKS) { \ if(blk == PIKE_CONCAT(DATA,_free_blocks)) { \
5fd2b42006-01-24Martin Stjernholm  /* blk->prev isn't NULL because MAX_EMPTY_BLOCKS >= 1 so we */ \ /* know there's at least one more empty block. */ \
d80f742002-10-01Marcus Comstedt  if((blk->prev->next = blk->next)) \ blk->next->prev = blk->prev; \ PIKE_CONCAT(DATA,_free_blocks) = blk->prev; \ } else { \ PIKE_CONCAT(DATA,_blocks) = blk->next; \ blk->next->prev = NULL; \ } \
b0a2362002-12-01Martin Stjernholm  \
09dd832006-01-24Martin Stjernholm  DO_IF_DMALLOC ( \ PIKE_CONCAT3(dmalloc_free_,DATA,_block) ( \ blk, "in block expected to be empty") \ ); \ DO_IF_NOT_DMALLOC( \ /* Mark meta-block as available, since libc will mess with it. */ \ PIKE_MEM_RW(*blk); \ free(blk); \ ); \
b0a2362002-12-01Martin Stjernholm  \
379b682002-09-30Marcus Comstedt  --PIKE_CONCAT3(num_empty_,DATA,_blocks); \ } \
b0a2362002-12-01Martin Stjernholm  \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
fc2c831999-04-01Fredrik Hübinette (Hubbe) } \ \
805f812001-03-30Fredrik Hübinette (Hubbe) static void PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(void) \
fc2c831999-04-01Fredrik Hübinette (Hubbe) { \ struct PIKE_CONCAT(DATA,_block) *tmp; \
09dd832006-01-24Martin Stjernholm  \ DO_IF_DMALLOC( \ MEMSET(PIKE_CONCAT(DATA,s_to_free), 0, sizeof(PIKE_CONCAT(DATA,s_to_free))); \ while ((tmp = PIKE_CONCAT(DATA,_blocks))) { \ PIKE_CONCAT(DATA,_blocks) = tmp->next; \ PIKE_CONCAT3(dmalloc_free_,DATA,_block) ( \ tmp, "in free_all_" TOSTR(DATA) "_blocks"); \ } \ ); \ \ DO_IF_NOT_DMALLOC( \ while((tmp=PIKE_CONCAT(DATA,_blocks))) \ { \ PIKE_CONCAT(DATA,_blocks)=tmp->next; \ /* Mark meta-block as available, since libc will mess with it. */ \ PIKE_MEM_RW(tmp->x); \ free((char *)tmp); \ } \ ); \ \
c9f7ef2004-12-07Henrik Grubbström (Grubba)  if (PIKE_CONCAT(DATA,_ctxs)) { \ struct PIKE_CONCAT(DATA, _context) *ctx = PIKE_CONCAT(DATA,_ctxs); \ PIKE_CONCAT(DATA,_blocks)=ctx->blocks; \ PIKE_CONCAT(DATA,_free_blocks)=ctx->free_blocks; \ PIKE_CONCAT3(num_empty_,DATA,_blocks)=ctx->num_empty_blocks; \ PIKE_CONCAT(DATA,_ctxs) = ctx->next; \ free(ctx); \ } else { \ PIKE_CONCAT(DATA,_blocks)=0; \ PIKE_CONCAT(DATA,_free_blocks)=0; \ PIKE_CONCAT3(num_empty_,DATA,_blocks)=0; \ } \
fc2c831999-04-01Fredrik Hübinette (Hubbe) } \
424d9c1999-05-02Fredrik Hübinette (Hubbe)  \
805f812001-03-30Fredrik Hübinette (Hubbe) void PIKE_CONCAT3(free_all_,DATA,_blocks)(void) \ { \ DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \ PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(); \ DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ } \
424d9c1999-05-02Fredrik Hübinette (Hubbe)  \
f757d02008-05-01Martin Stjernholm void PIKE_CONCAT3(count_memory_in_,DATA,s)(size_t *num_, size_t *size_) \
424d9c1999-05-02Fredrik Hübinette (Hubbe) { \
f757d02008-05-01Martin Stjernholm  size_t num=0, size=0; \
424d9c1999-05-02Fredrik Hübinette (Hubbe)  struct PIKE_CONCAT(DATA,_block) *tmp; \
c9f7ef2004-12-07Henrik Grubbström (Grubba)  struct PIKE_CONCAT(DATA,_context) *ctx = PIKE_CONCAT(DATA,_ctxs); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
424d9c1999-05-02Fredrik Hübinette (Hubbe)  for(tmp=PIKE_CONCAT(DATA,_blocks);tmp;tmp=tmp->next) \ { \ size+=sizeof(struct PIKE_CONCAT(DATA,_block)); \
379b682002-09-30Marcus Comstedt  num+=tmp->used; \
cfa7d82000-01-27Fredrik Hübinette (Hubbe)  COUNT_BLOCK(tmp); \
424d9c1999-05-02Fredrik Hübinette (Hubbe)  } \
c9f7ef2004-12-07Henrik Grubbström (Grubba)  while (ctx) { \ for(tmp=ctx->blocks;tmp;tmp=tmp->next) \ { \ size+=sizeof(struct PIKE_CONCAT(DATA,_block)); \ num+=tmp->used; \ COUNT_BLOCK(tmp); \ } \ ctx = ctx->next; \ } \
cfa7d82000-01-27Fredrik Hübinette (Hubbe)  COUNT_OTHER(); \
424d9c1999-05-02Fredrik Hübinette (Hubbe)  *num_=num; \ *size_=size; \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ } \ \ \ void PIKE_CONCAT3(init_,DATA,_blocks)(void) \ { \
805f812001-03-30Fredrik Hübinette (Hubbe) /* DO_IF_RUN_UNLOCKED(mt_init_recursive(&PIKE_CONCAT(DATA,_mutex)));*/ \ DO_IF_RUN_UNLOCKED(mt_init(&PIKE_CONCAT(DATA,_mutex))); \
379b682002-09-30Marcus Comstedt  PIKE_CONCAT(DATA,_free_blocks)=0; \
63150e2005-04-08Henrik Grubbström (Grubba) }
fc2c831999-04-01Fredrik Hübinette (Hubbe) 
afbc722001-09-06Fredrik Hübinette (Hubbe) #define LOW_PTR_HASH_ALLOC(DATA,BSIZE) \
011ad31999-10-22Fredrik Hübinette (Hubbe)  \ BLOCK_ALLOC(DATA,BSIZE) \ \
3f84322000-04-23Martin Stjernholm struct DATA **PIKE_CONCAT(DATA,_hash_table)=0; \
59e0112001-07-03Fredrik Hübinette (Hubbe) size_t PIKE_CONCAT(DATA,_hash_table_size)=0; \
afbc722001-09-06Fredrik Hübinette (Hubbe) size_t PIKE_CONCAT(DATA,_hash_table_magnitude)=0; \
b0a2362002-12-01Martin Stjernholm static size_t PIKE_CONCAT(num_,DATA)=0; \
011ad31999-10-22Fredrik Hübinette (Hubbe)  \
54a1302004-06-02Martin Nilsson static INLINE struct DATA * \
c473222003-02-24Henrik Grubbström (Grubba)  PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(void *ptr, \ PIKE_HASH_T hval) \
011ad31999-10-22Fredrik Hübinette (Hubbe) { \ struct DATA *p,**pp; \
ec6b782000-03-21Fredrik Hübinette (Hubbe)  p=PIKE_CONCAT(DATA,_hash_table)[hval]; \
db1aac2002-11-24Martin Stjernholm  if(!p || p->PTR_HASH_ALLOC_DATA == ptr) \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  { \ return p; \ } \
ec6b782000-03-21Fredrik Hübinette (Hubbe)  while((p=*(pp=&p->BLOCK_ALLOC_NEXT))) \
011ad31999-10-22Fredrik Hübinette (Hubbe)  { \
db1aac2002-11-24Martin Stjernholm  if(p->PTR_HASH_ALLOC_DATA==ptr) \
011ad31999-10-22Fredrik Hübinette (Hubbe)  { \ *pp=p->BLOCK_ALLOC_NEXT; \ p->BLOCK_ALLOC_NEXT=PIKE_CONCAT(DATA,_hash_table)[hval]; \ PIKE_CONCAT(DATA,_hash_table)[hval]=p; \ return p; \ } \ } \ return 0; \ } \ \ struct DATA *PIKE_CONCAT(find_,DATA)(void *ptr) \ { \
805f812001-03-30Fredrik Hübinette (Hubbe)  struct DATA *p; \
d2361e2003-06-30Martin Stjernholm  PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
805f812001-03-30Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
949ecb2006-03-10Martin Stjernholm  if(!PIKE_CONCAT(DATA,_hash_table)) { \
805f812001-03-30Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ return 0; \ } \
c473222003-02-24Henrik Grubbström (Grubba)  hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
805f812001-03-30Fredrik Hübinette (Hubbe)  p=PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(ptr, hval); \ DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ return p; \
c2b2442003-03-16Henrik Grubbström (Grubba) } \ \
54a1302004-06-02Martin Nilsson static INLINE struct DATA * \
c2b2442003-03-16Henrik Grubbström (Grubba)  PIKE_CONCAT3(just_find_,DATA,_unlocked)(void *ptr, \ PIKE_HASH_T hval) \ { \
1abbfb2006-07-05Martin Stjernholm  struct DATA *p; \
c2b2442003-03-16Henrik Grubbström (Grubba)  p=PIKE_CONCAT(DATA,_hash_table)[hval]; \ if(!p || p->PTR_HASH_ALLOC_DATA == ptr) \ { \ return p; \ } \ while((p=p->BLOCK_ALLOC_NEXT)) \ { \ if(p->PTR_HASH_ALLOC_DATA==ptr) return p; \ } \ return 0; \ } \ \ static struct DATA *PIKE_CONCAT(just_find_,DATA)(void *ptr) \ { \ struct DATA *p; \
d2361e2003-06-30Martin Stjernholm  PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
c2b2442003-03-16Henrik Grubbström (Grubba)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
949ecb2006-03-10Martin Stjernholm  if(!PIKE_CONCAT(DATA,_hash_table)) { \
c2b2442003-03-16Henrik Grubbström (Grubba)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ return 0; \ } \ hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \ p=PIKE_CONCAT3(just_find_,DATA,_unlocked)(ptr, hval); \ DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ return p; \
011ad31999-10-22Fredrik Hübinette (Hubbe) } \ \ \
805f812001-03-30Fredrik Hübinette (Hubbe)  \
d77bd52002-12-01Martin Stjernholm struct DATA *PIKE_CONCAT(make_,DATA)(void *ptr) \
805f812001-03-30Fredrik Hübinette (Hubbe) { \ struct DATA *p; \
d2361e2003-06-30Martin Stjernholm  PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
805f812001-03-30Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
c473222003-02-24Henrik Grubbström (Grubba)  hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
805f812001-03-30Fredrik Hübinette (Hubbe)  p=PIKE_CONCAT3(make_,DATA,_unlocked)(ptr,hval); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
011ad31999-10-22Fredrik Hübinette (Hubbe)  return p; \ } \ \
f3378f2000-05-16Fredrik Hübinette (Hubbe) struct DATA *PIKE_CONCAT(get_,DATA)(void *ptr) \
011ad31999-10-22Fredrik Hübinette (Hubbe) { \ struct DATA *p; \
d2361e2003-06-30Martin Stjernholm  PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
c473222003-02-24Henrik Grubbström (Grubba)  hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
805f812001-03-30Fredrik Hübinette (Hubbe)  if(!(p=PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(ptr, hval))) \ p=PIKE_CONCAT3(make_,DATA,_unlocked)(ptr, hval); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ return p; \
011ad31999-10-22Fredrik Hübinette (Hubbe) } \ \
e921e72008-01-24Henrik Grubbström (Grubba) int PIKE_CONCAT3(check_,DATA,_semaphore)(void *ptr) \
011ad31999-10-22Fredrik Hübinette (Hubbe) { \
d2361e2003-06-30Martin Stjernholm  PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
c473222003-02-24Henrik Grubbström (Grubba)  hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
e921e72008-01-24Henrik Grubbström (Grubba)  if(PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(ptr, hval)) \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  { \ DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
011ad31999-10-22Fredrik Hübinette (Hubbe)  return 0; \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  } \
011ad31999-10-22Fredrik Hübinette (Hubbe)  \
805f812001-03-30Fredrik Hübinette (Hubbe)  PIKE_CONCAT3(make_,DATA,_unlocked)(ptr, hval); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
011ad31999-10-22Fredrik Hübinette (Hubbe)  return 1; \ } \ \
e13e712002-12-01Martin Stjernholm void PIKE_CONCAT(move_,DATA)(struct DATA *block, void *new_ptr) \ { \
c473222003-02-24Henrik Grubbström (Grubba)  PIKE_HASH_T hval = \
d2361e2003-06-30Martin Stjernholm  (PIKE_HASH_T)PTR_TO_INT(block->PTR_HASH_ALLOC_DATA); \
e13e712002-12-01Martin Stjernholm  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
c473222003-02-24Henrik Grubbström (Grubba)  hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
e13e712002-12-01Martin Stjernholm  if (!PIKE_CONCAT3(really_low_find_,DATA,_unlocked)( \ block->PTR_HASH_ALLOC_DATA, hval)) \ Pike_fatal("The block to move wasn't found.\n"); \ DO_IF_DEBUG( \ if (PIKE_CONCAT(DATA,_hash_table)[hval] != block) \ Pike_fatal("Expected the block to be at the top of the hash chain.\n"); \ ); \ PIKE_CONCAT(DATA,_hash_table)[hval] = block->BLOCK_ALLOC_NEXT; \ block->PTR_HASH_ALLOC_DATA = new_ptr; \
d2361e2003-06-30Martin Stjernholm  hval = (PIKE_HASH_T)PTR_TO_INT(new_ptr) % \
c473222003-02-24Henrik Grubbström (Grubba)  (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
e13e712002-12-01Martin Stjernholm  block->BLOCK_ALLOC_NEXT = PIKE_CONCAT(DATA,_hash_table)[hval]; \ PIKE_CONCAT(DATA,_hash_table)[hval] = block; \ DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ } \ \
011ad31999-10-22Fredrik Hübinette (Hubbe) int PIKE_CONCAT(remove_,DATA)(void *ptr) \ { \ struct DATA *p; \
d2361e2003-06-30Martin Stjernholm  PIKE_HASH_T hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \ if(!PIKE_CONCAT(DATA,_hash_table)) \ { \ DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \ return 0; \ } \
c473222003-02-24Henrik Grubbström (Grubba)  hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
805f812001-03-30Fredrik Hübinette (Hubbe)  if((p=PIKE_CONCAT3(really_low_find_,DATA,_unlocked)(ptr, hval))) \
011ad31999-10-22Fredrik Hübinette (Hubbe)  { \ PIKE_CONCAT(num_,DATA)--; \
afbc722001-09-06Fredrik Hübinette (Hubbe)  DO_IF_DEBUG( if(PIKE_CONCAT(DATA,_hash_table)[hval]!=p) \
5aad932002-08-15Marcus Comstedt  Pike_fatal("GAOssdf\n"); ); \
011ad31999-10-22Fredrik Hübinette (Hubbe)  PIKE_CONCAT(DATA,_hash_table)[hval]=p->BLOCK_ALLOC_NEXT; \
b076ce2001-08-31Fredrik Hübinette (Hubbe)  BA_UL(PIKE_CONCAT(really_free_,DATA))(p); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
011ad31999-10-22Fredrik Hübinette (Hubbe)  return 1; \ } \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
011ad31999-10-22Fredrik Hübinette (Hubbe)  return 0; \ } \ \
b0a2362002-12-01Martin Stjernholm void PIKE_CONCAT3(low_init_,DATA,_hash)(size_t size) \
011ad31999-10-22Fredrik Hübinette (Hubbe) { \
fc60d42004-06-01Martin Nilsson  extern const INT32 hashprimes[32]; \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  extern int my_log2(size_t x); \ PIKE_CONCAT3(init_,DATA,_blocks)(); \ DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
afbc722001-09-06Fredrik Hübinette (Hubbe)  PIKE_CONCAT(DATA,_hash_table_size)= \ hashprimes[PIKE_CONCAT(DATA,_hash_table_magnitude)=my_log2(size)]; \
011ad31999-10-22Fredrik Hübinette (Hubbe)  \ PIKE_CONCAT(DATA,_hash_table)=(struct DATA **) \ malloc(sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size)); \ if(!PIKE_CONCAT(DATA,_hash_table)) \ { \ fprintf(stderr,"Fatal: out of memory.\n"); \ exit(17); \ } \ MEMSET(PIKE_CONCAT(DATA,_hash_table),0, \ sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size)); \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
afbc722001-09-06Fredrik Hübinette (Hubbe) } \ \ \ void PIKE_CONCAT3(init_,DATA,_hash)(void) \ { \ PIKE_CONCAT3(low_init_,DATA,_hash)(BSIZE); \
011ad31999-10-22Fredrik Hübinette (Hubbe) } \ \ void PIKE_CONCAT3(exit_,DATA,_hash)(void) \ { \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_lock(&PIKE_CONCAT(DATA,_mutex))); \
805f812001-03-30Fredrik Hübinette (Hubbe)  PIKE_CONCAT3(free_all_,DATA,_blocks_unlocked)(); \
011ad31999-10-22Fredrik Hübinette (Hubbe)  free(PIKE_CONCAT(DATA,_hash_table)); \ PIKE_CONCAT(DATA,_hash_table)=0; \
7bcb1d1999-12-19Fredrik Hübinette (Hubbe)  PIKE_CONCAT(num_,DATA)=0; \
aad99b2001-03-28Fredrik Hübinette (Hubbe)  DO_IF_RUN_UNLOCKED(mt_unlock(&PIKE_CONCAT(DATA,_mutex))); \
424d9c1999-05-02Fredrik Hübinette (Hubbe) }
afbc722001-09-06Fredrik Hübinette (Hubbe)  #define PTR_HASH_ALLOC_FIXED(DATA,BSIZE) \
d037172003-02-24Henrik Grubbström (Grubba) struct DATA *PIKE_CONCAT3(make_,DATA,_unlocked)(void *ptr, PIKE_HASH_T hval);\
afbc722001-09-06Fredrik Hübinette (Hubbe) LOW_PTR_HASH_ALLOC(DATA,BSIZE) \ \
d037172003-02-24Henrik Grubbström (Grubba) struct DATA *PIKE_CONCAT3(make_,DATA,_unlocked)(void *ptr, PIKE_HASH_T hval) \
afbc722001-09-06Fredrik Hübinette (Hubbe) { \ struct DATA *p; \ \ DO_IF_DEBUG( if(!PIKE_CONCAT(DATA,_hash_table)) \
b0a2362002-12-01Martin Stjernholm  Pike_fatal("Hash table error!\n"); ) \
afbc722001-09-06Fredrik Hübinette (Hubbe)  PIKE_CONCAT(num_,DATA)++; \ \ p=BA_UL(PIKE_CONCAT(alloc_,DATA))(); \
db1aac2002-11-24Martin Stjernholm  p->PTR_HASH_ALLOC_DATA=ptr; \
afbc722001-09-06Fredrik Hübinette (Hubbe)  p->BLOCK_ALLOC_NEXT=PIKE_CONCAT(DATA,_hash_table)[hval]; \ PIKE_CONCAT(DATA,_hash_table)[hval]=p; \ return p; \
63150e2005-04-08Henrik Grubbström (Grubba) }
afbc722001-09-06Fredrik Hübinette (Hubbe)  #define PTR_HASH_ALLOC(DATA,BSIZE) \
bee7632003-02-24Henrik Grubbström (Grubba) struct DATA *PIKE_CONCAT3(make_,DATA,_unlocked)(void *ptr, \ PIKE_HASH_T hval); \
afbc722001-09-06Fredrik Hübinette (Hubbe) LOW_PTR_HASH_ALLOC(DATA,BSIZE) \ \
0ca86e2005-04-09Henrik Grubbström (Grubba) static void PIKE_CONCAT(DATA,_rehash)(void) \
afbc722001-09-06Fredrik Hübinette (Hubbe) { \ /* Time to re-hash */ \
fc60d42004-06-01Martin Nilsson  extern const INT32 hashprimes[32]; \
afbc722001-09-06Fredrik Hübinette (Hubbe)  struct DATA **old_hash; \ struct DATA *p; \
c473222003-02-24Henrik Grubbström (Grubba)  PIKE_HASH_T hval; \
afbc722001-09-06Fredrik Hübinette (Hubbe)  size_t e; \ \ old_hash= PIKE_CONCAT(DATA,_hash_table); \ e=PIKE_CONCAT(DATA,_hash_table_size); \ \ PIKE_CONCAT(DATA,_hash_table_magnitude)++; \ PIKE_CONCAT(DATA,_hash_table_size)= \ hashprimes[PIKE_CONCAT(DATA,_hash_table_magnitude)]; \ if((PIKE_CONCAT(DATA,_hash_table)=(struct DATA **) \ malloc(PIKE_CONCAT(DATA,_hash_table_size)* \ sizeof(struct DATA *)))) \ { \ MEMSET(PIKE_CONCAT(DATA,_hash_table),0, \ sizeof(struct DATA *)*PIKE_CONCAT(DATA,_hash_table_size)); \ while(e-- > 0) \ { \ while((p=old_hash[e])) \ { \ old_hash[e]=p->BLOCK_ALLOC_NEXT; \
d2361e2003-06-30Martin Stjernholm  hval = (PIKE_HASH_T)PTR_TO_INT(p->PTR_HASH_ALLOC_DATA); \
c473222003-02-24Henrik Grubbström (Grubba)  hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
afbc722001-09-06Fredrik Hübinette (Hubbe)  p->BLOCK_ALLOC_NEXT=PIKE_CONCAT(DATA,_hash_table)[hval]; \ PIKE_CONCAT(DATA,_hash_table)[hval]=p; \ } \ } \ free((char *)old_hash); \ }else{ \ PIKE_CONCAT(DATA,_hash_table)=old_hash; \ PIKE_CONCAT(DATA,_hash_table_size)=e; \ } \ } \ \
c473222003-02-24Henrik Grubbström (Grubba) struct DATA *PIKE_CONCAT3(make_,DATA,_unlocked)(void *ptr, \ PIKE_HASH_T hval) \
afbc722001-09-06Fredrik Hübinette (Hubbe) { \ struct DATA *p; \ \ DO_IF_DEBUG( if(!PIKE_CONCAT(DATA,_hash_table)) \
b0a2362002-12-01Martin Stjernholm  Pike_fatal("Hash table error!\n"); ) \
afbc722001-09-06Fredrik Hübinette (Hubbe)  PIKE_CONCAT(num_,DATA)++; \ \
7d63aa2001-11-08Fredrik Hübinette (Hubbe)  if(( PIKE_CONCAT(num_,DATA)>>BLOCK_ALLOC_HSIZE_SHIFT ) >= \
afbc722001-09-06Fredrik Hübinette (Hubbe)  PIKE_CONCAT(DATA,_hash_table_size)) \ { \ PIKE_CONCAT(DATA,_rehash)(); \
d2361e2003-06-30Martin Stjernholm  hval = (PIKE_HASH_T)PTR_TO_INT(ptr); \
c473222003-02-24Henrik Grubbström (Grubba)  hval %= (PIKE_HASH_T)PIKE_CONCAT(DATA,_hash_table_size); \
afbc722001-09-06Fredrik Hübinette (Hubbe)  } \ \ p=BA_UL(PIKE_CONCAT(alloc_,DATA))(); \
db1aac2002-11-24Martin Stjernholm  p->PTR_HASH_ALLOC_DATA=ptr; \
afbc722001-09-06Fredrik Hübinette (Hubbe)  p->BLOCK_ALLOC_NEXT=PIKE_CONCAT(DATA,_hash_table)[hval]; \ PIKE_CONCAT(DATA,_hash_table)[hval]=p; \ return p; \
1f5f6a2001-09-08Henrik Grubbström (Grubba) }