summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/malloc/Makefile40
-rw-r--r--firmware/malloc/README21
-rw-r--r--firmware/malloc/THOUGHTS170
-rw-r--r--firmware/malloc/bmalloc.c386
-rw-r--r--firmware/malloc/bmalloc.h30
-rw-r--r--firmware/malloc/bysize.c451
-rw-r--r--firmware/malloc/bysize.h24
-rw-r--r--firmware/malloc/dmalloc.c634
-rw-r--r--firmware/malloc/dmalloc.h36
9 files changed, 0 insertions, 1792 deletions
diff --git a/firmware/malloc/Makefile b/firmware/malloc/Makefile
deleted file mode 100644
index 4524d0630b..0000000000
--- a/firmware/malloc/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-# __________ __ ___.
-# Open \______ \ ____ ____ | | _\_ |__ _______ ___
-# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
-# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
-# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
-# \/ \/ \/ \/ \/
-# $Id$
-#
-# Copyright (C) 2002 by Daniel Stenberg
-#
-# All files in this archive are subject to the GNU General Public License.
-# See the file COPYING in the source tree root for full license agreement.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-
-TARGET = libdmalloc.a
-
-LIBOBJS = dmalloc.o bmalloc.o bysize.o
-
-# define this to talk a lot in runtime
-# -DDEBUG_VERBOSE
-CFLAGS = -g -W -Wall -DDEBUG_MALLOC
-CC = gcc
-AR = ar
-
-LDFLAGS = -L. -ldmalloc
-
-all: $(TARGET)
-
-clean:
- rm -f core *~ $(TARGET) $(LIBOBJS)
-
-$(TARGET): $(LIBOBJS)
- $(AR) ruv $(TARGET) $(LIBOBJS)
-
-bmalloc.o: bmalloc.c bysize.h
-bysize.o: bysize.c
-dmalloc.o: dmalloc.c
diff --git a/firmware/malloc/README b/firmware/malloc/README
deleted file mode 100644
index 336bd571ae..0000000000
--- a/firmware/malloc/README
+++ /dev/null
@@ -1,21 +0,0 @@
-Package: dbestfit - a dynamic best-fit memory allocator
-Date: 1996 - 2002
-Version: 3.3
-Author: Daniel Stenberg <daniel@haxx.se>
-License: MIT originally, files in the Rockbox project are GPL licensed.
-
- I wrote the dmalloc part for small allocation sizes to improve the behavior
-of the built-in (first-fit) allocator found in pSOS, during late 1996 and
-spring 1997.
-
- I wrote the bmalloc part (best-fit with optional splay-tree sorting) just for
-the fun of it and to see how good malloc() implementation I could make. The
-quality of my implementation is still left to be judged in real-world tests.
-
-TODO:
- * Remove the final not-so-very-nice loop in dmalloc.c that checks for a block
- with free fragments (when the list gets longer too much time might be spent
- in that loop).
-
- * Make a separate application that samples the memory usage of a program
- and is capable of replaying it (in order to test properly).
diff --git a/firmware/malloc/THOUGHTS b/firmware/malloc/THOUGHTS
deleted file mode 100644
index 27517361da..0000000000
--- a/firmware/malloc/THOUGHTS
+++ /dev/null
@@ -1,170 +0,0 @@
- ====================================
- Memory Allocation Algorithm Theories
- ====================================
-
-GOAL
- It is intended to be a 100% working memory allocation system. It should be
- capable of replacing an ordinary Operating System's own routines. It should
- work good in a multitasking, shared memory, non-virtual memory environment
- without clogging the memory. Primary aimed for small machines, CPUs and
- memory amounts.
-
- I use a best-fit algorithm with a slight overhead in order to increase speed
- a lot. It should remain scalable and work good with very large amount of
- memory and free/used memory blocks too.
-
-TERMINOLOGY
-
- FRAGMENT - small identically sized parts of a larger BLOCK, they are _not_
- allocated when traversed in lists etc
- BLOCK - large memory area, if used for FRAGMENTS, they are linked in a
- lists. One list for each FRAGMENT size supported.
- TOP - head struct that holds information about and points to a chain
- of BLOCKS for a particular FRAGMENT size.
- CHUNK - a contiguous area of free memory
-
-MEMORY SYSTEM
-
- We split the system in two parts. One part allocates small memory amounts
- and one part allocates large memory amounts, but all allocations are done
- "through" the small-part-system. There is an option to use only the small
- system (and thus use the OS for large blocks) or the complete package.
-
-##############################################################################
- SMALL SIZE ALLOCATIONS
-##############################################################################
-
- Keywords for this system is 'Deferred Coalescing' and 'quick lists'.
-
- ALLOC
-
- * Small allocations are "aligned" upwards to a set of preset sizes. In the
- current implementation I use 20, 28, 52, 116, 312, 580, 1016, 2032 bytes.
- Memory allocations of these sizes are referred to as FRAGMENTS.
- (The reason for these specific sizes is the requirement that they must be
- 32-bit aligned and fit as good as possible within 4064 bytes.)
-
- * Allocations larger than 2032 will get a BLOCK for that allocation only.
-
- * Each of these sizes has it's own TOP. When a FRAGMENT is requested, a
- larger BLOCK will be allocated and divided into many FRAGMENTS (all of the
- same size). TOP points to a list with BLOCKS that contains FRAGMENTS of
- the same size. Each BLOCK has a 'number of free FRAGMENTS' counter and so
- has each TOP (for the entire chain).
-
- * A BLOCK is around 4064 bytes plus the size of the information header. This
- size is adjusted to make the allocation of the big block not require more
- than 4096 bytes. (This might not be so easy to be sure of, if you don't
- know how the big-block system works, but the BMALLOC system uses an
- extra header of 12 bytes and the header for the FRAGMENT BLOCK is 20 bytes
- in a general 32-bit environment.)
-
- * In case the allocation of a BLOCK fails when a FRAGMENT is required, the
- next size of FRAGMENTS will be checked for a free FRAGMENT. First when the
- larger size lists have been tested without success it will fail for real.
-
- FREE
-
- * When FRAGMENTS are freed so that a BLOCK becomes non-used, it is returned
- to the system.
-
- * FREEing a fragment adds the buffer in a LIFO-order. That means that the
- next request for a fragment from the same list, the last freed buffer will
- be returned first.
-
- REALLOC
-
- * REALLOCATION of a FRAGMENT does first check if the new size would fit
- within the same FRAGMENT and if it would use the same FRAGMENT size. If it
- does and would, the same pointer is returned.
-
- OVERHEAD
-
- Yes, there is an overhead on small allocations (internal fragmentation).
- Yet, I do believe that small allocations more often than larger ones are
- used dynamically. I believe that a large overhead is not a big problem if it
- remains only for a while. The big gain is with the extreme speed we can GET
- and RETURN small allocations. This has yet to be proven. I am open to other
- systems of dealing with the small ones, but I don`t believe in using the
- same system for all sizes of allocations.
-
- IMPROVEMENT
-
- An addition to the above described algorithm is the `save-empty-BLOCKS-a-
- while-afterwards`. It will be used when the last used FRAGMENT within a
- BLOCK is freed. The BLOCK will then not get returned to the system until "a
- few more" FRAGMENTS have been freed in case the last [few] freed FRAGMENTS
- are allocated yet again (and thus prevent the huge overhead of making
- FRAGMENTS in a BLOCK). The "only" drawback of such a SEBAWA concept is
- that it would mean an even bigger overhead...
-
- HEADERS (in allocated data)
-
- FRAGMENTS - 32-bit pointer to its parent BLOCK (lowest bit must be 0)
- BLOCK - 32-bit size (lowest bit must be 1 to separate this from
- FRAGMENTS)
-
-##############################################################################
- LARGER ALLOCATIONS
-##############################################################################
-
- If the requested size is larger than the largest FRAGMENT size supported,
- the allocation will be made for this memory area alone, or if a BLOCK is
- allocated to fit lots of FRAGMENTS a large block is also desired.
-
- * We add memory to the "system" with the add_pool() function call. It
- specifies the start and size of the new block of memory that will be
- used in this memory allocation system. Several add_pool() calls are
- supported and they may or may not add contiguous memory.
-
- * Make all blocks get allocated aligned to BLOCKSIZE (sometimes referred to
- as 'grain size'), 64 bytes in my implementation. Reports tell us there is
- no real gain in increasing the size of the align.
-
- * We link *all* pieces of memory (AREAS), free or not free. We keep the list
- in address order and thus when a FREE() occurs we know instantly if there
- are FREE CHUNKS wall-to-wall. No list "travels" needed. Requires some
- extra space in every allocated BLOCK. Still needs to put the new CHUNK in
- the right place in size-sorted list/tree. All memory areas, allocated or
- not, contain the following header:
- - size of this memory area (31 bits)
- - FREE status (1 bit)
- - pointer to the next AREA closest in memory (32 bits)
- - pointer to the prev AREA closest in memory (32 bits)
- (Totally 12 bytes)
-
- * Sort all FREE CHUNKS in size-order. We use a SPLAY TREE algorithm for
- maximum speed. Data/structs used for the size-sorting functions are kept
- in an abstraction layer away from this since it is really not changing
- anything (except executing speed).
-
- ALLOC (RSIZE - requested size, aligned properly)
-
- * Fetch a CHUNK that RSIZE fits within. If the found CHUNK is larger than
- RSIZE, split it and return the RSIZE to the caller. Link the new CHUNK
- into the list/tree.
-
- FREE (AREA - piece of memory that is returned to the system)
-
- * Since the allocated BLOCK has kept its link-pointers, we can without
- checking any list instantly see if there are any FREE CHUNKS that are
- wall-to-wall with the AREA (both sides). If the AREA *is* wall-to-wall
- with one or two CHUNKS that or they are unlinked from the lists, enlarged
- and re-linked into the lists.
-
- REALLOC
-
- * There IS NO realloc() of large blocks, they are performed in the previous
- layer (dmalloc).
-
-
-##############################################################################
- FURTHER READING
-##############################################################################
-
- * "Dynamic Storage Allocation: A Survey and Critical Review" (Paul R. Wilson,
- Mark S. Johnstone, Michael Neely, David Boles)
- ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps
-
- * "A Memory Allocator" (Doug Lea)
- http://g.oswego.edu/dl/html/malloc.html
diff --git a/firmware/malloc/bmalloc.c b/firmware/malloc/bmalloc.c
deleted file mode 100644
index 470ee49840..0000000000
--- a/firmware/malloc/bmalloc.c
+++ /dev/null
@@ -1,386 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 by Daniel Stenberg
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * 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 <daniel@haxx.se>
- *
- * Read THOUGHTS for theories and details on implementation.
- *
- ****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "bysize.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/* #define DEBUG_MALLOC */
-
-#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 bmalloc_status(void);
-
-
-/***********************************************************************
- *
- * remove_block()
- *
- * Remove the block from the address-sorted list.
- *
- ***********************************************************************/
-
-static
-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.
- *
- ***************************************************************************/
-static
-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: */
- bmalloc_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;
- }
- 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_blocktolists() recursively and then escape */
-
- remove_block(temp); /* unlink 'temp' from list */
-
- /* remove from size-sorted list: */
- bmalloc_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 */
- }
-
- newblock->info = newsize | INFO_FREE; /* we do assume size isn't using the
- FREE bit */
- bmalloc_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;
-}
-
-/***********************************************************************
- *
- * bmalloc_add_pool()
- *
- * This function should be the absolutely first function to call. It sets up
- * the memory bounds of the [first] CHUNK(s). It is 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 non-contigous memory areas.
- *
- * Returns non-zero if an error occured. The memory was not added then.
- *
- ***********************************************************************/
-
-int bmalloc_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_VERBOSE
-static void bmalloc_failed(size_t size)
-{
- printf("*** " __FILE__ " Couldn't allocate %d bytes\n", size);
- bmalloc_status();
-}
-#else
-#define bmalloc_failed(x)
-#endif
-
-void bmalloc_status(void)
-{
-#ifdef DEBUG_MALLOC
- struct BlockInfo *block = blockHead;
- long mem_free = 0;
- long mem_used = 0;
-
- printf("List of BLOCKS (in address order):\n");
- while(block) {
- printf(" START %p END %p SIZE %ld FLAG %s\n",
- block,
- (char *)block+(block->info&INFO_SIZE),
- block->info&INFO_SIZE,
- (block->info&INFO_FREE)?"free":"used");
- if(block->info&INFO_FREE)
- mem_free += block->info&INFO_SIZE;
- else
- mem_used += block->info&INFO_SIZE;
- block = block->higher;
- }
- printf(" Used mem: %ld , free mem: %ld (total %ld)\n",
- mem_used, mem_free, mem_used + mem_free);
- bmalloc_print_sizes();
-#endif
-}
-
-
-void *bmalloc(size_t size)
-{
- void *mem;
-
-#ifdef DEBUG_VERBOSE
- {
- 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 = bmalloc_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->lower,
- (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 */
- }
-
-#ifdef DEBUG_VERBOSE
- bmalloc_status();
-#endif
- return mem;
-}
-
-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_VERBOSE
- 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: */
- bmalloc_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: */
- bmalloc_remove_chunksize(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;
-
- bmalloc_insert_bysize((char *)block+sizeof(struct BlockInfo),
- block->info&INFO_SIZE);
-
-#ifdef DEBUG_VERBOSE
- bmalloc_status();
-#endif
-
-}
-
diff --git a/firmware/malloc/bmalloc.h b/firmware/malloc/bmalloc.h
deleted file mode 100644
index 4bb89b9adb..0000000000
--- a/firmware/malloc/bmalloc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 by Daniel Stenberg
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-#ifndef _BMALLOC_H_
-#define _BMALLOC_H_
-
-#include <stdlib.h>
-
-int bmalloc_add_pool(void *start, size_t size);
-void bmalloc_status(void);
-
-void *bmalloc(size_t size);
-void bfree(void *ptr);
-
-#endif
diff --git a/firmware/malloc/bysize.c b/firmware/malloc/bysize.c
deleted file mode 100644
index 437159579c..0000000000
--- a/firmware/malloc/bysize.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 by Daniel Stenberg
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * 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@haxx.se
- *
- * v2.0
- * - Added SPLAY TREE functionality.
- *
- * Adds and removes CHUNKS from a list or tree.
- *
- ****************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#define SPLAY /* we use the splay version as that is much faster when the
- amount of blocks grow */
-
-#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 bmalloc_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 bmalloc_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 *bmalloc_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) {
- bmalloc_remove_chunksize( chunk ); /* unlink size-wise */
- return (char *)chunk;
- }
- else
- return NULL;
-}
-
-void bmalloc_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.
- */
-static
-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. */
-static
-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. */
-static
-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. */
-static
-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;
-}
-
-#ifdef DEBUG_MALLOC
-static
-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; i<d; i++)
- if(output)
- printf(" ");
-
- if(output) {
- printf("%d[%d]", t->key, 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 bmalloc_remove_chunksize(void *data)
-{
- chunkHead = removebyaddr(chunkHead, data);
-}
-
-void bmalloc_insert_bysize(char *data, size_t size)
-{
- chunkHead = insert(size, chunkHead, (Tree *)data);
-}
-
-char *bmalloc_obtainbysize( size_t size)
-{
- Tree *receive;
- chunkHead = removebestfit(size, chunkHead, &receive);
- return (char *)receive;
-}
-
-#ifdef DEBUG_MALLOC
-void bmalloc_print_sizes(void)
-{
- printtree(chunkHead, 0, 1);
-}
-#endif
-
-#endif
diff --git a/firmware/malloc/bysize.h b/firmware/malloc/bysize.h
deleted file mode 100644
index 34be8f9021..0000000000
--- a/firmware/malloc/bysize.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 by Daniel Stenberg
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-void bmalloc_remove_chunksize(void *data);
-void bmalloc_insert_bysize(char *data, size_t size);
-char *bmalloc_obtainbysize( size_t size);
-#ifdef DEBUG_MALLOC
-void bmalloc_print_sizes(void);
-#endif
diff --git a/firmware/malloc/dmalloc.c b/firmware/malloc/dmalloc.c
deleted file mode 100644
index 7f1690b221..0000000000
--- a/firmware/malloc/dmalloc.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 by Daniel Stenberg
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-/*****************************************************************************
- *
- * Dynamic small-blocks Memory Allocation
- *
- * Author: Daniel Stenberg <daniel@haxx.se>
- *
- * Read THOUGHTS for theories and details on the implementation.
- *
- *****************************************************************************/
-
-#include <stdio.h>
-#include <string.h> /* memcpy */
-
-#ifdef DEBUG_MALLOC
-#include <stdarg.h>
-#endif
-
-#ifdef PSOS
-#include <psos.h>
-#define SEMAPHORE /* the PSOS routines use semaphore protection */
-#else
-
-#endif
-
-#define BMALLOC /* we use our own big-malloc system */
-
-#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_VERBOSE
-#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_MALLOC
-#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: <id> */
-#define SEMAPHOREOBTAIN(x) sm_p(x, SM_WAIT, 0)
-/* Argument: <id> */
-#define SEMAPHORERETURN(x) sm_v(x)
-/* Argument: <name> <id-variable name> */
-#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 DEBUG_MALLOC
-#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+=4) { a=4064/i; if(a*i >= 4060) { {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.
- */
-
-static const unsigned short qinfo[]= {
- 20, 28, 52, 116, 312, 580, 1016, 2032
-};
-
-#define MIN(x,y) ((x)<(y)?(x):(y))
-
-/* ---------------------------------------------------------------------- */
-/* Globals */
-/* ---------------------------------------------------------------------- */
-
-/* keeper of the chain of BLOCKS */
-static struct MemTop top[ sizeof(qinfo)/sizeof(qinfo[0]) ];
-
-/* ---------------------------------------------------------------------- */
-/* Start of the real code */
-/* ---------------------------------------------------------------------- */
-
-#ifdef DEBUG_MALLOC
-/************
- * A few functions that are verbose and tells us about the current status
- * of the dmalloc system
- ***********/
-
-void dmalloc_status(void)
-{
- unsigned int i;
- int used;
- int num;
- int totalfree=0;
- struct MemBlock *block;
- for(i=0; i<sizeof(qinfo)/sizeof(qinfo[0]);i++) {
- block = top[i].chain;
- used = 0;
- num = 0;
- while(block) {
- used += top[i].nmax-block->nfree;
- 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);
-}
-#endif
-
-#ifdef DEBUG_VERBOSE
-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_VERBOSE
-
-#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) {
- frag->next = (struct MemFrag *)((char *)frag + size);
- frag->prev = prev;
- prev = frag;
- (char *)frag += size;
- count += size;
- }
- prev->next = NULL; /* the last one has no next struct */
-}
-
-/***************************************************************************
- *
- * dmalloc_initialize();
- *
- * Call before the first dmalloc(). Inits a few memory things.
- *
- **************************************************************************/
-void dmalloc_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];
- snprintf(name, 7, "MEM%d", i);
- SEMAPHORECREATE(name, top[i].semaphore_id);
- /* doesn't matter if it failed, we continue anyway ;-( */
- }
-#endif
- }
-}
-
-/****************************************************************************
- *
- * 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 *malloc(size_t size)
-{
- void *mem;
-
- DBG(("malloc(%d)\n", size));
-
- /* 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: CHAIN %p FREE %d MAX %d FRAGSIZE %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 */
-
- /**** We'd prefer to not have this loop 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_VERBOSE
- 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);
-
- /* 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 free(void *memp)
-{
- struct MemInfo *meminfo = (struct MemInfo *)
- ((char *)memp- sizeof(struct MemInfo));
-
- DBG(("free(%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: */
-
- /* clean BLOCK_BIT */
- MEMDECR(meminfo->block, (size_t)meminfo->block&~BLOCK_BIT);
- DMEM_OSFREEMEM((void *)meminfo);
- }
-}
-
-/***************************************************************************
- *
- * drealloc()
- *
- * This needs no explanation. A realloc() look-alike.
- *
- **************************************************************************/
-
-void *realloc(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(("realloc(%p, %d)\n", ptr, size));
-
- if(NULL == ptr)
- return malloc( size );
-
- block = meminfo->block;
-
- /* Here we check if this is a FRAGMENT and if the new size is
- still smaller than the fragsize for this block. */
- if(!((size_t)block&BLOCK_BIT) &&
- (size + sizeof(struct MemInfo) < block->top->fragsize )) {
-
- 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 < (block->top-1)->fragsize))
- /* This fits in a smaller fragment, so we will make a realloc
- here */
- ;
- else
- mem = ptr; /* Just return the same pointer as we got in. */
- }
- if(!mem) {
- if((size_t)meminfo->block&BLOCK_BIT) {
- /* This is a stand-alone BLOCK */
- prevsize = ((size_t)meminfo->block&~BLOCK_BIT) -
- sizeof(struct MemInfo);
- }
- else
- /* a FRAGMENT realloc that no longer fits within the same FRAGMENT
- * or one that fits in a smaller */
- prevsize = block->top->fragsize;
-
- /* 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 = malloc(size);
- if(mem) {
- memcpy(mem, ptr, MIN(size, prevsize) );
- free(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 *
-calloc (size_t nmemb, size_t size)
-{
- void *result = malloc (nmemb * size);
-
- if (result != NULL)
- memset (result, 0, nmemb * size);
-
- return result;
-}
diff --git a/firmware/malloc/dmalloc.h b/firmware/malloc/dmalloc.h
deleted file mode 100644
index 96772a46f5..0000000000
--- a/firmware/malloc/dmalloc.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copyright (C) 2002 by Daniel Stenberg
- *
- * All files in this archive are subject to the GNU General Public License.
- * See the file COPYING in the source tree root for full license agreement.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-#ifndef _DMALLOC_H_
-#define _DMALLOC_H_
-
-#include <stdlib.h>
-
-void *malloc(size_t);
-void *calloc (size_t nmemb, size_t size);
-void free(void *);
-void *realloc(void *, size_t);
-
-/* use this to intialize the internals of the dmalloc engine */
-void dmalloc_initialize(void);
-
-#ifdef DEBUG
-void dmalloc_status(void);
-#endif
-
-#endif