aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/machine/xstormy16/tiny-malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'newlib/libc/machine/xstormy16/tiny-malloc.c')
-rw-r--r--newlib/libc/machine/xstormy16/tiny-malloc.c598
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