diff options
Diffstat (limited to 'newlib/libc/machine/xstormy16/tiny-malloc.c')
-rw-r--r-- | newlib/libc/machine/xstormy16/tiny-malloc.c | 598 |
1 files changed, 0 insertions, 598 deletions
diff --git a/newlib/libc/machine/xstormy16/tiny-malloc.c b/newlib/libc/machine/xstormy16/tiny-malloc.c deleted file mode 100644 index 597e389..0000000 --- a/newlib/libc/machine/xstormy16/tiny-malloc.c +++ /dev/null @@ -1,598 +0,0 @@ -/* A replacement malloc with: - - Much reduced code size; - - Smaller RAM footprint; - - The ability to handle downward-growing heaps; - but - - Slower; - - Probably higher memory fragmentation; - - Doesn't support threads (but, if it did support threads, - it wouldn't need a global lock, only a compare-and-swap instruction); - - Assumes the maximum alignment required is the alignment of a pointer; - - Assumes that memory is already there and doesn't need to be allocated. - -* Synopsis of public routines - - malloc(size_t n); - Return a pointer to a newly allocated chunk of at least n bytes, or null - if no space is available. - free(void* p); - Release the chunk of memory pointed to by p, or no effect if p is null. - realloc(void* p, size_t n); - Return a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes, or null - if no space is available. The returned pointer may or may not be - the same as p. If p is null, equivalent to malloc. Unless the - #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a - size argument of zero (re)allocates a minimum-sized chunk. - memalign(size_t alignment, size_t n); - Return a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument, which must be a power of - two. Will fail if 'alignment' is too large. - calloc(size_t unit, size_t quantity); - Returns a pointer to quantity * unit bytes, with all locations - set to zero. - cfree(void* p); - Equivalent to free(p). - malloc_trim(size_t pad); - Release all but pad bytes of freed top-most memory back - to the system. Return 1 if successful, else 0. - malloc_usable_size(void* p); - Report the number usable allocated bytes associated with allocated - chunk p. This may or may not report more bytes than were requested, - due to alignment and minimum size constraints. - malloc_stats(); - Prints brief summary statistics on stderr. - mallinfo() - Returns (by copy) a struct containing various summary statistics. - mallopt(int parameter_number, int parameter_value) - Changes one of the tunable parameters described below. Returns - 1 if successful in changing the parameter, else 0. Actually, returns 0 - always, as no parameter can be changed. -*/ - -#ifdef __xstormy16__ -#define MALLOC_DIRECTION -1 -#endif - -#ifndef MALLOC_DIRECTION -#define MALLOC_DIRECTION 1 -#endif - -#include <stddef.h> - -void* malloc(size_t); -void free(void*); -void* realloc(void*, size_t); -void* memalign(size_t, size_t); -void* valloc(size_t); -void* pvalloc(size_t); -void* calloc(size_t, size_t); -void cfree(void*); -int malloc_trim(size_t); -size_t malloc_usable_size(void*); -void malloc_stats(void); -int mallopt(int, int); -struct mallinfo mallinfo(void); - -typedef struct freelist_entry { - size_t size; - struct freelist_entry *next; -} *fle; - -extern void * __malloc_end; -extern fle __malloc_freelist; - -/* Return the number of bytes that need to be added to X to make it - aligned to an ALIGN boundary. ALIGN must be a power of 2. */ -#define M_ALIGN(x, align) (-(size_t)(x) & ((align) - 1)) - -/* Return the number of bytes that need to be subtracted from X to make it - aligned to an ALIGN boundary. ALIGN must be a power of 2. */ -#define M_ALIGN_SUB(x, align) ((size_t)(x) & ((align) - 1)) - -extern void __malloc_start; - -/* This is the minimum gap allowed between __malloc_end and the top of - the stack. This is only checked for when __malloc_end is - decreased; if instead the stack grows into the heap, silent data - corruption will result. */ -#define MALLOC_MINIMUM_GAP 32 - -#ifdef __xstormy16__ -register void * stack_pointer asm ("r15"); -#define MALLOC_LIMIT stack_pointer -#else -#define MALLOC_LIMIT __builtin_frame_address (0) -#endif - -#if MALLOC_DIRECTION < 0 -#define CAN_ALLOC_P(required) \ - (((size_t) __malloc_end - (size_t)MALLOC_LIMIT \ - - MALLOC_MINIMUM_GAP) >= (required)) -#else -#define CAN_ALLOC_P(required) \ - (((size_t)MALLOC_LIMIT - (size_t) __malloc_end \ - - MALLOC_MINIMUM_GAP) >= (required)) -#endif - -/* real_size is the size we actually have to allocate, allowing for - overhead and alignment. */ -#define REAL_SIZE(sz) \ - ((sz) < sizeof (struct freelist_entry) - sizeof (size_t) \ - ? sizeof (struct freelist_entry) \ - : sz + sizeof (size_t) + M_ALIGN(sz, sizeof (size_t))) - -#ifdef DEFINE_MALLOC - -void * __malloc_end = &__malloc_start; -fle __malloc_freelist; - -void * -malloc (size_t sz) -{ - fle *nextfree; - fle block; - - /* real_size is the size we actually have to allocate, allowing for - overhead and alignment. */ - size_t real_size = REAL_SIZE (sz); - - /* Look for the first block on the freelist that is large enough. */ - for (nextfree = &__malloc_freelist; - *nextfree; - nextfree = &(*nextfree)->next) - { - block = *nextfree; - - if (block->size >= real_size) - { - /* If the block found is just the right size, remove it from - the free list. Otherwise, split it. */ - if (block->size < real_size + sizeof (struct freelist_entry)) - { - *nextfree = block->next; - return (void *)&block->next; - } - else - { - size_t newsize = block->size - real_size; - fle newnext = block->next; - *nextfree = (fle)((size_t)block + real_size); - (*nextfree)->size = newsize; - (*nextfree)->next = newnext; - goto done; - } - } - - /* If this is the last block on the freelist, and it was too small, - enlarge it. */ - if (! block->next - && __malloc_end == (void *)((size_t)block + block->size)) - { - size_t moresize = real_size - block->size; - if (! CAN_ALLOC_P (moresize)) - return NULL; - - *nextfree = NULL; - if (MALLOC_DIRECTION < 0) - { - block = __malloc_end = (void *)((size_t)block - moresize); - } - else - { - __malloc_end = (void *)((size_t)block + real_size); - } - - goto done; - } - } - - /* No free space at the end of the free list. Allocate new space - and use that. */ - - if (! CAN_ALLOC_P (real_size)) - return NULL; - - if (MALLOC_DIRECTION > 0) - { - block = __malloc_end; - __malloc_end = (void *)((size_t)__malloc_end + real_size); - } - else - { - block = __malloc_end = (void *)((size_t)__malloc_end - real_size); - } - done: - block->size = real_size; - return (void *)&block->next; -} - -#endif - -#ifdef DEFINE_FREE - -void -free (void *block_p) -{ - fle *nextfree; - fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next)); - - if (block_p == NULL) - return; - - /* Look on the freelist to see if there's a free block just before - or just after this block. */ - for (nextfree = &__malloc_freelist; - *nextfree; - nextfree = &(*nextfree)->next) - { - fle thisblock = *nextfree; - if ((size_t)thisblock + thisblock->size == (size_t) block) - { - thisblock->size += block->size; - if (MALLOC_DIRECTION > 0 - && thisblock->next - && (size_t) block + block->size == (size_t) thisblock->next) - { - thisblock->size += thisblock->next->size; - thisblock->next = thisblock->next->next; - } - return; - } - else if ((size_t) thisblock == (size_t) block + block->size) - { - if (MALLOC_DIRECTION < 0 - && thisblock->next - && (size_t) block == ((size_t) thisblock->next - + thisblock->next->size)) - { - *nextfree = thisblock->next; - thisblock->next->size += block->size + thisblock->size; - } - else - { - block->size += thisblock->size; - block->next = thisblock->next; - *nextfree = block; - } - return; - } - else if ((MALLOC_DIRECTION > 0 - && (size_t) thisblock > (size_t) block) - || (MALLOC_DIRECTION < 0 - && (size_t) thisblock < (size_t) block)) - break; - } - - block->next = *nextfree; - *nextfree = block; - return; -} -#endif - -#ifdef DEFINE_REALLOC -void * -realloc (void *block_p, size_t sz) -{ - fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next)); - size_t real_size = REAL_SIZE (sz); - size_t old_real_size; - - if (block_p == NULL) - return malloc (sz); - - old_real_size = block->size; - - /* Perhaps we need to allocate more space. */ - if (old_real_size < real_size) - { - void *result; - size_t old_size = old_real_size - sizeof (size_t); - - /* Need to allocate, copy, and free. */ - result = malloc (sz); - if (result == NULL) - return NULL; - memcpy (result, block_p, old_size < sz ? old_size : sz); - free (block_p); - return result; - } - /* Perhaps we can free some space. */ - if (old_real_size - real_size >= sizeof (struct freelist_entry)) - { - fle newblock = (fle)((size_t)block + real_size); - block->size = real_size; - newblock->size = old_real_size - real_size; - free (&newblock->next); - } - return block_p; -} -#endif - -#ifdef DEFINE_CALLOC -void * -calloc (size_t n, size_t elem_size) -{ - void *result; - size_t sz = n * elem_size; - result = malloc (sz); - if (result != NULL) - memset (result, 0, sz); - return result; -} -#endif - -#ifdef DEFINE_CFREE -void -cfree (void *p) -{ - free (p); -} -#endif - -#ifdef DEFINE_MEMALIGN -void * -memalign (size_t align, size_t sz) -{ - fle *nextfree; - fle block; - - /* real_size is the size we actually have to allocate, allowing for - overhead and alignment. */ - size_t real_size = REAL_SIZE (sz); - - /* Some sanity checking on 'align'. */ - if ((align & (align - 1)) != 0 - || align <= 0) - return NULL; - - /* Look for the first block on the freelist that is large enough. */ - /* One tricky part is this: We want the result to be a valid pointer - to free. That means that there has to be room for a size_t - before the block. If there's additional space before the block, - it should go on the freelist, or it'll be lost---we could add it - to the size of the block before it in memory, but finding the - previous block is expensive. */ - for (nextfree = &__malloc_freelist; - ; - nextfree = &(*nextfree)->next) - { - size_t before_size; - size_t old_size; - - /* If we've run out of free blocks, allocate more space. */ - if (! *nextfree) - { - old_size = real_size; - if (MALLOC_DIRECTION < 0) - { - old_size += M_ALIGN_SUB (((size_t)__malloc_end - - old_size + sizeof (size_t)), - align); - if (! CAN_ALLOC_P (old_size)) - return NULL; - block = __malloc_end = (void *)((size_t)__malloc_end - old_size); - } - else - { - block = __malloc_end; - old_size += M_ALIGN ((size_t)__malloc_end + sizeof (size_t), - align); - if (! CAN_ALLOC_P (old_size)) - return NULL; - __malloc_end = (void *)((size_t)__malloc_end + old_size); - } - *nextfree = block; - block->size = old_size; - block->next = NULL; - } - else - { - block = *nextfree; - old_size = block->size; - } - - - before_size = M_ALIGN (&block->next, align); - if (before_size != 0) - before_size = sizeof (*block) + M_ALIGN (&(block+1)->next, align); - - /* If this is the last block on the freelist, and it is too small, - enlarge it. */ - if (! block->next - && old_size < real_size + before_size - && __malloc_end == (void *)((size_t)block + block->size)) - { - if (MALLOC_DIRECTION < 0) - { - size_t moresize = real_size - block->size; - moresize += M_ALIGN_SUB ((size_t)&block->next - moresize, align); - if (! CAN_ALLOC_P (moresize)) - return NULL; - block = __malloc_end = (void *)((size_t)block - moresize); - block->next = NULL; - block->size = old_size = old_size + moresize; - before_size = 0; - } - else - { - if (! CAN_ALLOC_P (before_size + real_size - block->size)) - return NULL; - __malloc_end = (void *)((size_t)block + before_size + real_size); - block->size = old_size = before_size + real_size; - } - - /* Two out of the four cases below will now be possible; which - two depends on MALLOC_DIRECTION. */ - } - - if (old_size >= real_size + before_size) - { - /* This block will do. If there needs to be space before it, - split the block. */ - if (before_size != 0) - { - fle old_block = block; - - old_block->size = before_size; - block = (fle)((size_t)block + before_size); - - /* If there's no space after the block, we're now nearly - done; just make a note of the size required. - Otherwise, we need to create a new free space block. */ - if (old_size - before_size - <= real_size + sizeof (struct freelist_entry)) - { - block->size = old_size - before_size; - return (void *)&block->next; - } - else - { - fle new_block; - new_block = (fle)((size_t)block + real_size); - new_block->size = old_size - before_size - real_size; - if (MALLOC_DIRECTION > 0) - { - new_block->next = old_block->next; - old_block->next = new_block; - } - else - { - new_block->next = old_block; - *nextfree = new_block; - } - goto done; - } - } - else - { - /* If the block found is just the right size, remove it from - the free list. Otherwise, split it. */ - if (old_size <= real_size + sizeof (struct freelist_entry)) - { - *nextfree = block->next; - return (void *)&block->next; - } - else - { - size_t newsize = old_size - real_size; - fle newnext = block->next; - *nextfree = (fle)((size_t)block + real_size); - (*nextfree)->size = newsize; - (*nextfree)->next = newnext; - goto done; - } - } - } - } - - done: - block->size = real_size; - return (void *)&block->next; -} -#endif - -#ifdef DEFINE_VALLOC -void * -valloc (size_t sz) -{ - return memalign (128, sz); -} -#endif -#ifdef DEFINE_PVALLOC -void * -pvalloc (size_t sz) -{ - return memalign (128, sz + M_ALIGN (sz, 128)); -} -#endif - -#ifdef DEFINE_MALLINFO -#include "malloc.h" - -struct mallinfo -mallinfo (void) -{ - struct mallinfo r; - fle fr; - size_t free_size; - size_t total_size; - size_t free_blocks; - - memset (&r, 0, sizeof (r)); - - free_size = 0; - free_blocks = 0; - for (fr = __malloc_freelist; fr; fr = fr->next) - { - free_size += fr->size; - free_blocks++; - if (! fr->next) - { - int atend; - if (MALLOC_DIRECTION > 0) - atend = (void *)((size_t)fr + fr->size) == __malloc_end; - else - atend = (void *)fr == __malloc_end; - if (atend) - r.keepcost = fr->size; - } - } - - if (MALLOC_DIRECTION > 0) - total_size = (char *)__malloc_end - (char *)&__malloc_start; - else - total_size = (char *)&__malloc_start - (char *)__malloc_end; - -#ifdef DEBUG - /* Fixme: should walk through all the in-use blocks and see if - they're valid. */ -#endif - - r.arena = total_size; - r.fordblks = free_size; - r.uordblks = total_size - free_size; - r.ordblks = free_blocks; - return r; -} -#endif - -#ifdef DEFINE_MALLOC_STATS -#include "malloc.h" -#include <stdio.h> - -void -malloc_stats(void) -{ - struct mallinfo i; - FILE *fp; - - fp = stderr; - i = mallinfo(); - fprintf (fp, "malloc has reserved %u bytes between %p and %p\n", - i.arena, &__malloc_start, __malloc_end); - fprintf (fp, "there are %u bytes free in %u chunks\n", - i.fordblks, i.ordblks); - fprintf (fp, "of which %u bytes are at the end of the reserved space\n", - i.keepcost); - fprintf (fp, "and %u bytes are in use.\n", i.uordblks); -} -#endif - -#ifdef DEFINE_MALLOC_USABLE_SIZE -size_t -malloc_usable_size (void *block_p) -{ - fle block = (fle)((size_t) block_p - offsetof (struct freelist_entry, next)); - return block->size - sizeof (size_t); -} -#endif - -#ifdef DEFINE_MALLOPT -int -mallopt (int n, int v) -{ - (void)n; (void)v; - return 0; -} -#endif |