#include <common.h>
+#ifdef CONFIG_SANDBOX
+#define DEBUG
+#endif
+
#if 0 /* Moved to malloc.h */
/* ---------- To make a malloc.h, start cutting here ------------ */
MORECORE_FAILURE (default: -1)
The value returned upon failure of MORECORE.
MORECORE_CLEARS (default 1)
- True (1) if the routine mapped to MORECORE zeroes out memory (which
+ true (1) if the routine mapped to MORECORE zeroes out memory (which
holds for sbrk).
DEFAULT_TRIM_THRESHOLD
DEFAULT_TOP_PAD
*/
-\f
/* Preliminaries */
*/
-#ifdef DEBUG
-#include <assert.h>
-#else
-#define assert(x) ((void)0)
-#endif
-
-
/*
INTERNAL_SIZE_T is the word-size used for internal bookkeeping
of chunk sizes. On a 64-bit machine, you can reduce malloc
#endif
/* ---------- To make a malloc.h, end cutting here ------------ */
-#else /* Moved to malloc.h */
+#endif /* 0 */ /* Moved to malloc.h */
#include <malloc.h>
-#if 0
+#include <asm/io.h>
+
+#ifdef DEBUG
#if __STD_C
static void malloc_update_mallinfo (void);
void malloc_stats (void);
static void malloc_update_mallinfo ();
void malloc_stats();
#endif
-#endif /* 0 */
-
-#endif /* 0 */ /* Moved to malloc.h */
+#endif /* DEBUG */
DECLARE_GLOBAL_DATA_PTR;
#endif
-\f
+
/*
Type declarations
INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if free. */
struct malloc_chunk* bk;
-};
+} __attribute__((__may_alias__)) ;
typedef struct malloc_chunk* mchunkptr;
serviced via calls to mmap, and then later released via munmap.
*/
-\f
+
/* sizes, alignments */
#define SIZE_SZ (sizeof(INTERNAL_SIZE_T))
#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
-\f
+
/*
Physical chunk operations
#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s)))
-\f
+
/*
Dealing with use bits
(((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
-\f
+
/*
Dealing with size fields
#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
-\f
+
/*
#define IAV(i) bin_at(i), bin_at(i)
static mbinptr av_[NAV * 2 + 2] = {
- 0, 0,
+ NULL, NULL,
IAV(0), IAV(1), IAV(2), IAV(3), IAV(4), IAV(5), IAV(6), IAV(7),
IAV(8), IAV(9), IAV(10), IAV(11), IAV(12), IAV(13), IAV(14), IAV(15),
IAV(16), IAV(17), IAV(18), IAV(19), IAV(20), IAV(21), IAV(22), IAV(23),
IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127)
};
-void malloc_bin_reloc (void)
+#ifdef CONFIG_NEEDS_MANUAL_RELOC
+static void malloc_bin_reloc(void)
{
- unsigned long *p = (unsigned long *)(&av_[2]);
- int i;
- for (i=2; i<(sizeof(av_)/sizeof(mbinptr)); ++i) {
- *p++ += gd->reloc_off;
- }
+ mbinptr *p = &av_[2];
+ size_t i;
+
+ for (i = 2; i < ARRAY_SIZE(av_); ++i, ++p)
+ *p = (mbinptr)((ulong)*p + gd->reloc_off);
}
+#else
+static inline void malloc_bin_reloc(void) {}
+#endif
ulong mem_malloc_start = 0;
ulong mem_malloc_end = 0;
ulong old = mem_malloc_brk;
ulong new = old + increment;
+ /*
+ * if we are giving memory back make sure we clear it out since
+ * we set MORECORE_CLEARS to 1
+ */
+ if (increment < 0)
+ memset((void *)new, 0, -increment);
+
if ((new < mem_malloc_start) || (new > mem_malloc_end))
- return NULL;
+ return (void *)MORECORE_FAILURE;
mem_malloc_brk = new;
return (void *)old;
}
-#ifndef CONFIG_X86
-/*
- * x86 boards use a slightly different init sequence thus they implement
- * their own version of mem_malloc_init()
- */
void mem_malloc_init(ulong start, ulong size)
{
mem_malloc_start = start;
mem_malloc_end = start + size;
mem_malloc_brk = start;
+ debug("using memory %#lx-%#lx for malloc()\n", mem_malloc_start,
+ mem_malloc_end);
+
memset((void *)mem_malloc_start, 0, size);
+
+ malloc_bin_reloc();
}
-#endif
/* field-extraction macros */
#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH)
-\f
+
/*
To help compensate for the large number of bins, a one-level index
#define clear_binblock(ii) (binblocks_w = (mbinptr)(binblocks_r & ~(idx2binblock(ii))))
-\f
+
/* Other static bookkeeping data */
/* Tracking mmaps */
-#if 0
+#ifdef DEBUG
static unsigned int n_mmaps = 0;
-#endif /* 0 */
+#endif /* DEBUG */
static unsigned long mmapped_mem = 0;
#if HAVE_MMAP
static unsigned int max_n_mmaps = 0;
static unsigned long max_mmapped_mem = 0;
#endif
-\f
+
/*
Debugging support
static void do_check_chunk(p) mchunkptr p;
#endif
{
-#if 0 /* causes warnings because assert() is off */
INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
-#endif /* 0 */
/* No checkable chunk is mmapped */
assert(!chunk_is_mmapped(p));
#endif
{
INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
-#if 0 /* causes warnings because assert() is off */
mchunkptr next = chunk_at_offset(p, sz);
-#endif /* 0 */
do_check_chunk(p);
static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
#endif
{
-#if 0 /* causes warnings because assert() is off */
INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
long room = sz - s;
-#endif /* 0 */
do_check_inuse_chunk(p);
#define check_malloced_chunk(P,N)
#endif
-\f
+
/*
Macro-based internal utilities
(last_remainder->fd = last_remainder->bk = last_remainder)
-\f
+
/* Routines dealing with mmap(). */
#endif /* HAVE_MMAP */
-\f
+
/*
Extend the top-most chunk by obtaining memory from system.
}
-\f
+
/* Main public routines */
INTERNAL_SIZE_T nb;
- if ((long)bytes < 0) return 0;
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+ if (gd && !(gd->flags & GD_FLG_FULL_MALLOC_INIT))
+ return malloc_simple(bytes);
+#endif
+
+ /* check if mem_malloc_init() was run */
+ if ((mem_malloc_start == 0) && (mem_malloc_end == 0)) {
+ /* not initialized yet */
+ return NULL;
+ }
+
+ if ((long)bytes < 0) return NULL;
nb = request2size(bytes); /* padded request size; */
/* Try to extend */
malloc_extend_top(nb);
if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
- return 0; /* propagate failure */
+ return NULL; /* propagate failure */
}
victim = top;
}
-\f
+
/*
mchunkptr fwd; /* misc temp for linking */
int islr; /* track whether merging with last_remainder */
- if (mem == 0) /* free(0) has no effect */
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+ /* free() is a no-op - all the memory will be freed on relocation */
+ if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT))
+ return;
+#endif
+
+ if (mem == NULL) /* free(0) has no effect */
return;
p = mem2chunk(mem);
}
-\f
+
/*
if (bytes == 0) { fREe(oldmem); return 0; }
#endif
- if ((long)bytes < 0) return 0;
+ if ((long)bytes < 0) return NULL;
/* realloc of null is supposed to be same as malloc */
- if (oldmem == 0) return mALLOc(bytes);
+ if (oldmem == NULL) return mALLOc(bytes);
+
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+ if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
+ /* This is harder to support and should not be needed */
+ panic("pre-reloc realloc() is not supported");
+ }
+#endif
newp = oldp = mem2chunk(oldmem);
newsize = oldsize = chunksize(oldp);
}
else
{
- next = 0;
+ next = NULL;
nextsize = 0;
}
/* try forward + backward first to save a later consolidation */
- if (next != 0)
+ if (next != NULL)
{
/* into top */
if (next == top)
}
/* backward only */
- if (prev != 0 && (long)(prevsize + newsize) >= (long)nb)
+ if (prev != NULL && (long)(prevsize + newsize) >= (long)nb)
{
unlink(prev, bck, fwd);
newp = prev;
newmem = mALLOc (bytes);
- if (newmem == 0) /* propagate failure */
- return 0;
+ if (newmem == NULL) /* propagate failure */
+ return NULL;
/* Avoid copy if newp is next chunk after oldp. */
/* (This can only happen when new chunk is sbrk'ed.) */
}
-\f
+
/*
mchunkptr remainder; /* spare room at end to split off */
long remainder_size; /* its size */
- if ((long)bytes < 0) return 0;
+ if ((long)bytes < 0) return NULL;
/* If need less alignment than we give anyway, just relay to malloc */
nb = request2size(bytes);
m = (char*)(mALLOc(nb + alignment + MINSIZE));
- if (m == 0) return 0; /* propagate failure */
+ if (m == NULL) return NULL; /* propagate failure */
p = mem2chunk(m);
}
-\f
+
/*
#endif
Void_t* mem = mALLOc (sz);
- if ((long)n < 0) return 0;
+ if ((long)n < 0) return NULL;
- if (mem == 0)
- return 0;
+ if (mem == NULL)
+ return NULL;
else
{
+#ifdef CONFIG_SYS_MALLOC_F_LEN
+ if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) {
+ MALLOC_ZERO(mem, sz);
+ return mem;
+ }
+#endif
p = mem2chunk(mem);
/* Two optional cases in which clearing not necessary */
}
#endif
-\f
+
/*
}
}
-\f
+
/*
malloc_usable_size:
#endif
{
mchunkptr p;
- if (mem == 0)
+ if (mem == NULL)
return 0;
else
{
}
-\f
+
/* Utility to update current_mallinfo for malloc_stats and mallinfo() */
-#if 0
+#ifdef DEBUG
static void malloc_update_mallinfo()
{
int i;
current_mallinfo.keepcost = chunksize(top);
}
-#endif /* 0 */
+#endif /* DEBUG */
+
-\f
/*
*/
-#if 0
+#ifdef DEBUG
void malloc_stats()
{
malloc_update_mallinfo();
(unsigned int)max_n_mmaps);
#endif
}
-#endif /* 0 */
+#endif /* DEBUG */
/*
mallinfo returns a copy of updated current mallinfo.
*/
-#if 0
+#ifdef DEBUG
struct mallinfo mALLINFo()
{
malloc_update_mallinfo();
return current_mallinfo;
}
-#endif /* 0 */
+#endif /* DEBUG */
+
-\f
/*
mallopt: