X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/2b2e97af7fdb9b456ab168f25a23208b428e4131..36fb4e9a7743326d1a2ca7601bc9bf1c5b9a0bcb:/libratbox/src/balloc.c diff --git a/libratbox/src/balloc.c b/libratbox/src/balloc.c index cd5c5e7..a147feb 100644 --- a/libratbox/src/balloc.c +++ b/libratbox/src/balloc.c @@ -28,7 +28,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA * - * $Id: balloc.c 25048 2008-01-23 18:34:02Z androsyn $ + * $Id: balloc.c 26100 2008-09-20 01:27:19Z androsyn $ */ /* @@ -59,6 +59,7 @@ #include #include +#ifndef NOBALLOC #ifdef HAVE_MMAP /* We've got mmap() that is good */ #include /* HP-UX sucks */ @@ -68,6 +69,9 @@ #endif #endif #endif +#endif + +static uintptr_t offset_pad; /* status information for an allocated block in heap */ struct rb_heap_block @@ -79,17 +83,6 @@ struct rb_heap_block }; typedef struct rb_heap_block rb_heap_block; -struct rb_heap_memblock -{ - rb_heap_block *block; - union { - rb_dlink_node node; - char data[1]; /* stub pointer..this is ugly */ - } ndata; -}; - -typedef struct rb_heap_memblock rb_heap_memblock; - /* information for the root node of the heap */ struct rb_bh { @@ -102,7 +95,7 @@ struct rb_bh }; #ifndef NOBALLOC -static int newblock(rb_bh * bh); +static int newblock(rb_bh *bh); static void rb_bh_gc_event(void *unused); #endif /* !NOBALLOC */ static rb_dlink_list *heap_lists; @@ -119,7 +112,7 @@ _rb_bh_fail(const char *reason, const char *file, int line) rb_lib_log("rb_heap_blockheap failure: %s (%s:%d)", reason, file, line); abort(); } - + #ifndef NOBALLOC /* * static inline void free_block(void *ptr, size_t size) @@ -134,7 +127,7 @@ free_block(void *ptr, size_t size) #ifdef HAVE_MMAP munmap(ptr, size); #else -#ifdef WIN32 +#ifdef _WIN32 HeapFree(block_heap, 0, ptr); #else free(ptr); @@ -155,9 +148,21 @@ void rb_init_bh(void) { heap_lists = rb_malloc(sizeof(rb_dlink_list)); + offset_pad = sizeof(void *); + /* XXX if you get SIGBUS when trying to use a long long..here is where you need to + * fix your shit + */ +#ifdef __sparc__ + if((offset_pad % __alignof__(long long)) != 0) + { + offset_pad += __alignof__(long long); + offset_pad &= ~(__alignof__(long long) - 1); + } +#endif + #ifndef NOBALLOC -#ifdef WIN32 - block_heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0); +#ifdef _WIN32 + block_heap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0); #endif rb_event_addish("rb_bh_gc_event", rb_bh_gc_event, NULL, 300); #endif /* !NOBALLOC */ @@ -187,15 +192,15 @@ get_block(size_t size) close(zero_fd); #endif /* MAP_ANON */ if(ptr == MAP_FAILED) - ptr = NULL; + ptr = NULL; #else -#ifdef WIN32 +#ifdef _WIN32 ptr = HeapAlloc(block_heap, 0, size); -#else +#else ptr = malloc(size); #endif #endif - return(ptr); + return (ptr); } @@ -221,32 +226,32 @@ rb_bh_gc_event(void *unused) /* ************************************************************************ */ static int -newblock(rb_bh * bh) +newblock(rb_bh *bh) { rb_heap_block *b; unsigned long i; - rb_uintptr_t offset; - + uintptr_t offset; + rb_dlink_node *node; /* Setup the initial data structure. */ b = rb_malloc(sizeof(rb_heap_block)); - b->alloc_size = bh->elemsPerBlock * (bh->elemSize + sizeof(rb_heap_block *)); + b->alloc_size = bh->elemsPerBlock * bh->elemSize; b->elems = get_block(b->alloc_size); - if(unlikely(b->elems == NULL)) + if(rb_unlikely(b->elems == NULL)) { return (1); } - offset = (rb_uintptr_t)b->elems; + offset = (uintptr_t)b->elems; /* Setup our blocks now */ - for (i = 0; i < bh->elemsPerBlock; i++, offset += (bh->elemSize + sizeof(rb_heap_block *))) + for(i = 0; i < bh->elemsPerBlock; i++, offset += bh->elemSize) { - rb_heap_memblock *memblock = (rb_heap_memblock *)offset; - memblock->block = b; - rb_dlinkAdd(memblock, &memblock->ndata.node, &bh->free_list); + *((void **)offset) = b; + node = (void *)(offset + offset_pad); + rb_dlinkAdd((void *)offset, node, &bh->free_list); } rb_dlinkAdd(b, &b->node, &bh->block_list); - b->free_count = bh->elemsPerBlock; + b->free_count = bh->elemsPerBlock; return (0); } #endif /* !NOBALLOC */ @@ -272,26 +277,27 @@ rb_bh_create(size_t elemsize, int elemsperblock, const char *desc) rb_bh *bh; lrb_assert(elemsize > 0 && elemsperblock > 0); lrb_assert(elemsize >= sizeof(rb_dlink_node)); + /* Catch idiotic requests up front */ - if((elemsize <= 0) || (elemsperblock <= 0)) + if((elemsize == 0) || (elemsperblock <= 0)) { rb_bh_fail("Attempting to rb_bh_create idiotic sizes"); } if(elemsize < sizeof(rb_dlink_node)) rb_bh_fail("Attempt to rb_bh_create smaller than sizeof(rb_dlink_node)"); - + /* Allocate our new rb_bh */ bh = rb_malloc(sizeof(rb_bh)); - #ifndef NOBALLOC + elemsize += offset_pad; if((elemsize % sizeof(void *)) != 0) { /* Pad to even pointer boundary */ elemsize += sizeof(void *); elemsize &= ~(sizeof(void *) - 1); } -#endif /* !NOBALLOC */ +#endif bh->elemSize = elemsize; bh->elemsPerBlock = elemsperblock; @@ -330,27 +336,28 @@ rb_bh_create(size_t elemsize, int elemsperblock, const char *desc) /* ************************************************************************ */ void * -rb_bh_alloc(rb_bh * bh) +rb_bh_alloc(rb_bh *bh) { #ifndef NOBALLOC rb_dlink_node *new_node; - rb_heap_memblock *memblock; -#endif + rb_heap_block **block; + void *ptr; +#endif lrb_assert(bh != NULL); - if(unlikely(bh == NULL)) + if(rb_unlikely(bh == NULL)) { rb_bh_fail("Cannot allocate if bh == NULL"); } #ifdef NOBALLOC - return(rb_malloc(bh->elemSize)); + return (rb_malloc(bh->elemSize)); #else if(bh->free_list.head == NULL) { /* Allocate new block and assign */ /* newblock returns 1 if unsuccessful, 0 if not */ - if(unlikely(newblock(bh))) + if(rb_unlikely(newblock(bh))) { rb_lib_log("newblock() failed"); rb_outofmemory(); /* Well that didn't work either...bail */ @@ -363,11 +370,12 @@ rb_bh_alloc(rb_bh * bh) } new_node = bh->free_list.head; - memblock = new_node->data; + block = (rb_heap_block **) new_node->data; + ptr = (void *)((uintptr_t)new_node->data + (uintptr_t)offset_pad); rb_dlinkDelete(new_node, &bh->free_list); - memblock->block->free_count--; - memset((void *)memblock->ndata.data, 0, bh->elemSize); - return((void *)memblock->ndata.data); + (*block)->free_count--; + memset(ptr, 0, bh->elemSize - offset_pad); + return (ptr); #endif } @@ -384,37 +392,42 @@ rb_bh_alloc(rb_bh * bh) /* 0 if successful, 1 if element not contained within rb_bh. */ /* ************************************************************************ */ int -rb_bh_free(rb_bh * bh, void *ptr) +rb_bh_free(rb_bh *bh, void *ptr) { #ifndef NOBALLOC - rb_heap_memblock *memblock; + rb_heap_block *block; + void *data; #endif lrb_assert(bh != NULL); lrb_assert(ptr != NULL); - if(unlikely(bh == NULL)) + if(rb_unlikely(bh == NULL)) { - rb_lib_log("balloc.c:rb_bh_free() bh == NULL"); + rb_lib_log("balloc.c:rb_bhFree() bh == NULL"); return (1); } - if(unlikely(ptr == NULL)) + if(rb_unlikely(ptr == NULL)) { - rb_lib_log("balloc.rb_bh_free() ptr == NULL"); + rb_lib_log("balloc.rb_bhFree() ptr == NULL"); return (1); } #ifdef NOBALLOC rb_free(ptr); #else - memblock = (rb_heap_memblock *) ((uintptr_t)ptr - sizeof(rb_heap_block *)); + data = (void *)((uintptr_t)ptr - (uintptr_t)offset_pad); + block = *(rb_heap_block **) data; /* XXX */ - if(unlikely(!((uintptr_t)ptr >= (uintptr_t)memblock->block->elems && (uintptr_t)ptr < (uintptr_t)memblock->block->elems + (uintptr_t)memblock->block->alloc_size))) + if(rb_unlikely + (!((uintptr_t)ptr >= (uintptr_t)block->elems + && (uintptr_t)ptr < (uintptr_t)block->elems + (uintptr_t)block->alloc_size))) { rb_bh_fail("rb_bh_free() bogus pointer"); } - memblock->block->free_count++; - rb_dlinkAdd(memblock, &memblock->ndata.node, &bh->free_list); + block->free_count++; + + rb_dlinkAdd(data, (rb_dlink_node *)ptr, &bh->free_list); #endif /* !NOBALLOC */ return (0); } @@ -431,7 +444,7 @@ rb_bh_free(rb_bh * bh, void *ptr) /* 0 if successful, 1 if bh == NULL */ /* ************************************************************************ */ int -rb_bh_destroy(rb_bh * bh) +rb_bh_destroy(rb_bh *bh) { #ifndef NOBALLOC rb_dlink_node *ptr, *next; @@ -448,7 +461,7 @@ rb_bh_destroy(rb_bh * bh) rb_free(b); } #endif /* !NOBALLOC */ - + rb_dlinkDelete(&bh->hlist, heap_lists); rb_free(bh->desc); rb_free(bh); @@ -457,8 +470,9 @@ rb_bh_destroy(rb_bh * bh) } void -rb_bh_usage(rb_bh * bh, size_t * bused, size_t * bfree, size_t * bmemusage, const char **desc) +rb_bh_usage(rb_bh *bh, size_t *bused, size_t *bfree, size_t *bmemusage, const char **desc) { +#ifndef NOBALLOC size_t used, freem, memusage; if(bh == NULL) @@ -468,7 +482,7 @@ rb_bh_usage(rb_bh * bh, size_t * bused, size_t * bfree, size_t * bmemusage, cons freem = rb_dlink_list_length(&bh->free_list); used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem; - memusage = used * (bh->elemSize + sizeof(void *)); + memusage = used * bh->elemSize; if(bused != NULL) *bused = used; if(bfree != NULL) @@ -477,9 +491,20 @@ rb_bh_usage(rb_bh * bh, size_t * bused, size_t * bfree, size_t * bmemusage, cons *bmemusage = memusage; if(desc != NULL) *desc = bh->desc; +#else + if(bused != NULL) + *bused = 0; + if(bfree != NULL) + *bfree = 0; + if(bmemusage != NULL) + *bmemusage = 0; + if(desc != NULL) + *desc = "no blockheap"; +#endif } -void rb_bh_usage_all(rb_bh_usage_cb *cb, void *data) +void +rb_bh_usage_all(rb_bh_usage_cb *cb, void *data) { rb_dlink_node *ptr; rb_bh *bh; @@ -492,14 +517,14 @@ void rb_bh_usage_all(rb_bh_usage_cb *cb, void *data) RB_DLINK_FOREACH(ptr, heap_lists->head) { - bh = (rb_bh *)ptr->data; + bh = (rb_bh *)ptr->data; freem = rb_dlink_list_length(&bh->free_list); used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem; - memusage = used * (bh->elemSize + sizeof(void *)); - heapalloc = (freem + used) * (bh->elemSize + sizeof(void *)); + memusage = used * bh->elemSize; + heapalloc = (freem + used) * bh->elemSize; if(bh->desc != NULL) desc = bh->desc; - cb(used, freem, memusage, heapalloc, desc, data); + cb(used, freem, memusage, heapalloc, desc, data); } return; } @@ -510,16 +535,16 @@ rb_bh_total_usage(size_t *total_alloc, size_t *total_used) rb_dlink_node *ptr; size_t total_memory = 0, used_memory = 0, used, freem; rb_bh *bh; - + RB_DLINK_FOREACH(ptr, heap_lists->head) { bh = (rb_bh *)ptr->data; freem = rb_dlink_list_length(&bh->free_list); used = (rb_dlink_list_length(&bh->block_list) * bh->elemsPerBlock) - freem; - used_memory += used * (bh->elemSize + sizeof(void *)); - total_memory += (freem + used) * (bh->elemSize + sizeof(void *)); + used_memory += used * bh->elemSize; + total_memory += (freem + used) * bh->elemSize; } - + if(total_alloc != NULL) *total_alloc = total_memory; if(total_used != NULL) @@ -528,20 +553,21 @@ rb_bh_total_usage(size_t *total_alloc, size_t *total_used) #ifndef NOBALLOC int -rb_bh_gc(rb_bh * bh) +rb_bh_gc(rb_bh *bh) { rb_heap_block *b; rb_dlink_node *ptr, *next; unsigned long i; uintptr_t offset; - + if(bh == NULL) { /* somebody is smoking some craq..(probably lee, but don't tell him that) */ return (1); } - if((rb_dlink_list_length(&bh->free_list) < bh->elemsPerBlock) || rb_dlink_list_length(&bh->block_list) == 1) + if((rb_dlink_list_length(&bh->free_list) < bh->elemsPerBlock) + || rb_dlink_list_length(&bh->block_list) == 1) { /* There couldn't possibly be an entire free block. Return. */ return (0); @@ -552,22 +578,22 @@ rb_bh_gc(rb_bh * bh) b = ptr->data; if(rb_dlink_list_length(&bh->block_list) == 1) return (0); - + if(b->free_count == bh->elemsPerBlock) { /* i'm seriously going to hell for this.. */ offset = (uintptr_t)b->elems; - for (i = 0; i < bh->elemsPerBlock; i++, offset += ((uintptr_t)bh->elemSize + sizeof(rb_heap_memblock *))) + for(i = 0; i < bh->elemsPerBlock; i++, offset += (uintptr_t)bh->elemSize) { - rb_heap_memblock *memblock = (rb_heap_memblock *)offset; - rb_dlinkDelete(&memblock->ndata.node, &bh->free_list); + rb_dlinkDelete((rb_dlink_node *)(offset + offset_pad), + &bh->free_list); } rb_dlinkDelete(&b->node, &bh->block_list); free_block(b->elems, b->alloc_size); rb_free(b); } - + } return (0); }