0a3d342011-11-10Arne Goedeke #include <stdlib.h>
67795d2011-11-11Arne Goedeke #include <string.h>
3854832011-11-18Arne Goedeke #include <stdint.h>
0a3d342011-11-10Arne Goedeke 
e2499f2012-01-03Arne Goedeke #include "block_allocator.h"
a60c242011-12-25Arne Goedeke #include "bitvector.h"
6fc6ce2011-12-30Arne Goedeke 
e2499f2012-01-03Arne Goedeke #if defined(PIKE_CORE) || defined(DYNAMIC_MODULE) || defined(STATIC_MODULE) #include "pike_memory.h" #endif
6fc6ce2011-12-30Arne Goedeke 
f2b3bd2011-12-31Arne Goedeke #ifndef PMOD_EXPORT # warning WTF
3854832011-11-18Arne Goedeke #endif
fdfd282011-12-25Arne Goedeke 
e2499f2012-01-03Arne Goedeke #if defined(BA_DEBUG) || (!defined(PIKE_CORE) && !defined(DYNAMIC_MODULE) \ && !defined(STATIC_MODULES)) #endif PMOD_EXPORT char errbuf[8192];
c8b5902012-01-04Arne Goedeke static INLINE void ba_htable_insert(const struct block_allocator * a,
f2b3bd2011-12-31Arne Goedeke  const void * ptr, const ba_page_t n);
6fc6ce2011-12-30Arne Goedeke 
335e6a2012-01-04Arne Goedeke #define BA_NBLOCK(a, p, ptr) ((uintptr_t)((char*)ptr - (char)(p+1))/(a)->block_size)
e90c492011-11-27Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke #define BA_DIVIDE(a, b) ((a) / (b) + (!!((a) & ((b)-1))))
a5e1b82011-11-09Arne Goedeke #define BA_PAGESIZE(a) ((a)->blocks * (a)->block_size)
3854832011-11-18Arne Goedeke #define BA_SPAGE_SIZE(a) (sizeof(struct ba_page) + (BA_DIVIDE((a)->blocks, sizeof(uintptr_t)*8) - 1)*sizeof(uintptr_t)) #define BA_HASH_MASK(a) (((a->allocated)) - 1)
e2499f2012-01-03Arne Goedeke #ifdef BA_HASH_THLD
335e6a2012-01-04Arne Goedeke # define BA_BYTES(a) ( (sizeof(ba_page) + ((a->allocated > BA_HASH_THLD) ? sizeof(ba_page_t) : 0)) * ((a)->allocated) )
e2499f2012-01-03Arne Goedeke #else
335e6a2012-01-04Arne Goedeke # define BA_BYTES(a) ( (sizeof(ba_page) + sizeof(ba_page_t)) * ((a)->allocated) )
e2499f2012-01-03Arne Goedeke #endif
3854832011-11-18Arne Goedeke 
e2499f2012-01-03Arne Goedeke #ifndef PIKE_MEM_RW_RANGE # define PIKE_MEM_RW_RANGE(x, y) #endif
67795d2011-11-11Arne Goedeke 
c8b5902012-01-04Arne Goedeke static INLINE void ba_realloc(struct block_allocator * a) {
4750752011-11-19Arne Goedeke  unsigned int i;
335e6a2012-01-04Arne Goedeke  ba_page * old;
6fc6ce2011-12-30Arne Goedeke  ba_page p;
335e6a2012-01-04Arne Goedeke  a->pages = (ba_page*)realloc(old = a->pages, BA_BYTES(a));
6fc6ce2011-12-30Arne Goedeke  if (unlikely(!a->pages)) {
e2499f2012-01-03Arne Goedeke  //a->pages = old; BA_ERROR("alloc of %lu bytes failed.", BA_BYTES(a));
67795d2011-11-11Arne Goedeke  } //fprintf(stderr, "realloc to size %u\n", a->allocated);
f2b3bd2011-12-31Arne Goedeke #ifdef BA_DEBUG
3854832011-11-18Arne Goedeke  memset((void*)BA_PAGE(a, a->num_pages+1), 0, BA_BYTES(a) - sizeof(struct ba_page)*a->num_pages); #endif
e2499f2012-01-03Arne Goedeke  a->htable = NULL;
6fc6ce2011-12-30Arne Goedeke  IF_HASH(
335e6a2012-01-04Arne Goedeke  a->htable = (ba_page_t*) (a->pages + a->allocated);
f2b3bd2011-12-31Arne Goedeke  memset(a->htable, 0, a->allocated * sizeof(ba_page_t));
6fc6ce2011-12-30Arne Goedeke  for (i = 0; i < a->num_pages; i++) { p = BA_PAGE(a, i+1); p->hchain = 0; ba_htable_insert(a, BA_LASTBLOCK(a, p), i+1); } ); #ifdef BA_DEBUG ba_check_allocator(a, "realloc", __FILE__, __LINE__); #endif
67795d2011-11-11Arne Goedeke }
a5e1b82011-11-09Arne Goedeke 
e2499f2012-01-03Arne Goedeke PMOD_EXPORT void ba_show_pages(struct block_allocator * a) { unsigned int i = 0; fprintf(stderr, "first: %p last_free: %p\n", a->first, a->last_free); for (i = 1; i <= a->num_pages; i++) { ba_page p = BA_PAGE(a, i);
335e6a2012-01-04Arne Goedeke  fprintf(stderr, "%d\t%f\t(%u %d) --> (prev: %p | next: %p)\n",
e2499f2012-01-03Arne Goedeke  i, p->blocks_used/(double)a->blocks * 100, p->blocks_used, p->blocks_used,
335e6a2012-01-04Arne Goedeke  p->prev, p->next);
e2499f2012-01-03Arne Goedeke  } }
c8b5902012-01-04Arne Goedeke PMOD_EXPORT INLINE void ba_init(struct block_allocator * a,
6fc6ce2011-12-30Arne Goedeke  uint32_t block_size, ba_page_t blocks) {
4750752011-11-19Arne Goedeke  uint32_t page_size = block_size * blocks;
3854832011-11-18Arne Goedeke 
e2499f2012-01-03Arne Goedeke  a->first = NULL; a->last_free = NULL;
335e6a2012-01-04Arne Goedeke  a->last_free_num = 0;
a5e1b82011-11-09Arne Goedeke 
0a3d342011-11-10Arne Goedeke  if ((page_size & (page_size - 1)) == 0)
67795d2011-11-11Arne Goedeke  a->magnitude = (uint16_t)ctz32(page_size);
a5e1b82011-11-09Arne Goedeke  else
67795d2011-11-11Arne Goedeke  a->magnitude = (uint16_t)ctz32(round_up32(page_size));
a5e1b82011-11-09Arne Goedeke 
0a3d342011-11-10Arne Goedeke  a->block_size = block_size;
e2499f2012-01-03Arne Goedeke  a->blocks = (1 << a->magnitude) / block_size;
a5e1b82011-11-09Arne Goedeke  a->num_pages = 0;
9387262011-12-25Arne Goedeke  a->empty_pages = 0;
e2499f2012-01-03Arne Goedeke  a->max_empty_pages = BA_MAX_EMPTY;
a5e1b82011-11-09Arne Goedeke 
67795d2011-11-11Arne Goedeke  // we start with management structures for 16 pages
6fc6ce2011-12-30Arne Goedeke  a->allocated = BA_ALLOC_INITIAL;
67795d2011-11-11Arne Goedeke  a->pages = NULL; ba_realloc(a); }
c8b5902012-01-04Arne Goedeke PMOD_EXPORT INLINE void ba_free_all(struct block_allocator * a) {
4750752011-11-19Arne Goedeke  unsigned int i;
67795d2011-11-11Arne Goedeke 
e2499f2012-01-03Arne Goedeke  if (!a->allocated) return;
67795d2011-11-11Arne Goedeke  for (i = 0; i < a->num_pages; i++) {
335e6a2012-01-04Arne Goedeke  ba_page p = BA_PAGE(a, i+1); PIKE_MEM_RW_RANGE(BA_BLOCKN(a, 0), BA_PAGESIZE(a)); free(p); BA_PAGE(a, i+1) = NULL;
a5e1b82011-11-09Arne Goedeke  }
67795d2011-11-11Arne Goedeke  a->num_pages = 0;
6fc6ce2011-12-30Arne Goedeke  a->empty_pages = 0;
e2499f2012-01-03Arne Goedeke  a->first = NULL; a->last_free = NULL; a->allocated = BA_ALLOC_INITIAL; ba_realloc(a); IF_HASH( memset(a->htable, 0, sizeof(*a->htable)*a->allocated); );
67795d2011-11-11Arne Goedeke }
c8b5902012-01-04Arne Goedeke PMOD_EXPORT INLINE void ba_count_all(struct block_allocator * a, size_t *num, size_t *size) {
4750752011-11-19Arne Goedeke  unsigned int i;
3854832011-11-18Arne Goedeke  size_t n = 0;
f2b3bd2011-12-31Arne Goedeke  //fprintf(stderr, "page_size: %u, pages: %u\n", BA_PAGESIZE(a), a->num_pages);
3854832011-11-18Arne Goedeke  *size = BA_BYTES(a) + a->num_pages * BA_PAGESIZE(a); for (i = 0; i < a->num_pages; i++) {
4750752011-11-19Arne Goedeke  n += BA_PAGE(a, i+1)->blocks_used;
3854832011-11-18Arne Goedeke  } *num = n; }
c8b5902012-01-04Arne Goedeke PMOD_EXPORT INLINE void ba_destroy(struct block_allocator * a) {
67795d2011-11-11Arne Goedeke  ba_free_all(a);
f2b3bd2011-12-31Arne Goedeke  PIKE_MEM_RW_RANGE(a->pages, BA_BYTES(a));
67795d2011-11-11Arne Goedeke  free(a->pages);
6fc6ce2011-12-30Arne Goedeke  a->allocated = 0;
e2499f2012-01-03Arne Goedeke  a->htable = NULL;
67795d2011-11-11Arne Goedeke  a->pages = NULL;
a5e1b82011-11-09Arne Goedeke }
c8b5902012-01-04Arne Goedeke static INLINE void ba_grow(struct block_allocator * a) {
3854832011-11-18Arne Goedeke  if (a->allocated) {
6fc6ce2011-12-30Arne Goedeke  // try to detect 32bit overrun? if (a->allocated >= ((ba_page_t)1 << (sizeof(ba_page_t)*8-1))) { Pike_error("too many pages.\n"); }
3854832011-11-18Arne Goedeke  a->allocated *= 2; ba_realloc(a); } else { ba_init(a, a->block_size, a->blocks); }
6fc6ce2011-12-30Arne Goedeke #ifdef BA_DEBUG ba_check_allocator(a, "ba_grow", __FILE__, __LINE__); #endif
67795d2011-11-11Arne Goedeke }
c8b5902012-01-04Arne Goedeke static INLINE void ba_shrink(struct block_allocator * a) {
67795d2011-11-11Arne Goedeke  a->allocated /= 2; ba_realloc(a); }
6fc6ce2011-12-30Arne Goedeke #define MIX(t) do { \ t ^= (t >> 20) ^ (t >> 12); \ t ^= (t >> 7) ^ (t >> 4); \ } while(0)
a5e1b82011-11-09Arne Goedeke 
c8b5902012-01-04Arne Goedeke static INLINE ba_page_t hash1(const struct block_allocator * a,
67795d2011-11-11Arne Goedeke  const void * ptr) { uintptr_t t = ((uintptr_t)ptr) >> a->magnitude;
a5e1b82011-11-09Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke  MIX(t); return (ba_page_t) t;
a5e1b82011-11-09Arne Goedeke }
c8b5902012-01-04Arne Goedeke static INLINE ba_page_t hash2(const struct block_allocator * a,
67795d2011-11-11Arne Goedeke  const void * ptr) { uintptr_t t = ((uintptr_t)ptr) >> a->magnitude;
a5e1b82011-11-09Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke  t++; MIX(t); return (ba_page_t) t; }
f2b3bd2011-12-31Arne Goedeke #ifdef BA_DEBUG PMOD_EXPORT void ba_print_htable(const struct block_allocator * a) {
6fc6ce2011-12-30Arne Goedeke  unsigned int i; ba_page p; fprintf(stderr, "allocated: %u\n", a->allocated); fprintf(stderr, "num_pages: %u\n", a->num_pages); fprintf(stderr, "max_empty_pages: %u\n", a->max_empty_pages); fprintf(stderr, "empty_pages: %u\n", a->empty_pages); fprintf(stderr, "magnitude: %u\n", a->magnitude); fprintf(stderr, "block_size: %u\n", a->block_size);
e2499f2012-01-03Arne Goedeke  IF_HASH( for (i = 0; i < a->allocated; i++) { ba_page_t n = a->htable[i]; ba_page_t hval; void * ptr; while (n) { p = BA_PAGE(a, n); ptr = BA_LASTBLOCK(a, p); hval = hash1(a, ptr);
335e6a2012-01-04Arne Goedeke  fprintf(stderr, "%u\t%X[%d]\t%p-%p\t%X (page %d)\n", i, hval, hval & BA_HASH_MASK(a), p+1, ptr, (unsigned int)((uintptr_t)ptr >> a->magnitude), n);
e2499f2012-01-03Arne Goedeke  n = p->hchain; }
6fc6ce2011-12-30Arne Goedeke  }
e2499f2012-01-03Arne Goedeke  );
a5e1b82011-11-09Arne Goedeke }
f2b3bd2011-12-31Arne Goedeke #endif
a5e1b82011-11-09Arne Goedeke  /* * insert the pointer to an allocated page into the * hashtable. uses linear probing and open allocation. */
c8b5902012-01-04Arne Goedeke static INLINE void ba_htable_insert(const struct block_allocator * a,
6fc6ce2011-12-30Arne Goedeke  const void * ptr, const ba_page_t n) { ba_page_t hval = hash1(a, ptr); ba_page_t * b = a->htable + (hval & BA_HASH_MASK(a)); #ifdef BA_DEBUG while (*b) { if (*b == n) { fprintf(stderr, "inserting (%p, %d) twice\n", ptr, n);
335e6a2012-01-04Arne Goedeke  fprintf(stderr, "is (%p, %d)\n", BA_PAGE(a, n)+1, n);
6fc6ce2011-12-30Arne Goedeke  Pike_error("double insert.\n"); return; } b = &BA_PAGE(a, *b)->hchain; } b = a->htable + (hval & BA_HASH_MASK(a)); #endif
3854832011-11-18Arne Goedeke 
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG fprintf(stderr, "replacing bucket %u with page %u by %u\n", hval & BA_HASH_MASK(a), *b, n); #endif
3854832011-11-18Arne Goedeke  BA_PAGE(a, n)->hchain = *b; *b = n; }
6fc6ce2011-12-30Arne Goedeke 
c8b5902012-01-04Arne Goedeke static INLINE void ba_htable_replace(const struct block_allocator * a,
6fc6ce2011-12-30Arne Goedeke  const void * ptr, const ba_page_t n, const ba_page_t new) { ba_page_t hval = hash1(a, ptr); ba_page_t * b = a->htable + (hval & BA_HASH_MASK(a));
3854832011-11-18Arne Goedeke  while (*b) { if (*b == n) { *b = new; BA_PAGE(a, new)->hchain = BA_PAGE(a, n)->hchain;
6fc6ce2011-12-30Arne Goedeke  BA_PAGE(a, n)->hchain = 0;
3854832011-11-18Arne Goedeke  return; } b = &BA_PAGE(a, *b)->hchain; }
6fc6ce2011-12-30Arne Goedeke #ifdef DEBUG fprintf(stderr, "ba_htable_replace(%p, %u, %u)\n", ptr, n, new); fprintf(stderr, "hval: %u, %u, %u\n", hval, hval & BA_HASH_MASK(a), BA_HASH_MASK(a)); ba_print_htable(a); Pike_error("did not find index to replace.\n") #endif
3854832011-11-18Arne Goedeke }
c8b5902012-01-04Arne Goedeke static INLINE void ba_htable_delete(const struct block_allocator * a,
6fc6ce2011-12-30Arne Goedeke  const void * ptr, const ba_page_t n) { ba_page_t hval = hash1(a, ptr); ba_page_t * b = a->htable + (hval & BA_HASH_MASK(a));
3854832011-11-18Arne Goedeke  while (*b) { if (*b == n) { *b = BA_PAGE(a, n)->hchain;
6fc6ce2011-12-30Arne Goedeke  BA_PAGE(a, n)->hchain = 0;
3854832011-11-18Arne Goedeke  return; } b = &BA_PAGE(a, *b)->hchain; }
6fc6ce2011-12-30Arne Goedeke #ifdef DEBUG
e2499f2012-01-03Arne Goedeke  ba_print_htable(a);
6fc6ce2011-12-30Arne Goedeke  fprintf(stderr, "ba_htable_delete(%p, %u)\n", ptr, n); Pike_error("did not find index to delete.\n") #endif
a5e1b82011-11-09Arne Goedeke }
c8b5902012-01-04Arne Goedeke static INLINE ba_page_t ba_htable_lookup(const struct block_allocator * a,
6fc6ce2011-12-30Arne Goedeke  const void * ptr) {
316eb42012-01-04Arne Goedeke #ifdef COUNT count_name = "hash"; #endif
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG
6fc6ce2011-12-30Arne Goedeke  int c = 0;
e2499f2012-01-03Arne Goedeke #endif ba_page_t n;
0a3d342011-11-10Arne Goedeke  ba_page p;
e2499f2012-01-03Arne Goedeke  n = a->htable[hash1(a, ptr) & BA_HASH_MASK(a)]; while (n) { p = BA_PAGE(a, n);
6fc6ce2011-12-30Arne Goedeke  if (BA_CHECK_PTR(a, p, ptr)) {
316eb42012-01-04Arne Goedeke  INC(good);
e2499f2012-01-03Arne Goedeke  return n;
6fc6ce2011-12-30Arne Goedeke  }
e2499f2012-01-03Arne Goedeke  n = p->hchain;
6fc6ce2011-12-30Arne Goedeke  }
e2499f2012-01-03Arne Goedeke  n = a->htable[hash2(a, ptr) & BA_HASH_MASK(a)]; while (n) { p = BA_PAGE(a, n);
6fc6ce2011-12-30Arne Goedeke  if (BA_CHECK_PTR(a, p, ptr)) {
316eb42012-01-04Arne Goedeke  if (a->htable[hash1(a, ptr) & BA_HASH_MASK(a)]) INC(ugly); else INC(bad);
e2499f2012-01-03Arne Goedeke  return n;
6fc6ce2011-12-30Arne Goedeke  }
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG if (c++ > a->allocated) {
6fc6ce2011-12-30Arne Goedeke  Pike_error("hash chain is infinite\n"); }
e2499f2012-01-03Arne Goedeke #endif n = p->hchain;
67795d2011-11-11Arne Goedeke  }
a5e1b82011-11-09Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke  return 0; }
67795d2011-11-11Arne Goedeke 
f2b3bd2011-12-31Arne Goedeke #ifdef BA_DEBUG
c8b5902012-01-04Arne Goedeke PMOD_EXPORT INLINE void ba_check_allocator(struct block_allocator * a,
6fc6ce2011-12-30Arne Goedeke  char *fun, char *file, int line) { unsigned int i = 0; int bad = 0;
67795d2011-11-11Arne Goedeke  ba_page p;
6fc6ce2011-12-30Arne Goedeke  if (a->empty_pages > a->num_pages) { fprintf(stderr, "too many empty pages.\n"); bad = 1; } for (i = 1; i <= a->num_pages; i++) { ba_page_t hval; int found = 0; ba_page_t n; p = BA_PAGE(a, i); if (p->blocks_used == a->blocks) { if (p->prev || p->next) {
335e6a2012-01-04Arne Goedeke  BA_ERROR("block is full but in list. next: %p prev: %p\n",
6fc6ce2011-12-30Arne Goedeke  p->next, p->prev); bad = 1;
67795d2011-11-11Arne Goedeke  } }
6fc6ce2011-12-30Arne Goedeke  IF_HASH( hval = hash1(a, BA_LASTBLOCK(a, p)); n = a->htable[hval & BA_HASH_MASK(a)]; while (n) { if (n == i) { found = 1; break; } n = BA_PAGE(a, n)->hchain;
67795d2011-11-11Arne Goedeke  }
6fc6ce2011-12-30Arne Goedeke  if (!found) { fprintf(stderr, "did not find page %d, %p (%u) in htable.\n", i, BA_LASTBLOCK(a, BA_PAGE(a, i)), hval); fprintf(stderr, "looking in bucket %u mask: %d\n", hval & BA_HASH_MASK(a), BA_HASH_MASK(a)); bad = 1; } for (i = 0; i < a->allocated; i++) { n = a->htable[i]; while (n) { p = BA_PAGE(a, n); hval = hash1(a, BA_LASTBLOCK(a, p)); if (i != (hval & BA_HASH_MASK(a))) { fprintf(stderr, "page %u found in wrong bucket %d\n", n, i); bad = 1; } n = p->hchain; } } ); } if (bad) { ba_print_htable(a); fprintf(stderr, "\nCalled from %s:%d:%s\n", fun, line, file); fprintf(stderr, "pages: %u\n", a->num_pages); Pike_error("bad");
a5e1b82011-11-09Arne Goedeke  } }
f2b3bd2011-12-31Arne Goedeke #endif
a5e1b82011-11-09Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke 
c8b5902012-01-04Arne Goedeke PMOD_EXPORT INLINE void * ba_low_alloc(struct block_allocator * a) {
e90c492011-11-27Arne Goedeke  //fprintf(stderr, "ba_alloc(%p)\n", a);
a5e1b82011-11-09Arne Goedeke  ba_page p;
6fc6ce2011-12-30Arne Goedeke #ifdef BA_DEBUG ba_check_allocator(a, "ba_alloc top", __FILE__, __LINE__); #endif
e2499f2012-01-03Arne Goedeke  unsigned int i;
d2892b2011-12-25Arne Goedeke 
e90c492011-11-27Arne Goedeke  //fprintf(stderr, "allocating new page. was %p\n", p);
6fc6ce2011-12-30Arne Goedeke  if (unlikely(a->num_pages == a->allocated)) {
3854832011-11-18Arne Goedeke  ba_grow(a);
6fc6ce2011-12-30Arne Goedeke  } #ifdef BA_DEBUG ba_check_allocator(a, "ba_alloc after grow", __FILE__, __LINE__); #endif
3854832011-11-18Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke  a->num_pages++; #ifdef BA_DEBUG
335e6a2012-01-04Arne Goedeke  if (BA_PAGE(a, a->num_pages)) {
6fc6ce2011-12-30Arne Goedeke  void * new = malloc(BA_PAGESIZE(a)); fprintf(stderr, "reusing unfreed page %d, data: %p -> %p\n", a->num_pages,
335e6a2012-01-04Arne Goedeke  p+1, new);
e2499f2012-01-03Arne Goedeke  a->num_pages--; ba_show_pages(a); a->num_pages++;
335e6a2012-01-04Arne Goedeke  BA_PAGE(a, a->num_pages) = p = new;
6fc6ce2011-12-30Arne Goedeke  } else #endif
335e6a2012-01-04Arne Goedeke  BA_PAGE(a, a->num_pages) = p = (ba_page)malloc(sizeof(struct ba_page) + BA_PAGESIZE(a)); if (!p) {
6fc6ce2011-12-30Arne Goedeke  Pike_error("no mem. alloc returned zero.");
a5e1b82011-11-09Arne Goedeke  }
335e6a2012-01-04Arne Goedeke  p->next = p->prev = NULL;
e2499f2012-01-03Arne Goedeke  a->first = p;
6fc6ce2011-12-30Arne Goedeke  IF_HASH( ba_htable_insert(a, BA_LASTBLOCK(a, p), a->num_pages); #ifdef BA_DEBUG ba_check_allocator(a, "ba_alloc after insert", __FILE__, __LINE__); #endif );
3854832011-11-18Arne Goedeke  p->blocks_used = 1;
f2b3bd2011-12-31Arne Goedeke  p->first = BA_BLOCKN(a, p, 1);
0639aa2012-01-04Arne Goedeke  for (i = 1; i+1 < a->blocks; i++) {
6fc6ce2011-12-30Arne Goedeke #ifdef BA_DEBUG
e2499f2012-01-03Arne Goedeke  PIKE_MEM_RW(BA_BLOCKN(a, p, i)->magic);
6fc6ce2011-12-30Arne Goedeke  BA_BLOCKN(a, p, i)->magic = BA_MARK_FREE; #endif
0639aa2012-01-04Arne Goedeke  BA_BLOCKN(a, p, i)->next = BA_BLOCKN(a, p, i+1);
6fc6ce2011-12-30Arne Goedeke  }
f2b3bd2011-12-31Arne Goedeke  BA_LASTBLOCK(a, p)->next = NULL;
6fc6ce2011-12-30Arne Goedeke  //memset(p->data, 0x00, BA_PAGESIZE(a)); #ifdef BA_DEBUG
e2499f2012-01-03Arne Goedeke  PIKE_MEM_RW(BA_LASTBLOCK(a, p)->magic);
f2b3bd2011-12-31Arne Goedeke  BA_LASTBLOCK(a, p)->magic = BA_MARK_FREE;
e2499f2012-01-03Arne Goedeke  PIKE_MEM_RW(BA_BLOCKN(a, p, 0)->magic);
6fc6ce2011-12-30Arne Goedeke  BA_BLOCKN(a, p, 0)->magic = BA_MARK_ALLOC; ba_check_allocator(a, "ba_alloc after insert", __FILE__, __LINE__);
3854832011-11-18Arne Goedeke #endif
335e6a2012-01-04Arne Goedeke  return BA_BLOCKN(a, p, 0);
a5e1b82011-11-09Arne Goedeke }
c8b5902012-01-04Arne Goedeke PMOD_EXPORT INLINE void ba_low_free(struct block_allocator * a,
335e6a2012-01-04Arne Goedeke  void * ptr, ba_page p, ba_page_t n) {
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG ba_check_allocator(a, "ba_low_free", __FILE__, __LINE__);
6fc6ce2011-12-30Arne Goedeke #endif
e2499f2012-01-03Arne Goedeke  if (!p) {
6fc6ce2011-12-30Arne Goedeke #ifdef BA_HASH_THLD
e2499f2012-01-03Arne Goedeke  if (a->allocated <= BA_HASH_THLD) BA_ERROR("ba_low_free(.., %p) should never be called: %d, %d\n", ptr, a->allocated, BA_HASH_THLD);
6fc6ce2011-12-30Arne Goedeke #endif
335e6a2012-01-04Arne Goedeke  n = ba_htable_lookup(a, ptr);
e2499f2012-01-03Arne Goedeke  if (n) { a->last_free = p = BA_PAGE(a, n);
335e6a2012-01-04Arne Goedeke  a->last_free_num = n;
e2499f2012-01-03Arne Goedeke  } else {
d2892b2011-12-25Arne Goedeke #ifdef BA_DEBUG
e2499f2012-01-03Arne Goedeke  fprintf(stderr, "magnitude: %u\n", a->magnitude); fprintf(stderr, "allocated: %u\n", a->allocated); fprintf(stderr, "did not find %p (%X[%X] | %X[%X])\n", ptr, hash1(a, ptr), hash1(a, ptr) & BA_HASH_MASK(a), hash2(a, ptr), hash2(a, ptr) & BA_HASH_MASK(a) ); ba_print_htable(a);
d2892b2011-12-25Arne Goedeke #endif
e2499f2012-01-03Arne Goedeke  BA_ERROR("Unknown pointer (not found in hash) %p\n", ptr); } } if (p->blocks_used == a->blocks) {
335e6a2012-01-04Arne Goedeke  if (a->first) { a->first->prev = p;
e2499f2012-01-03Arne Goedeke  }
335e6a2012-01-04Arne Goedeke  p->next = a->first; p->prev = NULL;
e2499f2012-01-03Arne Goedeke  a->first = p; p->first = NULL; } else if (p->blocks_used == 1 && a->empty_pages > a->max_empty_pages) { a->empty_pages--;
335e6a2012-01-04Arne Goedeke  ba_remove_page(a, n);
e2499f2012-01-03Arne Goedeke  return;
67795d2011-11-11Arne Goedeke  }
6fc6ce2011-12-30Arne Goedeke #ifdef BA_DEBUG
e2499f2012-01-03Arne Goedeke  if ((int)p->blocks_used <= 0) { fprintf(stderr, "MEGAFAIL in page %u at %p: %d %u\n", 1 + (a->pages - p), p, p->blocks_used, p->blocks_used); ba_show_pages(a);
6fc6ce2011-12-30Arne Goedeke  }
3854832011-11-18Arne Goedeke #endif
e2499f2012-01-03Arne Goedeke  p->blocks_used --; #ifdef BA_DEBUG if (((ba_block_header)ptr)->magic == BA_MARK_FREE) { fprintf(stderr, "double freed somethign\n"); } //memset(ptr, 0x75, a->block_size); ((ba_block_header)ptr)->magic = BA_MARK_FREE; #endif ((ba_block_header)ptr)->next = p->first; //fprintf(stderr, "setting first to %u (%p vs %p) n: %u vs %u\n", t+1, BA_BLOCKN(a, p, t+1), ptr, BA_NBLOCK(a, p, BA_BLOCKN(a, p, t+1)), BA_NBLOCK(a, p, ptr)); p->first = ptr;
3854832011-11-18Arne Goedeke }
f2b3bd2011-12-31Arne Goedeke 
c8b5902012-01-04Arne Goedeke PMOD_EXPORT INLINE void ba_remove_page(struct block_allocator * a,
e2499f2012-01-03Arne Goedeke  ba_page_t n) {
3854832011-11-18Arne Goedeke  ba_page tmp, p;
6fc6ce2011-12-30Arne Goedeke #ifdef BA_DEBUG ba_check_allocator(a, "ba_remove_page", __FILE__, __LINE__); if (a->empty_pages < a->max_empty_pages) { Pike_error("strange things happening\n"); } #endif
3854832011-11-18Arne Goedeke  p = BA_PAGE(a, n);
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG fprintf(stderr, "> ===============\n"); ba_show_pages(a); ba_print_htable(a); fprintf(stderr, "removing page %4u[%p]\t(%p .. %p) -> %X (%X) (of %u).\n", n, p,
335e6a2012-01-04Arne Goedeke  p+1, BA_LASTBLOCK(a, p), hash1(a, BA_LASTBLOCK(a,p)),
3854832011-11-18Arne Goedeke  hash1(a, BA_LASTBLOCK(a,p)) & BA_HASH_MASK(a), a->num_pages);
e2499f2012-01-03Arne Goedeke #endif
3854832011-11-18Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke  IF_HASH( ba_htable_delete(a, BA_LASTBLOCK(a, p), n); );
335e6a2012-01-04Arne Goedeke  PIKE_MEM_RW_RANGE(*p, BA_PAGESIZE(a));
3854832011-11-18Arne Goedeke 
e2499f2012-01-03Arne Goedeke  if (a->last_free == p) a->last_free = NULL;
3854832011-11-18Arne Goedeke  if (p->prev) {
335e6a2012-01-04Arne Goedeke  p->prev->next = p->next;
3854832011-11-18Arne Goedeke  } else {
e2499f2012-01-03Arne Goedeke  if (p->next) {
335e6a2012-01-04Arne Goedeke  a->first = p->next; a->first->prev = NULL;
e2499f2012-01-03Arne Goedeke  } else a->first = NULL;
3854832011-11-18Arne Goedeke  } if (p->next) {
335e6a2012-01-04Arne Goedeke  p->next->prev = p->prev;
3854832011-11-18Arne Goedeke  }
de2d072011-12-25Arne Goedeke  if (a->num_pages != n) { tmp = BA_PAGE(a, a->num_pages);
6fc6ce2011-12-30Arne Goedeke  // page tmp will have index changed to n
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG fprintf(stderr, "removing last from htable\n"); #endif
6fc6ce2011-12-30Arne Goedeke  IF_HASH( ba_htable_delete(a, BA_LASTBLOCK(a, tmp), a->num_pages); );
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG ba_print_htable(a); fprintf(stderr, "fooo\n"); fprintf(stderr, "replacing with page %4u[%p]\t(%p .. %p) -> %X (%X) (of %u).\n", a->num_pages, tmp, tmp->data, BA_LASTBLOCK(a, tmp), hash1(a, BA_LASTBLOCK(a,tmp)), hash1(a, BA_LASTBLOCK(a,tmp)) & BA_HASH_MASK(a), a->num_pages);
de2d072011-12-25Arne Goedeke  /* fprintf(stderr, "replacing with page %u\t(%p .. %p) -> %X (%X)\n", a->num_pages, tmp->data, BA_LASTBLOCK(a, tmp), hash1(a, BA_LASTBLOCK(a,tmp)), hash1(a, BA_LASTBLOCK(a,tmp)) & BA_HASH_MASK(a) ); */
e2499f2012-01-03Arne Goedeke #endif
335e6a2012-01-04Arne Goedeke  BA_PAGE(a, n) = BA_PAGE(a, a->num_pages); if (tmp == a->last_free) { a->last_free_num = n; }
6fc6ce2011-12-30Arne Goedeke  IF_HASH( // ba_htable_replace(a, BA_LASTBLOCK(a, tmp), a->num_pages, n); ba_htable_insert(a, BA_LASTBLOCK(a, tmp), n); );
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG ba_print_htable(a); fprintf(stderr, "fooo\n"); #endif
de2d072011-12-25Arne Goedeke  }
d2892b2011-12-25Arne Goedeke #ifdef BA_DEBUG
e2499f2012-01-03Arne Goedeke  memset(BA_PAGE(a, a->num_pages), 0, sizeof(struct ba_page)); if (a->first == BA_PAGE(a, a->num_pages)) {
d2892b2011-12-25Arne Goedeke  fprintf(stderr, "a->first will be old removed page %d\n", a->first);
335e6a2012-01-04Arne Goedeke  fprintf(stderr, "page %d was not moved and prev was %p\n", n, p->prev);
d2892b2011-12-25Arne Goedeke  } #endif
3854832011-11-18Arne Goedeke  a->num_pages--;
335e6a2012-01-04Arne Goedeke  free(p);
6fc6ce2011-12-30Arne Goedeke  #ifdef BA_DEBUG ba_check_allocator(a, "ba_remove_page", __FILE__, __LINE__); #endif
e2499f2012-01-03Arne Goedeke  if (a->allocated > BA_ALLOC_INITIAL && a->num_pages <= (a->allocated >> 2)) {
6fc6ce2011-12-30Arne Goedeke  ba_shrink(a); }
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG ba_show_pages(a); ba_print_htable(a); fprintf(stderr, "< =================\n"); #endif
a5e1b82011-11-09Arne Goedeke }