diff options
Diffstat (limited to 'media/sphinxbase/src/libsphinxbase/util/listelem_alloc.c')
-rw-r--r-- | media/sphinxbase/src/libsphinxbase/util/listelem_alloc.c | 294 |
1 files changed, 0 insertions, 294 deletions
diff --git a/media/sphinxbase/src/libsphinxbase/util/listelem_alloc.c b/media/sphinxbase/src/libsphinxbase/util/listelem_alloc.c deleted file mode 100644 index 354c4767c..000000000 --- a/media/sphinxbase/src/libsphinxbase/util/listelem_alloc.c +++ /dev/null @@ -1,294 +0,0 @@ -/* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* ==================================================================== - * Copyright (c) 1999-2004 Carnegie Mellon University. All rights - * reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * This work was supported in part by funding from the Defense Advanced - * Research Projects Agency and the National Science Foundation of the - * United States of America, and the CMU Sphinx Speech Consortium. - * - * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND - * ANY EXPRESSED 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 CARNEGIE MELLON UNIVERSITY - * NOR ITS EMPLOYEES 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. - * - * ==================================================================== - * - */ - -#include <stdio.h> -#include <stdlib.h> - -#include "sphinxbase/err.h" -#include "sphinxbase/ckd_alloc.h" -#include "sphinxbase/listelem_alloc.h" -#include "sphinxbase/glist.h" - -/** - * Fast linked list allocator. - * - * We keep a separate linked list for each element-size. Element-size - * must be a multiple of pointer-size. - * - * Initially a block of empty elements is allocated, where the first - * machine word in each element points to the next available element. - * To allocate, we use this pointer to move the freelist to the next - * element, then return the current element. - * - * The last element in the list starts with a NULL pointer, which is - * used as a signal to allocate a new block of elements. - * - * In order to be able to actually release the memory allocated, we - * have to add a linked list of block pointers. This shouldn't create - * much overhead since we never access it except when freeing the - * allocator. - */ -struct listelem_alloc_s { - char **freelist; /**< ptr to first element in freelist */ - glist_t blocks; /**< Linked list of blocks allocated. */ - glist_t blocksize; /**< Number of elements in each block */ - size_t elemsize; /**< Number of (char *) in element */ - size_t blk_alloc; /**< Number of alloc operations before increasing blocksize */ - size_t n_blocks; - size_t n_alloc; - size_t n_freed; -}; - -#define MIN_ALLOC 50 /**< Minimum number of elements to allocate in one block */ -#define BLKID_SHIFT 16 /**< Bit position of block number in element ID */ -#define BLKID_MASK ((1<<BLKID_SHIFT)-1) - -/** - * Allocate a new block of elements. - */ -static void listelem_add_block(listelem_alloc_t *list, - char *caller_file, int caller_line); - -listelem_alloc_t * -listelem_alloc_init(size_t elemsize) -{ - listelem_alloc_t *list; - - if ((elemsize % sizeof(void *)) != 0) { - size_t rounded = (elemsize + sizeof(void *) - 1) & ~(sizeof(void *)-1); - E_WARN - ("List item size (%lu) not multiple of sizeof(void *), rounding to %lu\n", - (unsigned long)elemsize, - (unsigned long)rounded); - elemsize = rounded; - } - list = ckd_calloc(1, sizeof(*list)); - list->freelist = NULL; - list->blocks = NULL; - list->elemsize = elemsize; - /* Intent of this is to increase block size once we allocate - * 256KiB (i.e. 1<<18). If somehow the element size is big enough - * to overflow that, just fail, people should use malloc anyway. */ - list->blk_alloc = (1 << 18) / (MIN_ALLOC * elemsize); - if (list->blk_alloc <= 0) { - E_ERROR("Element size * block size exceeds 256k, use malloc instead.\n"); - ckd_free(list); - return NULL; - } - list->n_alloc = 0; - list->n_freed = 0; - - /* Allocate an initial block to minimize latency. */ - listelem_add_block(list, __FILE__, __LINE__); - return list; -} - -void -listelem_alloc_free(listelem_alloc_t *list) -{ - gnode_t *gn; - if (list == NULL) - return; - for (gn = list->blocks; gn; gn = gnode_next(gn)) - ckd_free(gnode_ptr(gn)); - glist_free(list->blocks); - glist_free(list->blocksize); - ckd_free(list); -} - -static void -listelem_add_block(listelem_alloc_t *list, char *caller_file, int caller_line) -{ - char **cpp, *cp; - size_t j; - int32 blocksize; - - blocksize = list->blocksize ? gnode_int32(list->blocksize) : MIN_ALLOC; - /* Check if block size should be increased (if many requests for this size) */ - if (list->blk_alloc == 0) { - /* See above. No sense in allocating blocks bigger than - * 256KiB (well, actually, there might be, but we'll worry - * about that later). */ - blocksize <<= 1; - if (blocksize * list->elemsize > (1 << 18)) - blocksize = (1 << 18) / list->elemsize; - list->blk_alloc = (1 << 18) / (blocksize * list->elemsize); - } - - /* Allocate block */ - cpp = list->freelist = - (char **) __ckd_calloc__(blocksize, list->elemsize, - caller_file, caller_line); - list->blocks = glist_add_ptr(list->blocks, cpp); - list->blocksize = glist_add_int32(list->blocksize, blocksize); - cp = (char *) cpp; - /* Link up the blocks via their first machine word. */ - for (j = blocksize - 1; j > 0; --j) { - cp += list->elemsize; - *cpp = cp; - cpp = (char **) cp; - } - /* Make sure the last element's forward pointer is NULL */ - *cpp = NULL; - --list->blk_alloc; - ++list->n_blocks; -} - - -void * -__listelem_malloc__(listelem_alloc_t *list, char *caller_file, int caller_line) -{ - char **ptr; - - /* Allocate a new block if list empty */ - if (list->freelist == NULL) - listelem_add_block(list, caller_file, caller_line); - - /* Unlink and return first element in freelist */ - ptr = list->freelist; - list->freelist = (char **) (*(list->freelist)); - (list->n_alloc)++; - - return (void *)ptr; -} - -void * -__listelem_malloc_id__(listelem_alloc_t *list, char *caller_file, - int caller_line, int32 *out_id) -{ - char **ptr; - - /* Allocate a new block if list empty */ - if (list->freelist == NULL) - listelem_add_block(list, caller_file, caller_line); - - /* Unlink and return first element in freelist */ - ptr = list->freelist; - list->freelist = (char **) (*(list->freelist)); - (list->n_alloc)++; - - if (out_id) { - int32 blksize, blkidx, ptridx; - gnode_t *gn, *gn2; - char **block; - - gn2 = list->blocksize; - block = NULL; - blkidx = 0; - for (gn = list->blocks; gn; gn = gnode_next(gn)) { - block = gnode_ptr(gn); - blksize = gnode_int32(gn2) * list->elemsize / sizeof(*block); - if (ptr >= block && ptr < block + blksize) - break; - gn2 = gnode_next(gn2); - ++blkidx; - } - if (gn == NULL) { - E_ERROR("Failed to find block index for pointer %p!\n", ptr); - } - ptridx = (ptr - block) / (list->elemsize / sizeof(*block)); - E_DEBUG(4,("ptr %p block %p blkidx %d ptridx %d\n", - ptr, block, list->n_blocks - blkidx - 1, ptridx)); - *out_id = ((list->n_blocks - blkidx - 1) << BLKID_SHIFT) | ptridx; - } - - return ptr; -} - -void * -listelem_get_item(listelem_alloc_t *list, int32 id) -{ - int32 blkidx, ptridx, i; - gnode_t *gn; - - blkidx = (id >> BLKID_SHIFT) & BLKID_MASK; - ptridx = id & BLKID_MASK; - - i = 0; - blkidx = list->n_blocks - blkidx; - for (gn = list->blocks; gn; gn = gnode_next(gn)) { - if (++i == blkidx) - break; - } - if (gn == NULL) { - E_ERROR("Failed to find block index %d\n", blkidx); - return NULL; - } - - return (void *)((char **)gnode_ptr(gn) - + ptridx * (list->elemsize / sizeof(void *))); -} - -void -__listelem_free__(listelem_alloc_t *list, void *elem, - char *caller_file, int caller_line) -{ - char **cpp; - - /* - * Insert freed item at head of list. - */ - cpp = (char **) elem; - *cpp = (char *) list->freelist; - list->freelist = cpp; - (list->n_freed)++; -} - - -void -listelem_stats(listelem_alloc_t *list) -{ - gnode_t *gn, *gn2; - char **cpp; - size_t n; - - E_INFO("Linklist stats:\n"); - for (n = 0, cpp = list->freelist; cpp; - cpp = (char **) (*cpp), n++); - E_INFO - ("elemsize %lu, #alloc %lu, #freed %lu, #freelist %lu\n", - (unsigned long)list->elemsize, - (unsigned long)list->n_alloc, - (unsigned long)list->n_freed, - (unsigned long)n); - E_INFO("Allocated blocks:\n"); - gn2 = list->blocksize; - for (gn = list->blocks; gn; gn = gnode_next(gn)) { - E_INFO("%p (%d * %d bytes)\n", gnode_ptr(gn), gnode_int32(gn2), list->elemsize); - gn2 = gnode_next(gn2); - } -} |