diff options
Diffstat (limited to 'src/libmowgli/mowgli_heap.c')
-rw-r--r-- | src/libmowgli/mowgli_heap.c | 323 |
1 files changed, 0 insertions, 323 deletions
diff --git a/src/libmowgli/mowgli_heap.c b/src/libmowgli/mowgli_heap.c deleted file mode 100644 index 532517a..0000000 --- a/src/libmowgli/mowgli_heap.c +++ /dev/null @@ -1,323 +0,0 @@ -/* - * libmowgli: A collection of useful routines for programming. - * mowgli_heap.c: Heap allocation. - * - * Copyright (c) 2007 William Pitcock <nenolod -at- sacredspiral.co.uk> - * Copyright (c) 2005-2006 Theo Julienne <terminal -at- atheme.org> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice is present in all copies. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Legal note: code devised from claro.base.block module r288 (Pre MPL) - */ - -#include "mowgli.h" - -#ifdef HAVE_MMAP -# include <sys/mman.h> -# if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) -# define MAP_ANON MAP_ANONYMOUS -# endif -#endif - -/* A block of memory allocated to the allocator */ -struct mowgli_block_ -{ - mowgli_node_t node; - - /* link back to our heap */ - mowgli_heap_t *heap; - - /* pointer to the first item */ - void *data; - - /* singly linked list of free items */ - void *first_free; - - int num_allocated; -}; - -/* A pile of blocks */ -struct mowgli_heap_ -{ - mowgli_node_t node; - - unsigned int elem_size; - unsigned int mowgli_heap_elems; - unsigned int free_elems; - - unsigned int alloc_size; - - unsigned int flags; - - mowgli_list_t blocks; /* list of non-empty blocks */ - - mowgli_allocation_policy_t *allocator; - mowgli_boolean_t use_mmap; - - mowgli_block_t *empty_block; /* a single entirely free block, or NULL */ -}; - -typedef struct mowgli_heap_elem_header_ mowgli_heap_elem_header_t; - -struct mowgli_heap_elem_header_ -{ - union - { - mowgli_block_t *block; /* for allocated elems: block ptr */ - mowgli_heap_elem_header_t *next; /* for free elems: next free */ - } un; -}; - -/* expands a mowgli_heap_t by 1 block */ -static void -mowgli_heap_expand(mowgli_heap_t *bh) -{ - mowgli_block_t *block = NULL; - void *blp = NULL; - mowgli_heap_elem_header_t *node, *prev; - char *offset; - unsigned int a; - - size_t blp_size = sizeof(mowgli_block_t) + (bh->alloc_size * bh->mowgli_heap_elems); - - return_if_fail(bh->empty_block == NULL); - -#if defined(HAVE_MMAP) && defined(MAP_ANON) - if (bh->use_mmap) - blp = mmap(NULL, sizeof(mowgli_block_t) + (bh->alloc_size * bh->mowgli_heap_elems), - PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - else -#endif - { - if (bh->allocator) - blp = bh->allocator->allocate(blp_size); - else - blp = mowgli_alloc(blp_size); - } - - block = (mowgli_block_t *)blp; - - offset = (char*)blp + sizeof(mowgli_block_t); - block->data = offset; - block->heap = bh; - - prev = NULL; - - for (a = 0; a < bh->mowgli_heap_elems; a++) - { - node = (mowgli_heap_elem_header_t *)offset; - node->un.next = prev; - offset += bh->alloc_size; - prev = node; - } - - block->first_free = prev; - - bh->empty_block = block; - bh->free_elems += bh->mowgli_heap_elems; -} - -/* shrinks a mowgli_heap_t by 1 block. */ -static void -mowgli_heap_shrink(mowgli_heap_t *heap, mowgli_block_t *b) -{ - return_if_fail(b != NULL); - - if (b == heap->empty_block) - heap->empty_block = NULL; - else - mowgli_node_delete(&b->node, &heap->blocks); - -#ifdef HAVE_MMAP - if (heap->use_mmap) - munmap(b, sizeof(mowgli_block_t) + (heap->alloc_size * heap->mowgli_heap_elems)); - else -#endif - if (heap->allocator) - heap->allocator->deallocate(b); - else - mowgli_free(b); - - heap->free_elems -= heap->mowgli_heap_elems; -} - -/* creates a new mowgli_heap_t */ -mowgli_heap_t * -mowgli_heap_create_full(size_t elem_size, size_t mowgli_heap_elems, unsigned int flags, - mowgli_allocation_policy_t *allocator) -{ - mowgli_heap_t *bh = mowgli_alloc(sizeof(mowgli_heap_t)); - int numpages, pagesize; - - bh->elem_size = elem_size; - bh->mowgli_heap_elems = mowgli_heap_elems; - /* at least 2, this avoids some silly special cases */ - if (bh->mowgli_heap_elems < 2) - bh->mowgli_heap_elems = 2; - bh->free_elems = 0; - - bh->alloc_size = bh->elem_size + sizeof(mowgli_heap_elem_header_t); - - /* don't waste part of a page */ - if (allocator == NULL) - { -#ifdef HAVE_MMAP - pagesize = getpagesize(); -#else - pagesize = 4096; -#endif - numpages = (sizeof(mowgli_block_t) + (bh->alloc_size * bh->mowgli_heap_elems) + pagesize - 1) / pagesize; - bh->mowgli_heap_elems = (numpages * pagesize - sizeof(mowgli_block_t)) / bh->alloc_size; - } - - bh->flags = flags; - - bh->allocator = allocator ? allocator : mowgli_allocator_malloc; - -#ifdef HAVE_MMAP - bh->use_mmap = allocator != NULL ? FALSE : TRUE; -#endif - - if (flags & BH_NOW) - mowgli_heap_expand(bh); - - return bh; -} - -mowgli_heap_t * -mowgli_heap_create(size_t elem_size, size_t mowgli_heap_elems, unsigned int flags) -{ - return mowgli_heap_create_full(elem_size, mowgli_heap_elems, flags, NULL); -} - -/* completely frees a mowgli_heap_t and all blocks */ -void -mowgli_heap_destroy(mowgli_heap_t *heap) -{ - mowgli_node_t *n, *tn; - - MOWGLI_LIST_FOREACH_SAFE(n, tn, heap->blocks.head) - { - mowgli_heap_shrink(heap, n->data); - } - if (heap->empty_block) - mowgli_heap_shrink(heap, heap->empty_block); - - /* everything related to heap has gone, time for itself */ - mowgli_free(heap); -} - -/* allocates a new item from a mowgli_heap_t */ -void * -mowgli_heap_alloc(mowgli_heap_t *heap) -{ - mowgli_node_t *n; - mowgli_block_t *b; - mowgli_heap_elem_header_t *h; - - /* no free space? */ - if (heap->free_elems == 0) - { - mowgli_heap_expand(heap); - - return_val_if_fail(heap->free_elems != 0, NULL); - } - - /* try a partially used block before using a fully free block */ - n = heap->blocks.head; - b = n != NULL ? n->data : NULL; - if (b == NULL || b->first_free == NULL) - b = heap->empty_block; - /* due to above check */ - return_val_if_fail(b != NULL, NULL); - - /* pull the first free node from the list */ - h = b->first_free; - return_val_if_fail(h != NULL, NULL); - - /* mark it as used */ - b->first_free = h->un.next; - h->un.block = b; - - /* keep count */ - heap->free_elems--; - b->num_allocated++; - - /* move it between the lists if needed */ - /* note that a block has at least two items in it, so these cases - * cannot both occur in the same allocation */ - if (b->num_allocated == 1) - { - heap->empty_block = NULL; - mowgli_node_add_head(b, &b->node, &heap->blocks); - } - else if (b->first_free == NULL) - { - /* move full blocks to the end of the list */ - mowgli_node_delete(&b->node, &heap->blocks); - mowgli_node_add(b, &b->node, &heap->blocks); - } - -#ifdef HEAP_DEBUG - /* debug */ - mowgli_log("mowgli_heap_alloc(heap = @%p) -> %p", heap, fn->data); -#endif - /* return pointer to it */ - return (char *)h + sizeof(mowgli_heap_elem_header_t); -} - -/* frees an item back to the mowgli_heap_t */ -void -mowgli_heap_free(mowgli_heap_t *heap, void *data) -{ - mowgli_block_t *b; - mowgli_heap_elem_header_t *h; - - h = (mowgli_heap_elem_header_t *)((char *)data - sizeof(mowgli_heap_elem_header_t)); - b = h->un.block; - - return_if_fail(b->heap == heap); - return_if_fail(b->num_allocated > 0); - - /* memset the element before returning it to the heap. */ - memset(data, 0, b->heap->elem_size); - - /* mark it as free */ - h->un.next = b->first_free; - b->first_free = h; - - /* keep count */ - heap->free_elems++; - b->num_allocated--; -#ifdef HEAP_DEBUG - /* debug */ - mowgli_log("mowgli_heap_free(heap = @%p, data = %p)", heap, data); -#endif - /* move it between the lists if needed */ - if (b->num_allocated == 0) - { - if (heap->empty_block != NULL) - mowgli_heap_shrink(heap, heap->empty_block); - mowgli_node_delete(&b->node, &heap->blocks); - heap->empty_block = b; - } - else if (b->num_allocated == heap->mowgli_heap_elems - 1) - { - mowgli_node_delete(&b->node, &heap->blocks); - mowgli_node_add_head(b, &b->node, &heap->blocks); - } -} |