pike.git / src / block_allocator.c

version» Context lines:

pike.git/src/block_allocator.c:1:   #include <stdlib.h>   #include <string.h>   #include <stdint.h>    - #include "bitvector.h" - //#include "pike_error.h" + #include "post_modules/Critbit/bitvector.h" + #define __PIKE__ + #ifdef __PIKE__ + # include "pike_error.h" + #endif    -  + #define BA_SEGREGATE +    struct ba_page {    char * data;    uint16_t next, prev;    uint16_t hchain;   #ifdef BA_SEGREGATE    uint16_t blocks_used, first;   #else    uint16_t blocks_used;    uint16_t free_mask;    uintptr_t mask[1];
pike.git/src/block_allocator.c:24:   };   #endif      #include "block_allocator.h"      static inline void ba_htable_insert(const struct block_allocator * a,    const void * ptr, const uint16_t n);   static inline void ba_remove_page(struct block_allocator * a,    uint16_t n);    + #define BA_BLOCKN(a, p, n) ((void*)(((p)->data) + (n)*((a)->block_size))) + #define BA_LASTBLOCK(a, p) BA_BLOCKN(a, p, (a)->blocks - 1) + #define BA_NBLOCK(a, p, ptr) ((uintptr_t)((char*)ptr - (p)->data)/(a)->block_size) +    #define BA_DIVIDE(a, b) ((a) / (b) + !!((a) & ((b)-1)))   #define BA_PAGESIZE(a) ((a)->blocks * (a)->block_size)   #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)   #define BA_CHECK_PTR(a, p, ptr) ((char*)ptr >= p->data && BA_LASTBLOCK(a,p) >= ptr)      #ifdef BA_SEGREGATE   # define BA_PAGE(a, n) ((a)->pages + (n) - 1)   # define BA_BYTES(a) ( (sizeof(struct ba_page) + sizeof(uint16_t)) * ((a)->allocated) )   #else   # define BA_PAGE(a, n) ((ba_page)((char*)(a)->pages + ((n)-1) * ((a)->ba_page_size)))   # define BA_BYTES(a) (( (a)->ba_page_size + sizeof(uint16_t)) * ((a)->allocated))   # define BA_LAST_BITS(a) ((a)->blocks & (sizeof(uintptr_t)*8 - 1))   # define BA_LAST_MASK(a) (BA_LAST_BITS(a) ? TMASK(uintptr_t, BA_LAST_BITS(a)) : ~((uintptr_t)0))   # define BA_MASK_NUM(a) (((a)->ba_page_size - sizeof(struct ba_page) + sizeof(uintptr_t))/sizeof(uintptr_t))   #endif    - #define BA_BLOCKN(a, p, n) ((void*)(((p)->data) + (n)*((a)->block_size))) - #define BA_LASTBLOCK(a, p) BA_BLOCKN(a, p, (a)->blocks - 1) +     -  - #ifndef PIKE_ERROR_H + #ifndef __PIKE__   #include <stdio.h>   #include <unistd.h>      void Pike_error(char * msg) {    fprintf(stderr, "ERROR: %s\n", msg);    _exit(1);   }   #endif      static inline void ba_realloc(struct block_allocator * a) {
pike.git/src/block_allocator.c:120:    free(BA_PAGE(a, i+1)->data);    }    a->num_pages = 0;    a->first = a->last = 0;   }      void ba_count_all(struct block_allocator * a, size_t *num, size_t *size) {    unsigned int i;    size_t n = 0;    +  fprintf(stderr, "page_size: %u, pages: %u\n", BA_PAGESIZE(a), a->num_pages);    *size = BA_BYTES(a) + a->num_pages * BA_PAGESIZE(a);    for (i = 0; i < a->num_pages; i++) {    n += BA_PAGE(a, i+1)->blocks_used;    }       *num = n;   }      void ba_destroy(struct block_allocator * a) {    ba_free_all(a);
pike.git/src/block_allocator.c:216:    b = &BA_PAGE(a, *b)->hchain;    }   }      void ba_print_htable(struct block_allocator * a) {    int i;    ba_page p;       fprintf(stderr, "allocated: %u\n", a->allocated*2);    fprintf(stderr, "magnitude: %u\n", a->magnitude); +  fprintf(stderr, "block_size: %u\n", a->block_size);       for (i = 0; i < a->allocated; i++) {    uint16_t n = a->htable[i];    unsigned int hval;    void * ptr; -  if (n) { +  while (n) {    p = BA_PAGE(a, n); -  ptr = p->data + BA_PAGESIZE(a) - 1; +  ptr = BA_LASTBLOCK(a, p);    hval = hash1(a, ptr); -  fprintf(stdout, "%u\t%u\t%p\t%u\n", i, hval, ptr, ((uintptr_t)ptr >> a->magnitude)); +  fprintf(stderr, "%u\t%X\t%p-%p\t%X\n", i, hval, p->data, ptr, ((uintptr_t)ptr >> a->magnitude)); +  n = p->hchain;    }    }   }      #define likely(x) (__builtin_expect((x), 1))   #define unlikely(x) (__builtin_expect((x), 0))      static inline uint16_t ba_htable_lookup(const struct block_allocator * a,    const void * ptr) {    uint16_t n1, n2;
pike.git/src/block_allocator.c:262:    if (BA_CHECK_PTR(a, p, ptr)) {    return n2;    }    n2 = p->hchain;    }    }    return 0;   }      void * ba_alloc(struct block_allocator * a) { +  //fprintf(stderr, "ba_alloc(%p)\n", a);    ba_page p;   #ifndef BA_SEGREGATE    size_t i, j;   #endif       if (likely(a->first)) {   #ifndef BA_SEGREGATE    uintptr_t m;   #else    void * ptr;
pike.git/src/block_allocator.c:300:    j = ctz32(m);   #endif    m ^= TBITMASK(uintptr_t, j);    //fprintf(stderr, "setting bit %u -> %8X (using %u blocks) maks_num: %u\n", i*sizeof(uintptr_t)*8 + j, m, p->blocks_used, BA_MASK_NUM(a));    p->mask[i] = m;   // fprintf(stderr, "blk(%p)< n: %u\tmask: %04X\n", p, i, m);       // TODO: remove this:    p->blocks_used ++;    -  if (unlikely(m == 0)) { +  if (m) { +  /* +  fprintf(stderr, "3 alloced pointer %p (%u/%u used %u)\n", +  BA_BLOCKN(a, p, (i*sizeof(uintptr_t)*8 + j)), +  (i*sizeof(uintptr_t)*8 + j), a->blocks, p->blocks_used); +  */ +  return BA_BLOCKN(a, p, (i*sizeof(uintptr_t)*8 + j)); +  } else {    for (m = i+1; m < BA_MASK_NUM(a); m++) {    if (p->mask[m]) {    p->free_mask = m; -  +  /* +  fprintf(stderr, "1 alloced pointer %p (%u/%u used %u)\n", +  BA_BLOCKN(a, p, (i*sizeof(uintptr_t)*8 + j)), +  (i*sizeof(uintptr_t)*8 + j), a->blocks, +  p->blocks_used); +  */    return BA_BLOCKN(a, p, (i*sizeof(uintptr_t)*8 + j));    }    }    if (p->blocks_used != a->blocks) {    fprintf(stderr, "wrong block count detected: %u vs %u\n", p->blocks_used, a->blocks);    Pike_error("croak\n");    } -  +  //fprintf(stderr, "page is full now\n");    if (a->last == a->first) {    a->first = a->last = 0;    } else {    a->first = p->next;    }    p->next = 0;    p->free_mask = BA_MASK_NUM(a); -  } -  +     return BA_BLOCKN(a, p, (i*sizeof(uintptr_t)*8 + j)); -  +  }   #else    if (p->blocks_used == a->blocks) Pike_error("baaad!\n");    p->blocks_used ++;    ptr = BA_BLOCKN(a, p, p->first-1); -  +  //fprintf(stderr, "alloced pointer %p (%u/%u used %u)\n", +  //ptr, p->first-1, a->blocks, p->blocks_used);       if (unlikely(p->blocks_used == a->blocks)) {    a->first = p->next;    if (!a->first) {    a->last = 0;    }    p->next = 0;    } else { -  p->first = ((struct ba_block_header*)ptr)->next || p->first+1; +  //fprintf(stderr, "next: %u\n", ((struct ba_block_header*)ptr)->next); +  if (((struct ba_block_header*)ptr)->next) +  p->first = ((struct ba_block_header*)ptr)->next; +  else p->first++;    } -  +  //fprintf(stderr, "first is %u\n", p->first);       return ptr;   #endif    }    -  +  //fprintf(stderr, "allocating new page. was %p\n", p);    if (unlikely(a->num_pages == a->allocated))    ba_grow(a);       p = BA_PAGE(a, ++a->num_pages);    p->data = malloc(BA_PAGESIZE(a));    if (!p->data) {    Pike_error("no mem");    }    p->next = p->prev = 0;    a->first = a->last = a->num_pages;    ba_htable_insert(a, BA_LASTBLOCK(a, p), a->num_pages);   #ifndef BA_SEGREGATE -  memset((void*)p->mask, 0xff, BA_MASK_NUM(a)*sizeof(uintptr_t)); +  if (BA_MASK_NUM(a) > 1) +  memset((void*)p->mask, 0xff, (BA_MASK_NUM(a)-1)*sizeof(uintptr_t)); +  p->mask[BA_MASK_NUM(a)-1] = BA_LAST_MASK(a); +  p->mask[0] ^= TBITMASK(uintptr_t, 0); +     p->free_mask = 0; -  p->mask[0] = ~TBITMASK(uintptr_t, 0); +     // TODO: remove this:    p->blocks_used = 1;   #else    p->blocks_used = 1;    p->first = 2;    memset(p->data, 0x00, BA_PAGESIZE(a));   #endif    return p->data;   }   
pike.git/src/block_allocator.c:380:    ba_page p;    unsigned int n;       n = a->last_free;       if (n) {    p = BA_PAGE(a, n);    if (!BA_CHECK_PTR(a, p, ptr)) n = 0;    }    -  if (!n) { +  if (unlikely(!n)) {    a->last_free = n = ba_htable_lookup(a, ptr);    -  if (!n) { +  if (unlikely(!n)) { + #define BA_DEBUG + #ifdef BA_DEBUG +  fprintf(stderr, "magnitude: %u\n", a->magnitude);    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); +  ba_print_htable(a); + #endif    Pike_error("Unknown pointer \n");    }       p = BA_PAGE(a, n);    }       t = (uintptr_t)((char*)ptr - p->data)/a->block_size;   #ifndef BA_SEGREGATE    mask = t / (sizeof(uintptr_t) * 8);    bit = t & ((sizeof(uintptr_t)*8) - 1); -  +  /* +  fprintf(stderr, "freeing pointer %p (%u/%u) used %u\n", ptr, t, a->blocks, +  p->blocks_used); +  */       t = p->mask[mask];       if (t & TBITMASK(uintptr_t, bit)) {    Pike_error("double free!");    }    if (mask < p->free_mask)    p->free_mask = mask;    // TODO: remove this:    p->blocks_used --;       if (unlikely(t == 0)) { -  +  unsigned int i;    p->free_mask = mask; -  for (bit = 0; bit < BA_MASK_NUM(a); bit++) if (p->mask[bit]) return; -  p->mask[mask] |= TBITMASK(uintptr_t, bit); +  for (i = 0; i < BA_MASK_NUM(a); i++) if (p->mask[i]) { +  p->mask[mask] = TBITMASK(uintptr_t, bit); +  return; +  } +  p->mask[mask] = TBITMASK(uintptr_t, bit);    if (p->blocks_used != a->blocks-1) {    fprintf(stderr, "wrong block count detected: %u vs %u\n", p->blocks_used+1, a->blocks);    Pike_error("croak\n");    }    if (a->first == 0) {    a->first = a->last = n;    p->next = p->prev = 0;    } else {    p->next = a->first;    BA_PAGE(a, a->first)->prev = n;
pike.git/src/block_allocator.c:440: Inside #if undefined(BA_SEGREGATE)
   p->mask[mask] = t;       if (unlikely(~t == 0)) {    for (bit = 0; bit < BA_MASK_NUM(a)-1; bit++) if (~p->mask[bit]) return;    if (~(p->mask[BA_MASK_NUM(a)-1]|~BA_LAST_MASK(a))) return;    if (p->blocks_used != 0) {    fprintf(stderr, "wrong block count detected: %u vs %u\n", p->blocks_used+1, 1);    Pike_error("croak\n");    }    ba_remove_page(a, n); -  fprintf(stderr, "could reclaim memory of page %u\n", n); +  //fprintf(stderr, "could reclaim memory of page %u\n", n);    // we can reclaim memory to the system here!    } else if (p->blocks_used == 0 || p->blocks_used == a->blocks - 1) {    fprintf(stderr, "wrong number of used blocks: %u\n", p->blocks_used);    Pike_error("bad croak\n");    }   #else    if (p->blocks_used == a->blocks) {    if (a->first == 0) {    a->first = a->last = n;    p->next = p->prev = 0;
pike.git/src/block_allocator.c:462:    p->next = a->first;    BA_PAGE(a, a->first)->prev = n;    a->first = n;    }    } else if (p->blocks_used == 1) {    ba_remove_page(a, n);    return;    }    p->blocks_used --;    ((struct 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 = t+1;   #endif   }      static inline void ba_remove_page(struct block_allocator * a,    uint16_t n) {    ba_page tmp, p;       p = BA_PAGE(a, n);