Index: apps/codecs/lib/SOURCES =================================================================== --- apps/codecs/lib/SOURCES (revision 19952) +++ apps/codecs/lib/SOURCES (working copy) @@ -13,3 +13,8 @@ #elif defined(SIMULATOR) && defined(__APPLE__) osx.dummy.c #endif + +bmalloc.c +dmalloc.c +bysize.c + Index: apps/codecs/lib/bysize.c =================================================================== --- apps/codecs/lib/bysize.c (revision 0) +++ apps/codecs/lib/bysize.c (revision 0) @@ -0,0 +1,449 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: test_codec.c 19834 2009-01-24 03:47:09Z jethead71 $ + * + * Copyright (C) 2009 Daniel Stenberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/***************************************************************************** + * + * Size-sorted list/tree functions. + * + * Author: Daniel Stenberg + * Date: March 7, 1997 + * Version: 2.0 + * Email: Daniel.Stenberg@sth.frontec.se + * + * + * v2.0 + * - Added SPLAY TREE functionality. + * + * Adds and removes CHUNKS from a list or tree. + * + ****************************************************************************/ + +//#include +//#include +#include +#include "codeclib.h" +#define printf DEBUGF + +#define SPLAY /* we use the splay version as that is much faster */ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef SPLAY /* these routines are for the non-splay version */ + +struct ChunkInfo { + struct ChunkInfo *larger; + struct ChunkInfo *smaller; + size_t size; +}; + +/* the CHUNK list anchor */ +struct ChunkInfo *chunkHead=NULL; + +/*********************************************************************** + + findchunkbysize() + + Find the chunk that is smaller than the input size. Returns + NULL if none is. + + **********************************************************************/ + +static struct ChunkInfo *findchunkbysize(size_t size) +{ + struct ChunkInfo *test = chunkHead; + struct ChunkInfo *smaller = NULL; + while(test && (test->size < size)) { + smaller = test; + test = test->larger; + } + return smaller; +} + +/*********************************************************************** + + remove_chunksize() + + Remove the chunk from the size-sorted list. + ***********************************************************************/ + +void remove_chunksize(void *data) +{ + struct ChunkInfo *chunk = (struct ChunkInfo *)data; + if(chunk->smaller) + chunk->smaller->larger = chunk->larger; + else { + /* if this has no smaller, this is the head */ + chunkHead = chunk->larger; /* new head */ + } + if(chunk->larger) + chunk->larger->smaller = chunk->smaller; +} + +void insert_bysize(char *data, size_t size) +{ + struct ChunkInfo *newchunk = (struct ChunkInfo *)data; + struct ChunkInfo *chunk = findchunkbysize ( size ); + + newchunk->size = size; + + if(chunk) { + /* 'chunk' is smaller than size, append the new chunk ahead of this */ + newchunk->smaller = chunk; + newchunk->larger = chunk->larger; + if(chunk->larger) + chunk->larger->smaller = newchunk; + chunk->larger = newchunk; + } + else { + /* smallest CHUNK around, append first in the list */ + newchunk->larger = chunkHead; + newchunk->smaller = NULL; + + if(chunkHead) + chunkHead->smaller = newchunk; + chunkHead = newchunk; + } +} + +char *obtainbysize( size_t size) +{ + struct ChunkInfo *chunk = findchunkbysize( size ); + + if(!chunk) { + if(size <= (chunkHead->size)) + /* there is no smaller CHUNK, use the first one (if we fit within that) + */ + chunk = chunkHead; + } + else + /* we're on the last CHUNK that is smaller than requested, step onto + the bigger one */ + chunk = chunk->larger; + + if(chunk) { + remove_chunksize( chunk ); /* unlink size-wise */ + return (char *)chunk; + } + else + return NULL; +} + +void print_sizes(void) +{ + struct ChunkInfo *chunk = chunkHead; + printf("List of CHUNKS (in size order):\n"); +#if 1 + while(chunk) { + printf(" START %p END %p SIZE %d\n", + chunk, (char *)chunk+chunk->size, chunk->size); + chunk = chunk->larger; + } +#endif + printf("End of CHUNKS:\n"); +} + +#else /* Here follows all routines dealing with the SPLAY TREES */ + +typedef struct tree_node Tree; +struct tree_node { + Tree *smaller; /* smaller node */ + Tree *larger; /* larger node */ + Tree *same; /* points to a node with identical key */ + int key; /* the "sort" key */ +}; + +Tree *chunkHead = NULL; /* the root */ + +#define compare(i,j) ((i)-(j)) + +/* Set this to a key value that will *NEVER* appear otherwise */ +#define KEY_NOTUSED -1 + +/* + * Splay using the key i (which may or may not be in the tree.) The starting + * root is t. Weight fields are maintained. + */ +Tree * splay (int i, Tree *t) +{ + Tree N, *l, *r, *y; + int comp; + + if (t == NULL) + return t; + N.smaller = N.larger = NULL; + l = r = &N; + + for (;;) { + comp = compare(i, t->key); + if (comp < 0) { + if (t->smaller == NULL) + break; + if (compare(i, t->smaller->key) < 0) { + y = t->smaller; /* rotate smaller */ + t->smaller = y->larger; + y->larger = t; + + t = y; + if (t->smaller == NULL) + break; + } + r->smaller = t; /* link smaller */ + r = t; + t = t->smaller; + } + else if (comp > 0) { + if (t->larger == NULL) + break; + if (compare(i, t->larger->key) > 0) { + y = t->larger; /* rotate larger */ + t->larger = y->smaller; + y->smaller = t; + t = y; + if (t->larger == NULL) + break; + } + l->larger = t; /* link larger */ + l = t; + t = t->larger; + } + else { + break; + } + } + + l->larger = r->smaller = NULL; + + l->larger = t->smaller; /* assemble */ + r->smaller = t->larger; + t->smaller = N.larger; + t->larger = N.smaller; + + return t; +} + +/* Insert key i into the tree t. Return a pointer to the resulting tree or + NULL if something went wrong. */ +Tree *insert(int i, Tree *t, Tree *new) +{ + if (new == NULL) { + return t; + } + + if (t != NULL) { + t = splay(i,t); + if (compare(i, t->key)==0) { + /* it already exists one of this size */ + + new->same = t; + new->key = i; + new->smaller = t->smaller; + new->larger = t->larger; + + t->smaller = new; + t->key = KEY_NOTUSED; + + return new; /* new root node */ + } + } + + if (t == NULL) { + new->smaller = new->larger = NULL; + } + else if (compare(i, t->key) < 0) { + new->smaller = t->smaller; + new->larger = t; + t->smaller = NULL; + } + else { + new->larger = t->larger; + new->smaller = t; + t->larger = NULL; + } + new->key = i; + + new->same = NULL; /* no identical node (yet) */ + + return new; +} + +/* Finds and deletes the best-fit node from the tree. Return a pointer to the + resulting tree. best-fit means the smallest node that fits the requested + size. */ +Tree *removebestfit(int i, Tree *t, Tree **removed) +{ + Tree *x; + + if (t==NULL) + return NULL; + t = splay(i,t); + if(compare(i, t->key) > 0) { + /* too small node, try the larger chain */ + if(t->larger) + t=splay(t->larger->key, t); + else { + /* fail */ + *removed = NULL; + return t; + } + } + + if (compare(i, t->key) <= 0) { /* found it */ + + /* FIRST! Check if there is a list with identical sizes */ + x = t->same; + if(x) { + /* there is, pick one from the list */ + + /* 'x' is the new root node */ + + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + *removed = t; + return x; /* new root */ + } + + if (t->smaller == NULL) { + x = t->larger; + } + else { + x = splay(i, t->smaller); + x->larger = t->larger; + } + *removed = t; + + return x; + } + else { + *removed = NULL; /* no match */ + return t; /* It wasn't there */ + } +} + + +/* Deletes the node we point out from the tree if it's there. Return a pointer + to the resulting tree. */ +Tree *removebyaddr(Tree *t, Tree *remove) +{ + Tree *x; + + if (!t || !remove) + return NULL; + + if(KEY_NOTUSED == remove->key) { + /* just unlink ourselves nice and quickly: */ + remove->smaller->same = remove->same; + if(remove->same) + remove->same->smaller = remove->smaller; + /* voila, we're done! */ + return t; + } + + t = splay(remove->key,t); + + /* Check if there is a list with identical sizes */ + + x = t->same; + if(x) { + /* 'x' is the new root node */ + + x->key = t->key; + x->larger = t->larger; + x->smaller = t->smaller; + + return x; /* new root */ + } + + /* Remove the actualy root node: */ + + if (t->smaller == NULL) { + x = t->larger; + } + else { + x = splay(remove->key, t->smaller); + x->larger = t->larger; + } + + return x; +} +#if 0 +int printtree(Tree * t, int d, char output) +{ + int distance=0; + Tree *node; + int i; + if (t == NULL) + return 0; + distance += printtree(t->larger, d+1, output); + for (i=0; ikey, i); + } + + for(node = t->same; node; node = node->same) { + distance += i; /* this has the same "virtual" distance */ + + if(output) + printf(" [+]"); + } + if(output) + puts(""); + + distance += i; + distance += printtree(t->smaller, d+1, output); + return distance; +} +#endif +/* Here follow the look-alike interface so that the tree-function names are + the same as the list-ones to enable easy interchange */ + +void remove_chunksize(void *data) +{ + chunkHead = removebyaddr(chunkHead, data); +} + +void insert_bysize(char *data, size_t size) +{ + chunkHead = insert(size, chunkHead, (Tree *)data); +} + +char *obtainbysize( size_t size) +{ + Tree *receive; + chunkHead = removebestfit(size, chunkHead, &receive); + return (char *)receive; +} + +/* +void print_sizes(void) +{ + printtree(chunkHead, 0, 1); +} +*/ +#endif Property changes on: apps/codecs/lib/bysize.c ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/lib/bmalloc.c =================================================================== --- apps/codecs/lib/bmalloc.c (revision 0) +++ apps/codecs/lib/bmalloc.c (revision 0) @@ -0,0 +1,394 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: test_codec.c 19834 2009-01-24 03:47:09Z jethead71 $ + * + * Copyright (C) 2009 Daniel Stenberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/***************************************************************************** + * + * Big (best-fit) Memory Allocation + * + * Author: Daniel Stenberg + * Date: March 5, 1997 + * Version: 2.0 + * Email: Daniel.Stenberg@sth.frontec.se + * + * + * Read 'thoughts' for theories and details in implementation. + * + * Routines meant to replace the most low level functions of an Operting + * System + * + * v2.0 + * - Made all size-routines get moved out from this file. This way, the size + * functions can much more easily get replaced. + * - Improved how new memory blocks get added to the size-sorted list. When + * not adding new pools, there should never ever be any list traversing + * since all information is dynamically gathered. + * + ****************************************************************************/ + +//#include +//#include +#include +#include "codeclib.h" +#define printf DEBUGF + +#include "bysize.h" + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* #define DEBUG */ + +#define BMEM_ALIGN 64 /* resolution */ + +#define BMEMERR_TOOSMALL -1 + +/* this struct will be stored in all CHUNKS and AREAS */ +struct BlockInfo { + struct BlockInfo *lower; /* previous block in memory (lower address) */ + struct BlockInfo *higher; /* next block in memory (higher address) */ + unsigned long info; /* 31 bits size: 1 bit free boolean */ +#define INFO_FREE 1 +#define INFO_SIZE (~ INFO_FREE) /* inverted FREE bit pattern */ + + /* FREE+SIZE Could be written to use ordinary bitfields if using a smart + (like gcc) compiler in a manner like: + int size:31; + int free:1; + + The 'higher' pointer COULD be removed completely if the size is used as + an index to the higher one. This would then REQUIRE the entire memory + pool to be contiguous and it needs a 'terminating' "node" or an extra + flag that informs about the end of the list. + */ +}; + +/* the BLOCK list should be sorted in a lower to higher address order */ +struct BlockInfo *blockHead=NULL; /* nothing from the start */ + +void print_lists(void); + + +/*********************************************************************** + * + * remove_block() + * + * Remove the block from the address-sorted list. + * + ***********************************************************************/ + +void remove_block(struct BlockInfo *block) +{ + if(block->lower) + block->lower->higher = block->higher; + else + blockHead = block->higher; + if(block->higher) + block->higher->lower = block->lower; +} + +/**************************************************************************** + * + * add_blocktolists() + * + * Adds the specified block at the specified place in the address-sorted + * list and at the appropriate place in the size-sorted. + * + ***************************************************************************/ +void add_blocktolists(struct BlockInfo *block, + struct BlockInfo *newblock, + size_t newsize) +{ + struct BlockInfo *temp; /* temporary storage variable */ + if(block) { + /* `block' is now a lower address than 'newblock' */ + + /* + * Check if the new CHUNK is wall-to-wall with the lower addressed + * one (if *that* is free) + */ + if(block->info&INFO_FREE) { + if((char *)block + (block->info&INFO_SIZE) == (char *)newblock) { + /* yes sir, this is our lower address neighbour, enlarge that one + pick it out from the list and recursively add that chunk and + then we escape */ + + /* remove from size-sorted list: */ + remove_chunksize((char*)block+sizeof(struct BlockInfo)); + + block->info += newsize; /* newsize is an even number and thus the FREE + bit is untouched */ + + remove_block(block); /* unlink the block address-wise */ + + /* recursively check our lower friend(s) */ + add_blocktolists(block->lower, block, block->info&INFO_SIZE); + return; + } + } + + temp = block->higher; + + block->higher = newblock; + newblock->lower = block; + newblock->higher = temp; + if(newblock->higher) + newblock->higher->lower = newblock; + } + else { + /* this block should preceed the heading one */ + temp = blockHead; + + /* check if this is our higher addressed neighbour */ + if((char *)newblock + newsize == (char *)temp) { + + /* yes, we are wall-to-wall with the higher CHUNK */ + if(temp->info&INFO_FREE) { + /* and the neighbour is even free, remove that one and enlarge + ourselves, call add_pool() recursively and then escape */ + + remove_block(temp); /* unlink 'temp' from list */ + + /* remove from size-sorted list: */ + remove_chunksize((char*)temp+sizeof(struct BlockInfo) ); + + /* add the upper block's size on ourselves */ + newsize += temp->info&INFO_SIZE; + + /* add the new, bigger block */ + add_blocktolists(block, newblock, newsize); + return; + } + } + + blockHead = newblock; + newblock->higher = temp; + newblock->lower = NULL; /* there is no lower one */ + if(newblock->higher) + newblock->higher->lower = newblock; + } + + newblock->info = newsize | INFO_FREE; /* we do assume size isn't using the + FREE bit */ + insert_bysize((char *)newblock+sizeof(struct BlockInfo), newsize); +} + +/*********************************************************************** + * + * findblockbyaddr() + * + * Find the block that is just before the input block in memory. Returns NULL + * if none is. + * + ***********************************************************************/ + +static struct BlockInfo *findblockbyaddr(struct BlockInfo *block) +{ + struct BlockInfo *test = blockHead; + struct BlockInfo *lower = NULL; + + while(test && (test < block)) { + lower = test; + test = test->higher; + } + return lower; +} + +/*********************************************************************** + * + * add_pool() + * + * This function should be the absolutely first function to call. It sets up + * the memory bounds of the [first] CHUNK(s). It should be possible to call + * this function several times to add more CHUNKs to the pool of free + * memory. This allows the bmalloc system to deal with a non-contigous memory + * area. + * + * Returns non-zero if an error occured. The memory was not added then. + * + ***********************************************************************/ + +int add_pool(void *start, + size_t size) +{ + struct BlockInfo *newblock = (struct BlockInfo *)start; + struct BlockInfo *block; + + if(size < BMEM_ALIGN) + return BMEMERR_TOOSMALL; + + block = findblockbyaddr( newblock ); + /* `block' is now a lower address than 'newblock' or NULL */ + + if(size&1) + size--; /* only add even sizes */ + + add_blocktolists(block, newblock, size); + + return 0; +} + + +#ifdef DEBUG +static void bmalloc_failed(size_t size) +{ + printf("*** " __FILE__ " Couldn't allocate %d bytes\n", size); + print_lists(); +} +#else +#define bmalloc_failed(x) +#endif + +void print_lists() +{ + struct BlockInfo *block = blockHead; +#if 1 + printf("List of BLOCKS (in address order):\n"); + while(block) { + printf(" START %p END %p SIZE %ld FLAG %s\n", + (char *)block, + (char *)block+(block->info&INFO_SIZE), block->info&INFO_SIZE, + (block->info&INFO_FREE)?"free":"used"); + block = block->higher; + } + printf("End of BLOCKS:\n"); +#endif + print_sizes(); +} + +void *bmalloc(size_t size) +{ + void *mem; + +#ifdef DEBUG + { + static int count=0; + int realsize = size + sizeof(struct BlockInfo); + if(realsize%4096) + realsize = ((size / BMEM_ALIGN)+1) * BMEM_ALIGN; + printf("%d bmalloc(%d) [%d]\n", count++, size, realsize); + } +#endif + + size += sizeof(struct BlockInfo); /* add memory for our header */ + + if(size&(BMEM_ALIGN-1)) /* a lot faster than %BMEM_ALIGN but this MUST be + changed if the BLOCKSIZE is not 2^X ! */ + size = ((size / BMEM_ALIGN)+1) * BMEM_ALIGN; /* align like this */ + + /* get a CHUNK from the list with this size */ + mem = obtainbysize ( size ); + if(mem) { + /* the memory block we have got is the "best-fit" and it is already + un-linked from the free list */ + + /* now do the math to get the proper block pointer */ + struct BlockInfo *block= (struct BlockInfo *) + ((char *)mem - sizeof(struct BlockInfo)); + + block->info &= ~INFO_FREE; + /* not free anymore */ + + if( size != (block->info&INFO_SIZE)) { + /* split this chunk into two pieces and return the one that fits us */ + size_t othersize = (block->info&INFO_SIZE) - size; + + if(othersize > BMEM_ALIGN) { + /* prevent losing small pieces of memory due to weird alignments + of the memory pool */ + + block->info = size; /* set new size (leave FREE bit cleared) */ + + /* Add the new chunk to the lists: */ + add_blocktolists(block, + (struct BlockInfo *)((char *)block + size), + othersize ); + } + } + + /* Return the memory our parent may use: */ + return (char *)block+sizeof(struct BlockInfo); + } + else { + bmalloc_failed(size); + return NULL; /* can't find any memory, fail hard */ + } + return NULL; +} + +void bfree(void *ptr) +{ + struct BlockInfo *block = (struct BlockInfo *) + ((char *)ptr - sizeof(struct BlockInfo)); + size_t size; + + /* setup our initial higher and lower pointers */ + struct BlockInfo *lower = block->lower; + struct BlockInfo *higher = block->higher; + +#ifdef DEBUG + static int freecount=0; + printf("%d bfree(%p)\n", freecount++, ptr); +#endif + + /* bind together lower addressed FREE CHUNKS */ + if(lower && (lower->info&INFO_FREE) && + ((char *)lower + (lower->info&INFO_SIZE) == (char *)block)) { + size = block->info&INFO_SIZE; /* original size */ + + /* remove from size-link: */ + remove_chunksize((char *)lower+sizeof(struct BlockInfo)); + + remove_block(block); /* unlink from address list */ + block = lower; /* new base area pointer */ + block->info += size; /* append the new size (the FREE bit + will remain untouched) */ + + lower = lower->lower; /* new lower pointer */ + } + /* bind together higher addressed FREE CHUNKS */ + if(higher && (higher->info&INFO_FREE) && + ((char *)block + (block->info&INFO_SIZE) == (char *)higher)) { + /* append higher size, the FREE bit won't be affected */ + block->info += (higher->info&INFO_SIZE); + + /* unlink from size list: */ + remove_chunksize((char *)higher+sizeof(struct BlockInfo)); + remove_block(higher); /* unlink from address list */ + higher = higher->higher; /* the new higher link */ + block->higher = higher; /* new higher link */ + } + block->info |= INFO_FREE; /* consider this FREE! */ + + block->lower = lower; + block->higher = higher; + + insert_bysize((char *)block+sizeof(struct BlockInfo), block->info&INFO_SIZE); + +#ifdef DEBUG + print_lists(); +#endif + +} + Property changes on: apps/codecs/lib/bmalloc.c ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/lib/codeclib.h =================================================================== --- apps/codecs/lib/codeclib.h (revision 19952) +++ apps/codecs/lib/codeclib.h (working copy) @@ -46,6 +46,13 @@ void* codec_realloc(void* ptr, size_t size); void codec_free(void* ptr); +/*dbestfit malloc functions*/ +void *dmalloc(size_t); +void dfree(void *); +void *drealloc(void *, size_t); +void *dcalloc (size_t, size_t); +int add_pool(void *start, size_t size); + void *memcpy(void *dest, const void *src, size_t n); void *memset(void *s, int c, size_t n); int memcmp(const void *s1, const void *s2, size_t n); Index: apps/codecs/lib/bysize.h =================================================================== --- apps/codecs/lib/bysize.h (revision 0) +++ apps/codecs/lib/bysize.h (revision 0) @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: test_codec.c 19834 2009-01-24 03:47:09Z jethead71 $ + * + * Copyright (C) 2009 Daniel Stenberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +void remove_chunksize(void *data); +void insert_bysize(char *data, size_t size); +char *obtainbysize( size_t size); +void print_sizes(void); Property changes on: apps/codecs/lib/bysize.h ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/lib/dmalloc.c =================================================================== --- apps/codecs/lib/dmalloc.c (revision 0) +++ apps/codecs/lib/dmalloc.c (revision 0) @@ -0,0 +1,707 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: test_codec.c 19834 2009-01-24 03:47:09Z jethead71 $ + * + * Copyright (C) 2009 Daniel Stenberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/***************************************************************************** + * + * Dynamic Memory Allocation + * + * Author: Daniel Stenberg + * Date: March 10, 1997 + * Version: 2.3 + * Email: Daniel.Stenberg@sth.frontec.se + * + * + * Read 'thoughts' for theories and details of this implementation. + * + * v2.1 + * - I once again managed to gain some memory. BLOCK allocations now only use + * a 4 bytes header (instead of previos 8) just as FRAGMENTS. + * + * v2.2 + * - Re-adjusted the fragment sizes to better fit into the somewhat larger + * block. + * + * v2.3 + * - Made realloc(NULL, size) work as it should. Which is like a malloc(size) + * + *****************************************************************************/ + +#include +#include "codeclib.h" + +#ifdef DEBUG +#include +#endif + +#ifdef PSOS +#include +#define SEMAPHORE /* the PSOS routines use semaphore protection */ +#endif + +#ifdef BMALLOC +#include "bmalloc.h" +#endif + +/* Each TOP takes care of a chain of BLOCKS */ +struct MemTop { + struct MemBlock *chain; /* pointer to the BLOCK chain */ + long nfree; /* total number of free FRAGMENTS in the chain */ + short nmax; /* total number of FRAGMENTS in this kind of BLOCK */ + size_t fragsize; /* the size of each FRAGMENT */ + +#ifdef SEMAPHORE /* if we're protecting the list with SEMAPHORES */ + long semaphore_id; /* semaphore used to lock this particular list */ +#endif + +}; + +/* Each BLOCK takes care of an amount of FRAGMENTS */ +struct MemBlock { + struct MemTop *top; /* our TOP struct */ + struct MemBlock *next; /* next BLOCK */ + struct MemBlock *prev; /* prev BLOCK */ + + struct MemFrag *first; /* the first free FRAGMENT in this block */ + + short nfree; /* number of free FRAGMENTS in this BLOCK */ +}; + +/* This is the data kept in all _free_ FRAGMENTS */ +struct MemFrag { + struct MemFrag *next; /* next free FRAGMENT */ + struct MemFrag *prev; /* prev free FRAGMENT */ +}; + +/* This is the data kept in all _allocated_ FRAGMENTS and BLOCKS. We add this + to the allocation size first thing in the ALLOC function to make room for + this smoothly. */ + +struct MemInfo { + void *block; + /* which BLOCK is our father, if BLOCK_BIT is set it means this is a + stand-alone, large allocation and then the rest of the bits should be + treated as the size of the block */ +#define BLOCK_BIT 1 +}; + +/* ---------------------------------------------------------------------- */ +/* Defines */ +/* ---------------------------------------------------------------------- */ + +#ifdef DEBUG +#define MEMINCR(addr,x) memchange(addr, x) +#define MEMDECR(addr,x) memchange(addr,-(x)) +#else +#define MEMINCR(a,x) +#define MEMDECR(a,x) +#endif + +/* The low level functions used to get memory from the OS and to return memory + to the OS, we may also define a stub that does the actual allocation and + free, these are the defined function names used in the dmalloc system + anyway: */ +#ifdef PSOS + +#ifdef DEBUG +#define DMEM_OSALLOCMEM(size,pointer,type) pointer=(type)dbgmalloc(size) +#define DMEM_OSFREEMEM(x) dbgfree(x) +#else +#define DMEM_OSALLOCMEM(size,pointer,type) rn_getseg(0,size,RN_NOWAIT,0,(void **)&pointer) +/* Similar, but this returns the memory */ +#define DMEM_OSFREEMEM(x) rn_retseg(0, x) +#endif + +/* Argument: */ +#define SEMAPHOREOBTAIN(x) sm_p(x, SM_WAIT, 0) +/* Argument: */ +#define SEMAPHORERETURN(x) sm_v(x) +/* Argument: */ +#define SEMAPHORECREATE(x,y) sm_create(x, 1, SM_FIFO, (ULONG *)&(y)) + +#else +#ifdef BMALLOC /* use our own big-memory-allocation system */ +#define DMEM_OSALLOCMEM(size,pointer,type) pointer=(type)bmalloc(size) +#define DMEM_OSFREEMEM(x) bfree(x) +#elif defined(DEBUG) +#define DMEM_OSALLOCMEM(size,pointer,type) pointer=(type)dbgmalloc(size) +#define DMEM_OSFREEMEM(x) dbgfree(x) +#else +#define DMEM_OSALLOCMEM(size,pointer,type) pointer=(type)malloc(size) +#define DMEM_OSFREEMEM(x) free(x) +#endif +#endif + + +/* the largest memory allocation that is made a FRAGMENT: (grab the highest + number from the list below) */ +#define DMEM_LARGESTSIZE 2032 + +/* The total size of a BLOCK used for FRAGMENTS + In order to make this use only *1* even alignment from the big-block- + allocation-system (possible the bmalloc() system also written by me) + we need to subtract the [maximum] struct sizes that could get added all + the way through to the grab from the memory. */ +#define DMEM_BLOCKSIZE 4064 /* (4096 - sizeof(struct MemBlock) - 12) */ + +/* Since the blocksize isn't an even 2^X story anymore, we make a table with + the FRAGMENT sizes and amounts that fills up a BLOCK nicely */ + +/* a little 'bc' script that helps us maximize the usage: + - for 32-bit aligned addresses (SPARC crashes otherwise): + for(i=20; i<2040; i++) { a=4064/i; if(a*i >= 4060) { if(i%4==0) {i;} } } + + + I try to approximate a double of each size, starting with ~20. We don't do + ODD sizes since several CPU flavours dump core when accessing such + addresses. We try to do 32-bit aligned to make ALL kinds of CPUs to remain + happy with us. + */ +#define BIGBLOCKS 4059 +#if BIGBLOCKS==4060 /* previously */ +unsigned short qinfo[]= { 20, 28, 52, 116, 312, 580, 812, 2028 }; +#else +unsigned short qinfo[]= { 20, 28, 52, 116, 312, 580, 1016, 2032}; +/* 52 and 312 only make use of 4056 bytes, but without them there are too + wide gaps */ +#endif + +//#define MIN(x,y) ((x)<(y)?(x):(y)) + +/* ---------------------------------------------------------------------- */ +/* Globals */ +/* ---------------------------------------------------------------------- */ + +/* keeper of the chain of BLOCKS */ +static struct MemTop top[ sizeof(qinfo)/sizeof(qinfo[0]) ]; + +/* are we experienced? */ +static char initialized = 0; + +/* ---------------------------------------------------------------------- */ +/* Start of the real code */ +/* ---------------------------------------------------------------------- */ + +#ifdef DEBUG +/************ + * A few functions that are verbose and tells us about the current status + * of the dmalloc system + ***********/ + +static void dmalloc_status() +{ + int i; + int used; + int num; + int totalfree=0; + struct MemBlock *block; + for(i=0; infree; + num++; + block = block->next; + } + printf("Q %d (FRAG %4d), USED %4d FREE %4ld (SIZE %4ld) BLOCKS %d\n", + i, top[i].fragsize, used, top[i].nfree, + top[i].nfree*top[i].fragsize, num); + totalfree += top[i].nfree*top[i].fragsize; + } + printf("Total unused memory stolen by dmalloc: %d\n", totalfree); +} + +static void dmalloc_failed(size_t size) +{ + printf("*** " __FILE__ " Couldn't allocate %d bytes\n", size); + dmalloc_status(); +} +#else +#define dmalloc_failed(x) +#endif + +#ifdef DEBUG + +#define BORDER 1200 + +void *dbgmalloc(int size) +{ + char *mem; + size += BORDER; +#ifdef PSOS + rn_getseg(0,size,RN_NOWAIT,0,(void **)&mem); +#else + mem = malloc(size); +#endif + if(mem) { + memset(mem, 0xaa, BORDER/2); + memset(mem+BORDER/2, 0xbb, size -BORDER); + memset(mem-BORDER/2+size, 0xcc, BORDER/2); + *(long *)mem = size; + mem += (BORDER/2); + } + printf("OSmalloc(%p)\n", mem); + return (void *)mem; +} + +void checkmem(char *ptr) +{ + int i; + long size; + ptr -= BORDER/2; + + for(i=4; i<(BORDER/2); i++) + if((unsigned char)ptr[i] != 0xaa) { + printf("########### ALERT ALERT\n"); + break; + } + size = *(long *)ptr; + for(i=size-1; i>=(size - BORDER/2); i--) + if((unsigned char)ptr[i] != 0xcc) { + printf("********* POST ALERT\n"); + break; + } +} + +void dbgfree(char *ptr) +{ + long size; + checkmem(ptr); + ptr -= BORDER/2; + size = *(long *)ptr; + + printf("OSfree(%ld)\n", size); +#ifdef PSOS + rn_retseg(0, ptr); +#else + free(ptr); +#endif +} + + +#define DBG(x) syslog x + +void syslog(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stdout, fmt, ap); + va_end(ap); +} + +void memchange(void *a, int x) +{ + static int memory=0; + static int count=0; + static int max=0; + if(memory > max) + max = memory; + memory += x; + DBG(("%d. PTR %p / %d TOTAL %d MAX %d\n", ++count, a, x, memory, max)); +} +#else +#define DBG(x) +#endif + +/**************************************************************************** + * + * FragBlock() + * + * This function makes FRAGMENTS of the BLOCK sent as argument. + * + ***************************************************************************/ + +static void FragBlock(char *memp, int size) +{ + struct MemFrag *frag=(struct MemFrag *)memp; + struct MemFrag *prev=NULL; /* no previous in the first round */ + int count=0; + while((count+size) <= DMEM_BLOCKSIZE) { + memp += size; + frag->next = (struct MemFrag *)memp; + frag->prev = prev; + prev = frag; + frag = frag->next; + count += size; + } + prev->next = NULL; /* the last one has no next struct */ +} + +/*************************************************************************** + * + * initialize(); + * + * Called in the first dmalloc(). Inits a few memory things. + * + **************************************************************************/ +static void initialize(void) +{ + unsigned int i; + /* Setup the nmax and fragsize fields of the top structs */ + for(i=0; i< sizeof(qinfo)/sizeof(qinfo[0]); i++) { + top[i].fragsize = qinfo[i]; + top[i].nmax = DMEM_BLOCKSIZE/qinfo[i]; + +#ifdef PSOS + /* for some reason, these aren't nulled from start: */ + top[i].chain = NULL; /* no BLOCKS */ + top[i].nfree = 0; /* no FRAGMENTS */ +#endif +#ifdef SEMAPHORE + { + char name[7]; + sprintf(name, "MEM%d", i); + SEMAPHORECREATE(name, top[i].semaphore_id); + /* doesn't matter if it failed, we continue anyway ;-( */ + } +#endif + } + initialized = 1; +} + +/**************************************************************************** + * + * FragFromBlock() + * + * This should return a fragment from the block and mark it as used + * accordingly. + * + ***************************************************************************/ + +static void *FragFromBlock(struct MemBlock *block) +{ + /* make frag point to the first free FRAGMENT */ + struct MemFrag *frag = block->first; + struct MemInfo *mem = (struct MemInfo *)frag; + + /* + * Remove the FRAGMENT from the list and decrease the free counters. + */ + block->first = frag->next; /* new first free FRAGMENT */ + + block->nfree--; /* BLOCK counter */ + block->top->nfree--; /* TOP counter */ + + /* heal the FRAGMENT list */ + if(frag->prev) { + frag->prev->next = frag->next; + } + if(frag->next) { + frag->next->prev = frag->prev; + } + mem->block = block; /* no block bit set here */ + + return ((char *)mem)+sizeof(struct MemInfo); +} + +/*************************************************************************** + * + * dmalloc() + * + * This needs no explanation. A malloc() look-alike. + * + **************************************************************************/ + +void *dmalloc(size_t size) +{ + void *mem; + + if(!initialized) + initialize(); + + /* First, we make room for the space needed in every allocation */ + size += sizeof(struct MemInfo); + + if(size < DMEM_LARGESTSIZE) { + /* get a FRAGMENT */ + + struct MemBlock *block=NULL; /* SAFE */ + struct MemBlock *newblock=NULL; /* SAFE */ + struct MemTop *memtop=NULL; /* SAFE */ + + /* Determine which queue to use */ + unsigned int queue; + for(queue=0; size > qinfo[queue]; queue++) + ; + do { + /* This is the head master of our chain: */ + memtop = &top[queue]; + + DBG(("Top info: %p %d %d %d\n", + memtop->chain, + memtop->nfree, + memtop->nmax, + memtop->fragsize)); + +#ifdef SEMAPHORE + if(SEMAPHOREOBTAIN(memtop->semaphore_id)) + return NULL; /* failed somehow */ +#endif + + /* get the first BLOCK in the chain */ + block = memtop->chain; + + /* check if we have a free FRAGMENT */ + if(memtop->nfree) { + /* there exists a free FRAGMENT in this chain */ + + /* I WANT THIS LOOP OUT OF HERE! */ + + /* search for the free FRAGMENT */ + while(!block->nfree) + block = block->next; /* check next BLOCK */ + + /* + * Now 'block' is the first BLOCK with a free FRAGMENT + */ + + mem = FragFromBlock(block); + + } + else { + /* we do *not* have a free FRAGMENT but need to get us a new BLOCK */ + + DMEM_OSALLOCMEM(DMEM_BLOCKSIZE + sizeof(struct MemBlock), + newblock, + struct MemBlock *); + if(!newblock) { + if(++queue < sizeof(qinfo)/sizeof(qinfo[0])) { + /* There are queues for bigger FRAGMENTS that we should check + before we fail this for real */ +#ifdef DEBUG + printf("*** " __FILE__ " Trying a bigger Q: %d\n", queue); +#endif + mem = NULL; + } + else { + dmalloc_failed(size- sizeof(struct MemInfo)); + return NULL; /* not enough memory */ + } + } + else { + /* allocation of big BLOCK was successful */ + + MEMINCR(newblock, DMEM_BLOCKSIZE + sizeof(struct MemBlock)); + + memtop->chain = newblock; /* attach this BLOCK to the chain */ + newblock->next = block; /* point to the previous first BLOCK */ + if(block) + block->prev = newblock; /* point back on this new BLOCK */ + newblock->prev = NULL; /* no previous */ + newblock->top = memtop; /* our head master */ + + /* point to the new first FRAGMENT */ + newblock->first = (struct MemFrag *) + ((char *)newblock+sizeof(struct MemBlock)); + + /* create FRAGMENTS of the BLOCK: */ + FragBlock((char *)newblock->first, memtop->fragsize); + +#if defined(DEBUG) && !defined(BMALLOC) + checkmem((char *)newblock); +#endif + + /* fix the nfree counters */ + newblock->nfree = memtop->nmax; + memtop->nfree += memtop->nmax; + + /* get a FRAGMENT from the BLOCK */ + mem = FragFromBlock(newblock); + } + } +#ifdef SEMAPHORE + SEMAPHORERETURN(memtop->semaphore_id); /* let it go */ +#endif + } while(NULL == mem); /* if we should retry a larger FRAGMENT */ + } + else { + /* get a stand-alone BLOCK */ + struct MemInfo *meminfo; + + if(size&1) + /* don't leave this with an odd size since we'll use that bit for + information */ + size++; + + DMEM_OSALLOCMEM(size, meminfo, struct MemInfo *); + + if(meminfo) { + MEMINCR(meminfo, size); + meminfo->block = (void *)(size|BLOCK_BIT); + mem = (char *)meminfo + sizeof(struct MemInfo); + } + else { + dmalloc_failed(size); + mem = NULL; + } + } + return (void *)mem; +} + +/*************************************************************************** + * + * dfree() + * + * This needs no explanation. A free() look-alike. + * + **************************************************************************/ + +void dfree(void *memp) +{ + struct MemInfo *meminfo = (struct MemInfo *) + ((char *)memp- sizeof(struct MemInfo)); + + DBG(("dfree(%p)\n", memp)); + + if(!((size_t)meminfo->block&BLOCK_BIT)) { + /* this is a FRAGMENT we have to deal with */ + + struct MemBlock *block=meminfo->block; + struct MemTop *memtop = block->top; + +#ifdef SEMAPHORE + SEMAPHOREOBTAIN(memtop->semaphore_id); +#endif + + /* increase counters */ + block->nfree++; + memtop->nfree++; + + /* is this BLOCK completely empty now? */ + if(block->nfree == memtop->nmax) { + /* yes, return the BLOCK to the system */ + if(block->prev) + block->prev->next = block->next; + else + memtop->chain = block->next; + if(block->next) + block->next->prev = block->prev; + + memtop->nfree -= memtop->nmax; /* total counter subtraction */ + MEMDECR(block, DMEM_BLOCKSIZE + sizeof(struct MemBlock)); + DMEM_OSFREEMEM((void *)block); /* return the whole block */ + } + else { + /* there are still used FRAGMENTS in the BLOCK, link this one + into the chain of free ones */ + struct MemFrag *frag = (struct MemFrag *)meminfo; + frag->prev = NULL; + frag->next = block->first; + if(block->first) + block->first->prev = frag; + block->first = frag; + } +#ifdef SEMAPHORE + SEMAPHORERETURN(memtop->semaphore_id); +#endif + } + else { + /* big stand-alone block, just give it back to the OS: */ + MEMDECR(&meminfo->block, (size_t)meminfo->block&~BLOCK_BIT); /* clean BLOCK_BIT */ + DMEM_OSFREEMEM((void *)meminfo); + } +} + +/*************************************************************************** + * + * drealloc() + * + * This needs no explanation. A realloc() look-alike. + * + **************************************************************************/ + +void *drealloc(void *ptr, size_t size) +{ + struct MemInfo *meminfo = (struct MemInfo *) + ((char *)ptr- sizeof(struct MemInfo)); + /* + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * NOTE: the ->size field of the meminfo will now contain the MemInfo + * struct size too! + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + */ + void *mem=NULL; /* SAFE */ + size_t prevsize; + + /* NOTE that this is only valid if BLOCK_BIT isn't set: */ + struct MemBlock *block; + + DBG(("drealloc(%p, %d)\n", ptr, size)); + + if(NULL == ptr) + return dmalloc( size ); + + block = meminfo->block; + + if(!((size_t)meminfo->block&BLOCK_BIT) && + (size + sizeof(struct MemInfo) < + (prevsize = block->top->fragsize) )) { + /* This is a FRAGMENT and new size is possible to retain within the same + FRAGMENT */ + if((prevsize > qinfo[0]) && + /* this is not the smallest memory Q */ + (size < (unsigned)(block->top-1)->fragsize)) + /* this fits in a smaller Q */ + ; + else + mem = ptr; /* Just return the same pointer as we got in. */ + } + if(!mem) { + /* This is a stand-alone BLOCK or a realloc that no longer fits within + the same FRAGMENT */ + + if((size_t)meminfo->block&BLOCK_BIT) { + prevsize = ((size_t)meminfo->block&~BLOCK_BIT) - + sizeof(struct MemInfo); + } + else + prevsize -= sizeof(struct MemInfo); + + /* No tricks involved here, just grab a new bite of memory, copy the data + * from the old place and free the old memory again. */ + mem = dmalloc(size); + if(mem) { + memcpy(mem, ptr, MIN(size, prevsize) ); + dfree(ptr); + } + } + return mem; +} + +/*************************************************************************** + * + * dcalloc() + * + * This needs no explanation. A calloc() look-alike. + * + **************************************************************************/ +/* Allocate an array of NMEMB elements each SIZE bytes long. + The entire array is initialized to zeros. */ +void * +dcalloc (size_t nmemb, size_t size) +{ + void *result = dmalloc (nmemb * size); + + if (result != NULL) + memset (result, 0, nmemb * size); + + return result; +} Property changes on: apps/codecs/lib/dmalloc.c ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/lib/bmalloc.h =================================================================== --- apps/codecs/lib/bmalloc.h (revision 0) +++ apps/codecs/lib/bmalloc.h (revision 0) @@ -0,0 +1,27 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: test_codec.c 19834 2009-01-24 03:47:09Z jethead71 $ + * + * Copyright (C) 2009 Daniel Stenberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +int add_pool(void *start, size_t size); +void print_lists(); + +void *bmalloc(size_t size); +void bfree(void *ptr); + Property changes on: apps/codecs/lib/bmalloc.h ___________________________________________________________________ Added: svn:executable + * Index: apps/codecs/libtremor/os_types.h =================================================================== --- apps/codecs/libtremor/os_types.h (revision 19952) +++ apps/codecs/libtremor/os_types.h (working copy) @@ -24,7 +24,7 @@ #ifdef _LOW_ACCURACY_ # define X(n) (((((n)>>22)+1)>>1) - ((((n)>>22)+1)>>9)) -# define LOOKUP_T const unsigned char +# define LOOKUP_T const unsigned char #else # define X(n) (n) # define LOOKUP_T const ogg_int32_t @@ -33,23 +33,20 @@ /* make it easy on the folks that want to compile the libs with a different malloc than stdlib */ -#define _ogg_malloc ogg_malloc -#define _ogg_calloc ogg_calloc -#define _ogg_realloc ogg_realloc -#define _ogg_free(x) do { } while(0) +#define _ogg_malloc dmalloc +#define _ogg_calloc dcalloc +#define _ogg_realloc drealloc +#define _ogg_free dfree +#define ogg_tmpmalloc dmalloc +#define ogg_tmpcalloc dcalloc +#define ogg_tmpmalloc_free dfree + void ogg_malloc_init(void); -void *ogg_malloc(size_t size); -void *ogg_tmpmalloc(size_t size); -void *ogg_calloc(size_t nmemb, size_t size); -void *ogg_tmpcalloc(size_t nmemb, size_t size); -void *ogg_realloc(void *ptr, size_t size); -long ogg_tmpmalloc_pos(void); -void ogg_tmpmalloc_free(long pos); - typedef short ogg_int16_t; - typedef int ogg_int32_t; - typedef unsigned int ogg_uint32_t; - typedef long long ogg_int64_t; +typedef short ogg_int16_t; +typedef int ogg_int32_t; +typedef unsigned int ogg_uint32_t; +typedef long long ogg_int64_t; #endif /* _OS_TYPES_H */ Index: apps/codecs/libtremor/oggmalloc.c =================================================================== --- apps/codecs/libtremor/oggmalloc.c (revision 19952) +++ apps/codecs/libtremor/oggmalloc.c (working copy) @@ -1,74 +1,12 @@ #include "os_types.h" +#include "codeclib.h" -static size_t tmp_ptr; - void ogg_malloc_init(void) { + mallocbuf = ci->codec_get_buffer(&bufsize); - tmp_ptr = bufsize & ~3; - mem_ptr = 0; -} -void *ogg_malloc(size_t size) -{ - void* x; + /*init dbestfit malloc here*/ + add_pool(mallocbuf, bufsize); - size = (size + 3) & ~3; - - if (mem_ptr + size > tmp_ptr) - return NULL; - - x = &mallocbuf[mem_ptr]; - mem_ptr += size; /* Keep memory 32-bit aligned */ - - return x; } - -void *ogg_tmpmalloc(size_t size) -{ - size = (size + 3) & ~3; - - if (mem_ptr + size > tmp_ptr) - return NULL; - - tmp_ptr -= size; - return &mallocbuf[tmp_ptr]; -} - -void *ogg_calloc(size_t nmemb, size_t size) -{ - void *x; - x = ogg_malloc(nmemb * size); - if (x == NULL) - return NULL; - ci->memset(x, 0, nmemb * size); - return x; -} - -void *ogg_tmpcalloc(size_t nmemb, size_t size) -{ - void *x; - x = ogg_tmpmalloc(nmemb * size); - if (x == NULL) - return NULL; - ci->memset(x, 0, nmemb * size); - return x; -} - -void *ogg_realloc(void *ptr, size_t size) -{ - void *x; - (void)ptr; - x = ogg_malloc(size); - return x; -} - -long ogg_tmpmalloc_pos(void) -{ - return tmp_ptr; -} - -void ogg_tmpmalloc_free(long pos) -{ - tmp_ptr = pos; -} Index: apps/codecs/libtremor/sharedbook.c =================================================================== --- apps/codecs/libtremor/sharedbook.c (revision 19952) +++ apps/codecs/libtremor/sharedbook.c (working copy) @@ -325,7 +325,6 @@ int vorbis_book_init_decode(codebook *c,const static_codebook *s){ int i,j,n=0,tabn; int *sortindex; - long pos = ogg_tmpmalloc_pos(); memset(c,0,sizeof(*c)); /* count actually used entries */ @@ -433,11 +432,8 @@ } } } - - ogg_tmpmalloc_free(pos); return(0); err_out: - ogg_tmpmalloc_free(pos); vorbis_book_clear(c); return(-1); }