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 
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
41889b2012-01-10Arne Goedeke #include "block_allocator.h"
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 
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)) {
41889b2012-01-10Arne Goedeke  //a->pages = old; // TODO we do need this
e2499f2012-01-03Arne Goedeke  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
41889b2012-01-10Arne Goedeke  memset((void*)(a->pages + a->num_pages), 0, BA_BYTES(a) - sizeof(ba_page)*a->num_pages);
3854832011-11-18Arne Goedeke #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 
41889b2012-01-10Arne Goedeke #define PRINT_NODE(a, name) do {\ fprintf(stderr, #name": %p[%u]\n", a->name, a->name ? a->name->n : 0);\ } while (0)
e2499f2012-01-03Arne Goedeke PMOD_EXPORT void ba_show_pages(struct block_allocator * a) { unsigned int i = 0;
41889b2012-01-10Arne Goedeke  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); PRINT_NODE(a, empty); PRINT_NODE(a, first); PRINT_NODE(a, last_free);
e2499f2012-01-03Arne Goedeke  for (i = 1; i <= a->num_pages; i++) { ba_page p = BA_PAGE(a, i);
41889b2012-01-10Arne Goedeke  ba_block_t blocks_used; if (p == a->first) {
2861c22012-01-28Arne Goedeke  blocks_used = 0;
41889b2012-01-10Arne Goedeke  } else {
2861c22012-01-28Arne Goedeke  blocks_used = p->used;
41889b2012-01-10Arne Goedeke  } fprintf(stderr, "%d(%p[%u])\t%f\t(%u %d) --> (prev: %p[%u] | next: %p[%u])\n", i, p, p->n, blocks_used/(double)a->blocks * 100, blocks_used, blocks_used, p->prev, BA_NUM(p->prev), p->next, BA_NUM(p->next));
e2499f2012-01-03Arne Goedeke  } }
d947bc2012-01-06Arne Goedeke //#define BA_ALIGNMENT 8
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) {
d947bc2012-01-06Arne Goedeke  uint32_t page_size; #ifdef BA_ALIGNMENT if (block_size & (BA_ALIGNMENT - 1)) block_size += (BA_ALIGNMENT - (block_size & (BA_ALIGNMENT - 1))); #endif page_size = block_size * blocks;
41889b2012-01-10Arne Goedeke  a->offset = sizeof(struct ba_page) + page_size - block_size;
3854832011-11-18Arne Goedeke 
41889b2012-01-10Arne Goedeke  a->first_blk = NULL; a->empty = a->first = a->last_free = NULL;
a5e1b82011-11-09Arne Goedeke 
25a9422012-01-06Arne Goedeke  if ((page_size & (page_size - 1))) { page_size = round_up32(page_size); a->blocks = page_size/block_size; } else a->blocks = blocks;
a5e1b82011-11-09Arne Goedeke 
25a9422012-01-06Arne Goedeke  a->magnitude = (uint16_t)ctz32(page_size);
0a3d342011-11-10Arne Goedeke  a->block_size = 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); }
2861c22012-01-28Arne Goedeke static INLINE void ba_free_page(struct block_allocator * a, ba_page p) { p->first = BA_BLOCKN(a, p, 0); p->used = 0; if (a->blueprint) { //xmemset(p+1, a->blueprint, a->block_size, a->blocks); size_t len = (a->blocks - 1) * a->block_size, clen = a->block_size; p++; memcpy(p, a->blueprint, a->block_size); while (len > clen) { memcpy(((char*)(p)) + clen, p, clen); len -= clen; clen <<= 1; } if (len) memcpy(((char*)(p)) + clen, p, len); p--; } do { char * ptr = (char*)(p+1); while (ptr < BA_LASTBLOCK(a, p)) { #ifdef BA_DEBUG PIKE_MEM_RW(((ba_block_header)ptr)->magic); ((ba_block_header)ptr)->magic = BA_MARK_FREE; #endif ((ba_block_header)ptr)->next = (ba_block_header)(ptr+a->block_size); ptr+=a->block_size; } BA_LASTBLOCK(a, p)->next = NULL; } while (0); }
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;
41889b2012-01-10Arne Goedeke  a->empty = a->first = a->last_free = NULL; a->first_blk = NULL;
e2499f2012-01-03Arne Goedeke  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++) {
41889b2012-01-10Arne Goedeke  ba_page p = a->pages[i];
2861c22012-01-28Arne Goedeke  n+= p->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))) {
41889b2012-01-10Arne Goedeke  BA_ERROR("too many pages.\n");
6fc6ce2011-12-30Arne Goedeke  }
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;
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);
41889b2012-01-10Arne Goedeke  BA_ERROR("double insert.\n");
6fc6ce2011-12-30Arne Goedeke  return; } b = &BA_PAGE(a, *b)->hchain; } b = a->htable + (hval & BA_HASH_MASK(a)); #endif
3854832011-11-18Arne Goedeke 
41889b2012-01-10Arne Goedeke #if 0//def BA_DEBUG
e2499f2012-01-03Arne Goedeke  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);
41889b2012-01-10Arne Goedeke  BA_ERROR("did not find index to replace.\n")
6fc6ce2011-12-30Arne Goedeke #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);
41889b2012-01-10Arne Goedeke  BA_ERROR("did not find index to delete.\n")
6fc6ce2011-12-30Arne Goedeke #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) {
41889b2012-01-10Arne Goedeke  ba_page p; ba_page_t n1, n2;
316eb42012-01-04Arne Goedeke #ifdef COUNT count_name = "hash"; #endif
0de0072012-01-06Arne Goedeke  n1 = a->htable[hash1(a, ptr) & BA_HASH_MASK(a)]; n2 = a->htable[hash2(a, ptr) & BA_HASH_MASK(a)]; while (n1 || n2) { if (n1) { p = BA_PAGE(a, n1); if (BA_CHECK_PTR(a, p, ptr)) { return n1; } n1 = p->hchain;
6fc6ce2011-12-30Arne Goedeke  }
0de0072012-01-06Arne Goedeke  if (n2) { p = BA_PAGE(a, n2); if (BA_CHECK_PTR(a, p, ptr)) { return n2; } n2 = p->hchain;
6fc6ce2011-12-30Arne Goedeke  }
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);
41889b2012-01-10Arne Goedeke  if (p->n != i) { fprintf(stderr, "wrong number %u found in block %p[%u]\n", p->n, p, i); bad = 1; } if (!p->first && p != a->first) {
6fc6ce2011-12-30Arne Goedeke  if (p->prev || p->next) {
41889b2012-01-10Arne Goedeke  fprintf(stderr, "page %p[%u] is full but in list. next: %p[%u]" "prev: %p[%u]\n", p, BA_NUM(p), p->next, BA_NUM(p->next), p->prev, BA_NUM(p->prev));
6fc6ce2011-12-30Arne Goedeke  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; } }
41889b2012-01-10Arne Goedeke  if (bad) ba_print_htable(a);
6fc6ce2011-12-30Arne Goedeke  ); } if (bad) {
41889b2012-01-10Arne Goedeke  ba_show_pages(a);
6fc6ce2011-12-30Arne Goedeke  fprintf(stderr, "\nCalled from %s:%d:%s\n", fun, line, file); fprintf(stderr, "pages: %u\n", a->num_pages);
41889b2012-01-10Arne Goedeke  BA_ERROR("bad");
a5e1b82011-11-09Arne Goedeke  } }
f2b3bd2011-12-31Arne Goedeke #endif
a5e1b82011-11-09Arne Goedeke 
41889b2012-01-10Arne Goedeke static INLINE void ba_alloc_page(struct block_allocator * a) {
a5e1b82011-11-09Arne Goedeke  ba_page p;
e2499f2012-01-03Arne Goedeke  unsigned int i;
2861c22012-01-28Arne Goedeke  void * ptr;
d2892b2011-12-25Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke  if (unlikely(a->num_pages == a->allocated)) {
3854832011-11-18Arne Goedeke  ba_grow(a);
6fc6ce2011-12-30Arne Goedeke  }
3854832011-11-18Arne Goedeke 
6fc6ce2011-12-30Arne Goedeke  a->num_pages++;
2861c22012-01-28Arne Goedeke  ptr = malloc(BA_PAGESIZE(a)); if (!ptr) BA_ERROR("no mem. alloc returned zero.");
6fc6ce2011-12-30Arne Goedeke #ifdef BA_DEBUG
335e6a2012-01-04Arne Goedeke  if (BA_PAGE(a, a->num_pages)) {
6fc6ce2011-12-30Arne Goedeke  fprintf(stderr, "reusing unfreed page %d, data: %p -> %p\n", a->num_pages,
2861c22012-01-28Arne Goedeke  p+1, ptr);
e2499f2012-01-03Arne Goedeke  a->num_pages--; ba_show_pages(a); a->num_pages++;
6fc6ce2011-12-30Arne Goedeke  } else #endif
2861c22012-01-28Arne Goedeke  BA_PAGE(a, a->num_pages) = p = (ba_page)ptr;
41889b2012-01-10Arne Goedeke  p->n = a->num_pages; #ifdef BA_DEBUG if (!p->n) BA_ERROR("num pages cannot be zero\n"); #endif
2861c22012-01-28Arne Goedeke  ba_free_page(a, p);
335e6a2012-01-04Arne Goedeke  p->next = p->prev = NULL;
41889b2012-01-10Arne Goedeke  a->last = 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 ); #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
a5e1b82011-11-09Arne Goedeke }
41889b2012-01-10Arne Goedeke PMOD_EXPORT void ba_low_alloc(struct block_allocator * a) { //fprintf(stderr, "ba_alloc(%p)\n", a);
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG
41889b2012-01-10Arne Goedeke  ba_check_allocator(a, "ba_alloc top", __FILE__, __LINE__);
1133892012-01-06Arne Goedeke #endif
41889b2012-01-10Arne Goedeke  //fprintf(stderr, "allocating new page. was %p\n", p); if (a->first) { ba_page p = a->first; if (p->next) a->first = p->next; else a->first = a->last = NULL; p->prev = NULL; p->next = NULL; p->first = NULL;
2861c22012-01-28Arne Goedeke  p->used = a->blocks;
e2499f2012-01-03Arne Goedeke  }
41889b2012-01-10Arne Goedeke  if (a->first) {
2861c22012-01-28Arne Goedeke #ifdef BA_DEBUG
41889b2012-01-10Arne Goedeke  if (!a->first->first) { ba_show_pages(a); BA_ERROR("no free blk in page %p[%u]\n", a->first, BA_NUM(a->first));
e2499f2012-01-03Arne Goedeke  }
41889b2012-01-10Arne Goedeke #endif a->first->prev = NULL; } else if (a->empty_pages) { a->last = a->first = a->empty; a->empty = a->empty->next;
e2499f2012-01-03Arne Goedeke  a->empty_pages--;
41889b2012-01-10Arne Goedeke  a->first->next = NULL; } else ba_alloc_page(a);
2861c22012-01-28Arne Goedeke #ifdef BA_DEBUG
41889b2012-01-10Arne Goedeke  if (!a->first->first) { ba_show_pages(a); BA_ERROR("a->first has no first block!\n"); } #endif #ifdef BA_DEBUG ba_check_allocator(a, "ba_alloc after grow", __FILE__, __LINE__); #endif a->first_blk = a->first->first; }
2861c22012-01-28Arne Goedeke PMOD_EXPORT void ba_low_free(struct block_allocator * a, ba_page p, ba_block_header ptr) { // page was full if (unlikely(!ptr->next)) {
41889b2012-01-10Arne Goedeke 
2861c22012-01-28Arne Goedeke  if (a->first) { p->prev = a->last; a->last->next = p; a->last = p; p->first = ptr; } else { p->prev = p->next = NULL; a->first = a->last = p; a->first_blk = ptr; } } else if (!p->used) { if (a->empty_pages == a->max_empty_pages) { ba_remove_page(a, p); return; } if (p->next) p->next->prev = p->prev; else a->last = p->prev; if (p->prev) { p->prev->next = p->next; p->prev = NULL; } a->last_free = NULL; p->next = a->empty; a->empty = p; a->empty_pages ++;
41889b2012-01-10Arne Goedeke  } } PMOD_EXPORT void ba_find_page(struct block_allocator * a, const void * ptr) { ba_page_t n;
6fc6ce2011-12-30Arne Goedeke #ifdef BA_DEBUG
41889b2012-01-10Arne Goedeke  ba_check_allocator(a, "ba_low_free", __FILE__, __LINE__); #endif #ifdef BA_HASH_THLD if (a->num_pages <= BA_HASH_THLD) { for (n = 0; n < a->num_pages; n++) { if (BA_CHECK_PTR(a, a->pages[n], ptr)) { a->last_free = a->pages[n]; return; } } } else { #endif n = ba_htable_lookup(a, ptr); if (n) { a->last_free = BA_PAGE(a, n); return; } #ifdef BA_HASH_THLD
6fc6ce2011-12-30Arne Goedeke  }
3854832011-11-18Arne Goedeke #endif
e2499f2012-01-03Arne Goedeke #ifdef BA_DEBUG
41889b2012-01-10Arne 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);
e2499f2012-01-03Arne Goedeke #endif
41889b2012-01-10Arne Goedeke  BA_ERROR("Unknown pointer (not found in hash) %p\n", ptr);
3854832011-11-18Arne Goedeke }
f2b3bd2011-12-31Arne Goedeke 
41889b2012-01-10Arne Goedeke PMOD_EXPORT void ba_remove_page(struct block_allocator * a, ba_page p) { ba_page_t n = p->n; ba_page tmp;
6fc6ce2011-12-30Arne Goedeke #ifdef BA_DEBUG ba_check_allocator(a, "ba_remove_page", __FILE__, __LINE__); if (a->empty_pages < a->max_empty_pages) {
41889b2012-01-10Arne Goedeke  BA_ERROR("strange things happening\n"); } if (p == a->first) { BA_ERROR("removing first page. this is not supposed to happen\n");
6fc6ce2011-12-30Arne Goedeke  } #endif
3854832011-11-18Arne Goedeke 
41889b2012-01-10Arne Goedeke #if 0//def BA_DEBUG
e2499f2012-01-03Arne Goedeke  fprintf(stderr, "> ===============\n"); ba_show_pages(a); ba_print_htable(a);
41889b2012-01-10Arne Goedeke  fprintf(stderr, "removing page %4u[%p]\t(%p .. %p) -> %X (%X) (of %u).\n", n, p, 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 
41889b2012-01-10Arne Goedeke  // we know that p == a->last_free a->last_free = NULL;
3854832011-11-18Arne Goedeke 
41889b2012-01-10Arne Goedeke  if (p->prev) p->prev->next = p->next; if (p->next) p->next->prev = p->prev; else a->last = 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 IF_HASH( ba_htable_delete(a, BA_LASTBLOCK(a, tmp), a->num_pages); );
41889b2012-01-10Arne Goedeke #if 0//def BA_DEBUG
e2499f2012-01-03Arne Goedeke  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,
41889b2012-01-10Arne Goedeke  tmp+1, BA_LASTBLOCK(a, tmp), hash1(a, BA_LASTBLOCK(a,tmp)),
e2499f2012-01-03Arne Goedeke  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
41889b2012-01-10Arne Goedeke  BA_PAGE(a, n) = tmp; tmp->n = 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); );
41889b2012-01-10Arne Goedeke #if 0//def BA_DEBUG
e2499f2012-01-03Arne Goedeke  ba_print_htable(a); fprintf(stderr, "fooo\n"); #endif
de2d072011-12-25Arne Goedeke  }
d2892b2011-12-25Arne Goedeke #ifdef BA_DEBUG
41889b2012-01-10Arne Goedeke  memset(p, 0, sizeof(struct ba_page)); if (a->first == p) { fprintf(stderr, "a->first will be old removed page %p\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  }
41889b2012-01-10Arne Goedeke  BA_PAGE(a, a->num_pages) = NULL;
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); }
41889b2012-01-10Arne Goedeke #if 0//def BA_DEBUG
e2499f2012-01-03Arne Goedeke  ba_show_pages(a); ba_print_htable(a); fprintf(stderr, "< =================\n"); #endif
a5e1b82011-11-09Arne Goedeke }