]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - libratbox/src/balloc.c
Update FAQ.
[irc/rqf/shadowircd.git] / libratbox / src / balloc.c
index 54a29c8ecdc288c071b72c963a85e283d8fdd610..a147feb100fc2c10ae8268c52a4e578c9090624f 100644 (file)
@@ -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 <libratbox_config.h>
 #include <ratbox_lib.h>
 
+#ifndef NOBALLOC
 #ifdef HAVE_MMAP               /* We've got mmap() that is good */
 #include <sys/mman.h>
 /* 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,21 +392,22 @@ 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_bhFree() bh == NULL");
                return (1);
        }
 
-       if(unlikely(ptr == NULL))
+       if(rb_unlikely(ptr == NULL))
        {
                rb_lib_log("balloc.rb_bhFree() ptr == NULL");
                return (1);
@@ -407,14 +416,18 @@ rb_bh_free(rb_bh * bh, void *ptr)
 #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);
 }