0a3d34 | 2011-11-10 | Arne Goedeke | | #include <stdlib.h>
|
67795d | 2011-11-11 | Arne Goedeke | | #include <string.h>
|
385483 | 2011-11-18 | Arne Goedeke | | #include <stdint.h>
|
0a3d34 | 2011-11-10 | Arne Goedeke | |
|
a60c24 | 2011-12-25 | Arne Goedeke | | #include "bitvector.h"
|
6fc6ce | 2011-12-30 | Arne Goedeke | |
|
e2499f | 2012-01-03 | Arne Goedeke | | #if defined(PIKE_CORE) || defined(DYNAMIC_MODULE) || defined(STATIC_MODULE)
#include "pike_memory.h"
#endif
|
41889b | 2012-01-10 | Arne Goedeke | | #include "block_allocator.h"
|
6fc6ce | 2011-12-30 | Arne Goedeke | |
|
f2b3bd | 2011-12-31 | Arne Goedeke | | #ifndef PMOD_EXPORT
# warning WTF
|
385483 | 2011-11-18 | Arne Goedeke | | #endif
|
fdfd28 | 2011-12-25 | Arne Goedeke | |
|
e2499f | 2012-01-03 | Arne Goedeke | | #if defined(BA_DEBUG) || (!defined(PIKE_CORE) && !defined(DYNAMIC_MODULE) \
&& !defined(STATIC_MODULES))
#endif
PMOD_EXPORT char errbuf[8192];
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE void ba_htable_insert(const struct block_allocator * a,
|
f2b3bd | 2011-12-31 | Arne Goedeke | | const void * ptr, const ba_page_t n);
|
6fc6ce | 2011-12-30 | Arne Goedeke | |
|
335e6a | 2012-01-04 | Arne Goedeke | | #define BA_NBLOCK(a, p, ptr) ((uintptr_t)((char*)ptr - (char)(p+1))/(a)->block_size)
|
e90c49 | 2011-11-27 | Arne Goedeke | |
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #define BA_DIVIDE(a, b) ((a) / (b) + (!!((a) & ((b)-1))))
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | #define BA_PAGESIZE(a) ((a)->blocks * (a)->block_size)
|
385483 | 2011-11-18 | Arne 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)
|
e2499f | 2012-01-03 | Arne Goedeke | | #ifdef BA_HASH_THLD
|
335e6a | 2012-01-04 | Arne Goedeke | | # define BA_BYTES(a) ( (sizeof(ba_page) + ((a->allocated > BA_HASH_THLD) ? sizeof(ba_page_t) : 0)) * ((a)->allocated) )
|
e2499f | 2012-01-03 | Arne Goedeke | | #else
|
335e6a | 2012-01-04 | Arne Goedeke | | # define BA_BYTES(a) ( (sizeof(ba_page) + sizeof(ba_page_t)) * ((a)->allocated) )
|
e2499f | 2012-01-03 | Arne Goedeke | | #endif
|
385483 | 2011-11-18 | Arne Goedeke | |
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE void ba_realloc(struct block_allocator * a) {
|
475075 | 2011-11-19 | Arne Goedeke | | unsigned int i;
|
335e6a | 2012-01-04 | Arne Goedeke | | ba_page * old;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | ba_page p;
|
335e6a | 2012-01-04 | Arne Goedeke | | a->pages = (ba_page*)realloc(old = a->pages, BA_BYTES(a));
|
6fc6ce | 2011-12-30 | Arne Goedeke | | if (unlikely(!a->pages)) {
|
41889b | 2012-01-10 | Arne Goedeke | |
|
e2499f | 2012-01-03 | Arne Goedeke | | BA_ERROR("alloc of %lu bytes failed.", BA_BYTES(a));
|
67795d | 2011-11-11 | Arne Goedeke | | }
|
f2b3bd | 2011-12-31 | Arne Goedeke | | #ifdef BA_DEBUG
|
41889b | 2012-01-10 | Arne Goedeke | | memset((void*)(a->pages + a->num_pages), 0, BA_BYTES(a) - sizeof(ba_page)*a->num_pages);
|
385483 | 2011-11-18 | Arne Goedeke | | #endif
|
e2499f | 2012-01-03 | Arne Goedeke | | a->htable = NULL;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | IF_HASH(
|
335e6a | 2012-01-04 | Arne Goedeke | | a->htable = (ba_page_t*) (a->pages + a->allocated);
|
f2b3bd | 2011-12-31 | Arne Goedeke | | memset(a->htable, 0, a->allocated * sizeof(ba_page_t));
|
6fc6ce | 2011-12-30 | Arne 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
|
67795d | 2011-11-11 | Arne Goedeke | | }
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | | #define PRINT_NODE(a, name) do {\
fprintf(stderr, #name": %p[%u]\n", a->name, a->name ? a->name->n : 0);\
} while (0)
|
e2499f | 2012-01-03 | Arne Goedeke | | PMOD_EXPORT void ba_show_pages(struct block_allocator * a) {
unsigned int i = 0;
|
41889b | 2012-01-10 | Arne 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);
|
e2499f | 2012-01-03 | Arne Goedeke | | for (i = 1; i <= a->num_pages; i++) {
ba_page p = BA_PAGE(a, i);
|
41889b | 2012-01-10 | Arne Goedeke | | ba_block_t blocks_used;
if (p == a->first) {
if (!a->first_blk) blocks_used = a->blocks;
else blocks_used = a->blocks - a->first_blk->left;
} else {
if (!p->first) blocks_used = a->blocks;
else blocks_used = a->blocks - p->first->left;
}
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));
|
e2499f | 2012-01-03 | Arne Goedeke | |
}
}
|
d947bc | 2012-01-06 | Arne Goedeke | |
|
c8b590 | 2012-01-04 | Arne Goedeke | | PMOD_EXPORT INLINE void ba_init(struct block_allocator * a,
|
6fc6ce | 2011-12-30 | Arne Goedeke | | uint32_t block_size, ba_page_t blocks) {
|
d947bc | 2012-01-06 | Arne 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;
|
41889b | 2012-01-10 | Arne Goedeke | | a->offset = sizeof(struct ba_page) + page_size - block_size;
|
385483 | 2011-11-18 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | | a->first_blk = NULL;
a->empty = a->first = a->last_free = NULL;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
25a942 | 2012-01-06 | Arne Goedeke | | if ((page_size & (page_size - 1))) {
page_size = round_up32(page_size);
a->blocks = page_size/block_size;
} else a->blocks = blocks;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
25a942 | 2012-01-06 | Arne Goedeke | | a->magnitude = (uint16_t)ctz32(page_size);
|
0a3d34 | 2011-11-10 | Arne Goedeke | | a->block_size = block_size;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | a->num_pages = 0;
|
938726 | 2011-12-25 | Arne Goedeke | | a->empty_pages = 0;
|
e2499f | 2012-01-03 | Arne Goedeke | | a->max_empty_pages = BA_MAX_EMPTY;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
67795d | 2011-11-11 | Arne Goedeke | |
|
6fc6ce | 2011-12-30 | Arne Goedeke | | a->allocated = BA_ALLOC_INITIAL;
|
67795d | 2011-11-11 | Arne Goedeke | | a->pages = NULL;
ba_realloc(a);
}
|
c8b590 | 2012-01-04 | Arne Goedeke | | PMOD_EXPORT INLINE void ba_free_all(struct block_allocator * a) {
|
475075 | 2011-11-19 | Arne Goedeke | | unsigned int i;
|
67795d | 2011-11-11 | Arne Goedeke | |
|
e2499f | 2012-01-03 | Arne Goedeke | | if (!a->allocated) return;
|
67795d | 2011-11-11 | Arne Goedeke | | for (i = 0; i < a->num_pages; i++) {
|
335e6a | 2012-01-04 | Arne 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;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
|
67795d | 2011-11-11 | Arne Goedeke | | a->num_pages = 0;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | a->empty_pages = 0;
|
41889b | 2012-01-10 | Arne Goedeke | | a->empty = a->first = a->last_free = NULL;
a->first_blk = NULL;
|
e2499f | 2012-01-03 | Arne Goedeke | | a->allocated = BA_ALLOC_INITIAL;
ba_realloc(a);
IF_HASH(
memset(a->htable, 0, sizeof(*a->htable)*a->allocated);
);
|
67795d | 2011-11-11 | Arne Goedeke | | }
|
c8b590 | 2012-01-04 | Arne Goedeke | | PMOD_EXPORT INLINE void ba_count_all(struct block_allocator * a, size_t *num, size_t *size) {
|
475075 | 2011-11-19 | Arne Goedeke | | unsigned int i;
|
385483 | 2011-11-18 | Arne Goedeke | | size_t n = 0;
|
f2b3bd | 2011-12-31 | Arne Goedeke | |
|
385483 | 2011-11-18 | Arne Goedeke | | *size = BA_BYTES(a) + a->num_pages * BA_PAGESIZE(a);
for (i = 0; i < a->num_pages; i++) {
|
41889b | 2012-01-10 | Arne Goedeke | | ba_page p = a->pages[i];
if (p == a->first) {
if (a->first_blk) n += a->first_blk->left;
else n += a->blocks;
} else {
if (p->first) n+= p->first->left;
else n += a->blocks;
}
|
385483 | 2011-11-18 | Arne Goedeke | | }
*num = n;
}
|
c8b590 | 2012-01-04 | Arne Goedeke | | PMOD_EXPORT INLINE void ba_destroy(struct block_allocator * a) {
|
67795d | 2011-11-11 | Arne Goedeke | | ba_free_all(a);
|
f2b3bd | 2011-12-31 | Arne Goedeke | | PIKE_MEM_RW_RANGE(a->pages, BA_BYTES(a));
|
67795d | 2011-11-11 | Arne Goedeke | | free(a->pages);
|
6fc6ce | 2011-12-30 | Arne Goedeke | | a->allocated = 0;
|
e2499f | 2012-01-03 | Arne Goedeke | | a->htable = NULL;
|
67795d | 2011-11-11 | Arne Goedeke | | a->pages = NULL;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE void ba_grow(struct block_allocator * a) {
|
385483 | 2011-11-18 | Arne Goedeke | | if (a->allocated) {
|
6fc6ce | 2011-12-30 | Arne Goedeke | |
if (a->allocated >= ((ba_page_t)1 << (sizeof(ba_page_t)*8-1))) {
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("too many pages.\n");
|
6fc6ce | 2011-12-30 | Arne Goedeke | | }
|
385483 | 2011-11-18 | Arne Goedeke | | a->allocated *= 2;
ba_realloc(a);
} else {
ba_init(a, a->block_size, a->blocks);
}
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #ifdef BA_DEBUG
ba_check_allocator(a, "ba_grow", __FILE__, __LINE__);
#endif
|
67795d | 2011-11-11 | Arne Goedeke | | }
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE void ba_shrink(struct block_allocator * a) {
|
67795d | 2011-11-11 | Arne Goedeke | | a->allocated /= 2;
ba_realloc(a);
}
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #define MIX(t) do { \
t ^= (t >> 20) ^ (t >> 12); \
t ^= (t >> 7) ^ (t >> 4); \
} while(0)
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE ba_page_t hash1(const struct block_allocator * a,
|
67795d | 2011-11-11 | Arne Goedeke | | const void * ptr) {
uintptr_t t = ((uintptr_t)ptr) >> a->magnitude;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
6fc6ce | 2011-12-30 | Arne Goedeke | | MIX(t);
return (ba_page_t) t;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE ba_page_t hash2(const struct block_allocator * a,
|
67795d | 2011-11-11 | Arne Goedeke | | const void * ptr) {
uintptr_t t = ((uintptr_t)ptr) >> a->magnitude;
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
6fc6ce | 2011-12-30 | Arne Goedeke | | t++;
MIX(t);
return (ba_page_t) t;
}
|
f2b3bd | 2011-12-31 | Arne Goedeke | | #ifdef BA_DEBUG
PMOD_EXPORT void ba_print_htable(const struct block_allocator * a) {
|
6fc6ce | 2011-12-30 | Arne Goedeke | | unsigned int i;
ba_page p;
|
e2499f | 2012-01-03 | Arne 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);
|
335e6a | 2012-01-04 | Arne 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);
|
e2499f | 2012-01-03 | Arne Goedeke | | n = p->hchain;
}
|
6fc6ce | 2011-12-30 | Arne Goedeke | | }
|
e2499f | 2012-01-03 | Arne Goedeke | | );
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
|
f2b3bd | 2011-12-31 | Arne Goedeke | | #endif
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE void ba_htable_insert(const struct block_allocator * a,
|
6fc6ce | 2011-12-30 | Arne 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);
|
335e6a | 2012-01-04 | Arne Goedeke | | fprintf(stderr, "is (%p, %d)\n", BA_PAGE(a, n)+1, n);
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("double insert.\n");
|
6fc6ce | 2011-12-30 | Arne Goedeke | | return;
}
b = &BA_PAGE(a, *b)->hchain;
}
b = a->htable + (hval & BA_HASH_MASK(a));
#endif
|
385483 | 2011-11-18 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | | #if 0//def BA_DEBUG
|
e2499f | 2012-01-03 | Arne Goedeke | | fprintf(stderr, "replacing bucket %u with page %u by %u\n",
hval & BA_HASH_MASK(a), *b, n);
#endif
|
385483 | 2011-11-18 | Arne Goedeke | | BA_PAGE(a, n)->hchain = *b;
*b = n;
}
|
6fc6ce | 2011-12-30 | Arne Goedeke | |
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE void ba_htable_replace(const struct block_allocator * a,
|
6fc6ce | 2011-12-30 | Arne 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));
|
385483 | 2011-11-18 | Arne Goedeke | |
while (*b) {
if (*b == n) {
*b = new;
BA_PAGE(a, new)->hchain = BA_PAGE(a, n)->hchain;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | BA_PAGE(a, n)->hchain = 0;
|
385483 | 2011-11-18 | Arne Goedeke | | return;
}
b = &BA_PAGE(a, *b)->hchain;
}
|
6fc6ce | 2011-12-30 | Arne 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);
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("did not find index to replace.\n")
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #endif
|
385483 | 2011-11-18 | Arne Goedeke | | }
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE void ba_htable_delete(const struct block_allocator * a,
|
6fc6ce | 2011-12-30 | Arne 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));
|
385483 | 2011-11-18 | Arne Goedeke | |
while (*b) {
if (*b == n) {
*b = BA_PAGE(a, n)->hchain;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | BA_PAGE(a, n)->hchain = 0;
|
385483 | 2011-11-18 | Arne Goedeke | | return;
}
b = &BA_PAGE(a, *b)->hchain;
}
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #ifdef DEBUG
|
e2499f | 2012-01-03 | Arne Goedeke | | ba_print_htable(a);
|
6fc6ce | 2011-12-30 | Arne Goedeke | | fprintf(stderr, "ba_htable_delete(%p, %u)\n", ptr, n);
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("did not find index to delete.\n")
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #endif
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
|
c8b590 | 2012-01-04 | Arne Goedeke | | static INLINE ba_page_t ba_htable_lookup(const struct block_allocator * a,
|
6fc6ce | 2011-12-30 | Arne Goedeke | | const void * ptr) {
|
41889b | 2012-01-10 | Arne Goedeke | | ba_page p;
ba_page_t n1, n2;
|
316eb4 | 2012-01-04 | Arne Goedeke | | #ifdef COUNT
count_name = "hash";
#endif
|
0de007 | 2012-01-06 | Arne 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;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | }
|
0de007 | 2012-01-06 | Arne Goedeke | | if (n2) {
p = BA_PAGE(a, n2);
if (BA_CHECK_PTR(a, p, ptr)) {
return n2;
}
n2 = p->hchain;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | }
|
67795d | 2011-11-11 | Arne Goedeke | | }
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
6fc6ce | 2011-12-30 | Arne Goedeke | | return 0;
}
|
67795d | 2011-11-11 | Arne Goedeke | |
|
f2b3bd | 2011-12-31 | Arne Goedeke | | #ifdef BA_DEBUG
|
c8b590 | 2012-01-04 | Arne Goedeke | | PMOD_EXPORT INLINE void ba_check_allocator(struct block_allocator * a,
|
6fc6ce | 2011-12-30 | Arne Goedeke | | char *fun, char *file, int line) {
unsigned int i = 0;
int bad = 0;
|
67795d | 2011-11-11 | Arne Goedeke | | ba_page p;
|
6fc6ce | 2011-12-30 | Arne 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);
|
41889b | 2012-01-10 | Arne 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) {
|
6fc6ce | 2011-12-30 | Arne Goedeke | | if (p->prev || p->next) {
|
41889b | 2012-01-10 | Arne 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));
|
6fc6ce | 2011-12-30 | Arne Goedeke | | bad = 1;
|
67795d | 2011-11-11 | Arne Goedeke | | }
}
|
6fc6ce | 2011-12-30 | Arne 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;
|
67795d | 2011-11-11 | Arne Goedeke | | }
|
6fc6ce | 2011-12-30 | Arne 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;
}
}
|
41889b | 2012-01-10 | Arne Goedeke | | if (bad)
ba_print_htable(a);
|
6fc6ce | 2011-12-30 | Arne Goedeke | | );
}
if (bad) {
|
41889b | 2012-01-10 | Arne Goedeke | | ba_show_pages(a);
|
6fc6ce | 2011-12-30 | Arne Goedeke | | fprintf(stderr, "\nCalled from %s:%d:%s\n", fun, line, file);
fprintf(stderr, "pages: %u\n", a->num_pages);
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("bad");
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
}
|
f2b3bd | 2011-12-31 | Arne Goedeke | | #endif
|
a5e1b8 | 2011-11-09 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | | static INLINE void ba_alloc_page(struct block_allocator * a) {
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | ba_page p;
|
e2499f | 2012-01-03 | Arne Goedeke | | unsigned int i;
|
d2892b | 2011-12-25 | Arne Goedeke | |
|
6fc6ce | 2011-12-30 | Arne Goedeke | | if (unlikely(a->num_pages == a->allocated)) {
|
385483 | 2011-11-18 | Arne Goedeke | | ba_grow(a);
|
6fc6ce | 2011-12-30 | Arne Goedeke | | }
|
385483 | 2011-11-18 | Arne Goedeke | |
|
6fc6ce | 2011-12-30 | Arne Goedeke | | a->num_pages++;
#ifdef BA_DEBUG
|
335e6a | 2012-01-04 | Arne Goedeke | | if (BA_PAGE(a, a->num_pages)) {
|
6fc6ce | 2011-12-30 | Arne Goedeke | | void * new = malloc(BA_PAGESIZE(a));
fprintf(stderr, "reusing unfreed page %d, data: %p -> %p\n", a->num_pages,
|
335e6a | 2012-01-04 | Arne Goedeke | | p+1, new);
|
e2499f | 2012-01-03 | Arne Goedeke | | a->num_pages--;
ba_show_pages(a);
a->num_pages++;
|
335e6a | 2012-01-04 | Arne Goedeke | | BA_PAGE(a, a->num_pages) = p = new;
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("dont continue\n");
|
6fc6ce | 2011-12-30 | Arne Goedeke | | } else
#endif
|
335e6a | 2012-01-04 | Arne Goedeke | | BA_PAGE(a, a->num_pages) = p = (ba_page)malloc(sizeof(struct ba_page) + BA_PAGESIZE(a));
if (!p) {
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("no mem. alloc returned zero.");
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
|
41889b | 2012-01-10 | Arne Goedeke | | p->n = a->num_pages;
#ifdef BA_DEBUG
if (!p->n) BA_ERROR("num pages cannot be zero\n");
#endif
|
335e6a | 2012-01-04 | Arne Goedeke | | p->next = p->prev = NULL;
|
41889b | 2012-01-10 | Arne Goedeke | | a->last = a->first = p;
|
6fc6ce | 2011-12-30 | Arne 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
);
|
41889b | 2012-01-10 | Arne Goedeke | | p->first = BA_BLOCKN(a, p, 0);
|
0639aa | 2012-01-04 | Arne Goedeke | |
|
25a942 | 2012-01-06 | Arne Goedeke | | if (a->blueprint) {
size_t len = (a->blocks - 1) * a->block_size, clen = a->block_size;
memcpy(p+1, a->blueprint, a->block_size);
while (len > clen) {
memcpy(((char*)(p+1)) + clen, p+1, clen);
len -= clen;
clen <<= 1;
}
if (len) memcpy(((char*)(p+1)) + clen, p+1, len);
}
|
41889b | 2012-01-10 | Arne Goedeke | | for (i = 0; i < a->blocks; i++) {
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #ifdef BA_DEBUG
|
e2499f | 2012-01-03 | Arne Goedeke | | PIKE_MEM_RW(BA_BLOCKN(a, p, i)->magic);
|
6fc6ce | 2011-12-30 | Arne Goedeke | | BA_BLOCKN(a, p, i)->magic = BA_MARK_FREE;
#endif
|
0639aa | 2012-01-04 | Arne Goedeke | | BA_BLOCKN(a, p, i)->next = BA_BLOCKN(a, p, i+1);
|
41889b | 2012-01-10 | Arne Goedeke | | BA_BLOCKN(a, p, i)->left = a->blocks - (i);
|
6fc6ce | 2011-12-30 | Arne Goedeke | | }
|
f2b3bd | 2011-12-31 | Arne Goedeke | | BA_LASTBLOCK(a, p)->next = NULL;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #ifdef BA_DEBUG
|
e2499f | 2012-01-03 | Arne Goedeke | | PIKE_MEM_RW(BA_LASTBLOCK(a, p)->magic);
|
f2b3bd | 2011-12-31 | Arne Goedeke | | BA_LASTBLOCK(a, p)->magic = BA_MARK_FREE;
|
e2499f | 2012-01-03 | Arne Goedeke | | PIKE_MEM_RW(BA_BLOCKN(a, p, 0)->magic);
|
6fc6ce | 2011-12-30 | Arne Goedeke | | BA_BLOCKN(a, p, 0)->magic = BA_MARK_ALLOC;
ba_check_allocator(a, "ba_alloc after insert", __FILE__, __LINE__);
|
385483 | 2011-11-18 | Arne Goedeke | | #endif
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
|
41889b | 2012-01-10 | Arne Goedeke | | PMOD_EXPORT void ba_low_alloc(struct block_allocator * a) {
|
e2499f | 2012-01-03 | Arne Goedeke | | #ifdef BA_DEBUG
|
41889b | 2012-01-10 | Arne Goedeke | | ba_check_allocator(a, "ba_alloc top", __FILE__, __LINE__);
|
113389 | 2012-01-06 | Arne Goedeke | | #endif
|
41889b | 2012-01-10 | Arne Goedeke | |
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;
|
d2892b | 2011-12-25 | Arne Goedeke | | #ifdef BA_DEBUG
#endif
|
e2499f | 2012-01-03 | Arne Goedeke | | }
|
41889b | 2012-01-10 | Arne Goedeke | | if (a->first) {
#if 1//def BA_DEBUG
if (!a->first->first) {
ba_show_pages(a);
BA_ERROR("no free blk in page %p[%u]\n", a->first,
BA_NUM(a->first));
|
e2499f | 2012-01-03 | Arne Goedeke | | }
|
41889b | 2012-01-10 | Arne Goedeke | | #endif
a->first->prev = NULL;
} else if (a->empty_pages) {
a->last = a->first = a->empty;
a->empty = a->empty->next;
|
e2499f | 2012-01-03 | Arne Goedeke | | a->empty_pages--;
|
41889b | 2012-01-10 | Arne Goedeke | | a->first->next = NULL;
} else ba_alloc_page(a);
#if 1//def BA_DEBUG
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;
}
PMOD_EXPORT void ba_free_empty(struct block_allocator * a, ba_page p) {
if (a->empty_pages == a->max_empty_pages) {
ba_remove_page(a, p);
|
e2499f | 2012-01-03 | Arne Goedeke | | return;
|
67795d | 2011-11-11 | Arne Goedeke | | }
|
41889b | 2012-01-10 | Arne Goedeke | | 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 ++;
}
|
67795d | 2011-11-11 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | | PMOD_EXPORT void ba_free_full(struct block_allocator * a,
ba_page p, ba_block_header ptr) {
ptr->next = NULL;
ptr->left = 1;
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;
}
}
PMOD_EXPORT void ba_find_page(struct block_allocator * a,
const void * ptr) {
ba_page_t n;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #ifdef BA_DEBUG
|
41889b | 2012-01-10 | Arne 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
|
6fc6ce | 2011-12-30 | Arne Goedeke | | }
|
385483 | 2011-11-18 | Arne Goedeke | | #endif
|
e2499f | 2012-01-03 | Arne Goedeke | | #ifdef BA_DEBUG
|
41889b | 2012-01-10 | Arne 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);
|
e2499f | 2012-01-03 | Arne Goedeke | | #endif
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("Unknown pointer (not found in hash) %p\n", ptr);
|
385483 | 2011-11-18 | Arne Goedeke | | }
|
f2b3bd | 2011-12-31 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | | PMOD_EXPORT void ba_remove_page(struct block_allocator * a,
ba_page p) {
ba_page_t n = p->n;
ba_page tmp;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | #ifdef BA_DEBUG
ba_check_allocator(a, "ba_remove_page", __FILE__, __LINE__);
if (a->empty_pages < a->max_empty_pages) {
|
41889b | 2012-01-10 | Arne Goedeke | | BA_ERROR("strange things happening\n");
}
if (p == a->first) {
BA_ERROR("removing first page. this is not supposed to happen\n");
|
6fc6ce | 2011-12-30 | Arne Goedeke | | }
#endif
|
385483 | 2011-11-18 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | | #if 0//def BA_DEBUG
|
e2499f | 2012-01-03 | Arne Goedeke | | fprintf(stderr, "> ===============\n");
ba_show_pages(a);
ba_print_htable(a);
|
41889b | 2012-01-10 | Arne 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)),
|
385483 | 2011-11-18 | Arne Goedeke | | hash1(a, BA_LASTBLOCK(a,p)) & BA_HASH_MASK(a),
a->num_pages);
|
e2499f | 2012-01-03 | Arne Goedeke | | #endif
|
385483 | 2011-11-18 | Arne Goedeke | |
|
6fc6ce | 2011-12-30 | Arne Goedeke | | IF_HASH(
ba_htable_delete(a, BA_LASTBLOCK(a, p), n);
);
|
335e6a | 2012-01-04 | Arne Goedeke | | PIKE_MEM_RW_RANGE(*p, BA_PAGESIZE(a));
|
385483 | 2011-11-18 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | |
a->last_free = NULL;
|
385483 | 2011-11-18 | Arne Goedeke | |
|
41889b | 2012-01-10 | Arne Goedeke | | if (p->prev) p->prev->next = p->next;
if (p->next) p->next->prev = p->prev;
else a->last = p->prev;
|
385483 | 2011-11-18 | Arne Goedeke | |
|
de2d07 | 2011-12-25 | Arne Goedeke | | if (a->num_pages != n) {
tmp = BA_PAGE(a, a->num_pages);
|
6fc6ce | 2011-12-30 | Arne Goedeke | |
IF_HASH(
ba_htable_delete(a, BA_LASTBLOCK(a, tmp), a->num_pages);
);
|
41889b | 2012-01-10 | Arne Goedeke | | #if 0//def BA_DEBUG
|
e2499f | 2012-01-03 | Arne 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,
|
41889b | 2012-01-10 | Arne Goedeke | | tmp+1, BA_LASTBLOCK(a, tmp), hash1(a, BA_LASTBLOCK(a,tmp)),
|
e2499f | 2012-01-03 | Arne Goedeke | | hash1(a, BA_LASTBLOCK(a,tmp)) & BA_HASH_MASK(a),
a->num_pages);
|
de2d07 | 2011-12-25 | Arne Goedeke | |
|
e2499f | 2012-01-03 | Arne Goedeke | | #endif
|
41889b | 2012-01-10 | Arne Goedeke | | BA_PAGE(a, n) = tmp;
tmp->n = n;
|
6fc6ce | 2011-12-30 | Arne Goedeke | | IF_HASH(
ba_htable_insert(a, BA_LASTBLOCK(a, tmp), n);
);
|
41889b | 2012-01-10 | Arne Goedeke | | #if 0//def BA_DEBUG
|
e2499f | 2012-01-03 | Arne Goedeke | | ba_print_htable(a);
fprintf(stderr, "fooo\n");
#endif
|
de2d07 | 2011-12-25 | Arne Goedeke | | }
|
d2892b | 2011-12-25 | Arne Goedeke | | #ifdef BA_DEBUG
|
41889b | 2012-01-10 | Arne 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);
|
335e6a | 2012-01-04 | Arne Goedeke | | fprintf(stderr, "page %d was not moved and prev was %p\n", n, p->prev);
|
d2892b | 2011-12-25 | Arne Goedeke | | }
|
41889b | 2012-01-10 | Arne Goedeke | | BA_PAGE(a, a->num_pages) = NULL;
|
d2892b | 2011-12-25 | Arne Goedeke | | #endif
|
385483 | 2011-11-18 | Arne Goedeke | | a->num_pages--;
|
335e6a | 2012-01-04 | Arne Goedeke | | free(p);
|
6fc6ce | 2011-12-30 | Arne Goedeke | |
#ifdef BA_DEBUG
ba_check_allocator(a, "ba_remove_page", __FILE__, __LINE__);
#endif
|
e2499f | 2012-01-03 | Arne Goedeke | | if (a->allocated > BA_ALLOC_INITIAL && a->num_pages <= (a->allocated >> 2)) {
|
6fc6ce | 2011-12-30 | Arne Goedeke | | ba_shrink(a);
}
|
41889b | 2012-01-10 | Arne Goedeke | | #if 0//def BA_DEBUG
|
e2499f | 2012-01-03 | Arne Goedeke | | ba_show_pages(a);
ba_print_htable(a);
fprintf(stderr, "< =================\n");
#endif
|
a5e1b8 | 2011-11-09 | Arne Goedeke | | }
|