2009-09-28 Michael Eager <eager@eagercon.com>
* configure.in: Add microblaze-*-*. * configure: Add microblaze-*-* (not regenerated.) * microblaze: NEW microblaze target directory. * microblaze/configure.in: NEW. * microblaze/configure: Generate. * microblaze/Makefile.in: NEW. * microblaze/{crt0.S, crt1.S, crt2.S, crt3.S, crt4.S, crtinit.S}: NEW. * microblaze/{pgcrtinit.S, _program_clean.S, _program_init.S, sbrk.c, sim-crtinit.S, sim-pgcrtinit.S, timer.c, _exception_handler.S, _hw_exception_handler.S, _interrupt_handler.S, xil_malloc.c, nnxil_printf.c, xil_sbrk.c: NEW. * microblaze/xilinx.ld: NEW.
This commit is contained in:
804
libgloss/microblaze/xil_malloc.c
Normal file
804
libgloss/microblaze/xil_malloc.c
Normal file
@ -0,0 +1,804 @@
|
||||
/* Copyright (c) 1995, 2002, 2009 Xilinx, Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Xilinx nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#else
|
||||
typedef unsigned int size_t;
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#define sbrk xil_sbrk
|
||||
|
||||
/* The only extern functions I need if not printing. */
|
||||
extern void* sbrk(size_t incr);
|
||||
extern void *memcpy(void *s1, const void *s2, size_t n);
|
||||
extern void *memset(void *s, int c, size_t n);
|
||||
|
||||
|
||||
typedef unsigned char BOOLEAN;
|
||||
const BOOLEAN FALSE=0;
|
||||
const BOOLEAN TRUE =1;
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#define M_DBG_NORMAL 0
|
||||
#define M_DBG_PARTIAL 1
|
||||
#define M_DBG_FULL 2
|
||||
|
||||
/* debugging breakpoint aids */
|
||||
static char xil_mem_null_free[] = "xil_mem_null_free";
|
||||
static char xil_mem_chkcnt [] = "xil_mem_chkcnt";
|
||||
|
||||
/* Flag values describing the state of a memory block.
|
||||
/* Indicator for allocated blk */
|
||||
#define M_ALLOCEDFLAG 0x5a
|
||||
/* End-of-block if debug level */
|
||||
#define M_ALLOCED 0xc99cc99c
|
||||
/* Free block indicator. */
|
||||
#define M_FREEFLAG 0xa5
|
||||
/* End-of-block if debug level */
|
||||
#define M_FREE 0x9cc99cc9
|
||||
/* Zero length block. */
|
||||
#define M_ZEROFLAG 0xaa
|
||||
|
||||
/* Header of a memory block. */
|
||||
typedef unsigned char DATA_T;
|
||||
typedef DATA_T * DATA_P;
|
||||
struct M_HEADER
|
||||
{
|
||||
unsigned dbglev:2; /* Debug level this was created with. */
|
||||
unsigned size:22; /* Size of block / 8. 32 Meg max. */
|
||||
unsigned flag:8; /* Indicates whether allocated or freed. */
|
||||
};
|
||||
typedef struct M_HEADER* M_HEADERP;
|
||||
|
||||
BOOLEAN isalloced(M_HEADERP this)
|
||||
{
|
||||
return this->flag == M_ALLOCEDFLAG;
|
||||
}
|
||||
BOOLEAN isfree(M_HEADERP this)
|
||||
{
|
||||
return this->flag == M_FREEFLAG;
|
||||
}
|
||||
BOOLEAN iszero(M_HEADERP this)
|
||||
{
|
||||
return this->flag == M_ZEROFLAG;
|
||||
}
|
||||
|
||||
void setalloced(M_HEADERP this) { this->flag = M_ALLOCEDFLAG; }
|
||||
void setfree(M_HEADERP this) { this->flag = M_FREEFLAG; }
|
||||
void setzero(M_HEADERP this) { this->flag = M_ZEROFLAG; }
|
||||
|
||||
int getdbglev(M_HEADERP this) { return this->dbglev; }
|
||||
void setdbglev(M_HEADERP this, int d) { this->dbglev = d; }
|
||||
|
||||
size_t getsize(M_HEADERP this) { return this->size << 3; } /* Alignment is 8. */
|
||||
void setsize(M_HEADERP this, size_t s){ this->size = s >> 3; }
|
||||
|
||||
DATA_T * getend(M_HEADERP this) { return (((DATA_T *)this)+getsize(this)); }
|
||||
|
||||
/* Next pointer is after data in block. */
|
||||
M_HEADERP getnext(M_HEADERP this) { return *(((M_HEADERP*)getend(this)) - 1); }
|
||||
void setnext(M_HEADERP this, M_HEADERP n) { *(((M_HEADERP*)getend(this)) - 1) = n; }
|
||||
|
||||
/* Routines used to set a flag at end of block if debuglevel != normal. */
|
||||
/* Sentinel is right BEFORE the next pointer. */
|
||||
unsigned long* getsentinel(M_HEADERP this);
|
||||
void setsentinel(M_HEADERP this, unsigned long lflag);
|
||||
BOOLEAN testsentinel(M_HEADERP this, unsigned long lflag);
|
||||
|
||||
/* Routines to handle data. Depend on debug level. */
|
||||
DATA_T * getdata(M_HEADERP this) { return (((DATA_T*)this)+sizeof(*this)); }
|
||||
size_t getdatasize(M_HEADERP this);
|
||||
|
||||
/* Fill data with a pattern. */
|
||||
void setdata(M_HEADERP this, int f);
|
||||
|
||||
/* Debug routines */
|
||||
BOOLEAN checkalloc(M_HEADERP this); /* Is this a valid allocated memory pointer? */
|
||||
BOOLEAN checkfree(M_HEADERP this); /* Is this a valid freelist entry? */
|
||||
|
||||
|
||||
|
||||
/* Get length of data. */
|
||||
size_t
|
||||
getdatasize(M_HEADERP this)
|
||||
{
|
||||
/* By default, size is size of block - size of header. */
|
||||
int tmp_size = getsize(this) - sizeof(struct M_HEADER);
|
||||
|
||||
if (this->dbglev != M_DBG_NORMAL)
|
||||
{
|
||||
/* Subtract size of sentinel, and next pointer. */
|
||||
tmp_size -= sizeof(long) + sizeof(M_HEADERP);
|
||||
/* If only eight bytes, no room for sentinel. */
|
||||
if (tmp_size < 0)
|
||||
tmp_size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free block always has a next pointer. Otherwise not. */
|
||||
if (isfree(this))
|
||||
tmp_size -= sizeof(M_HEADERP);
|
||||
}
|
||||
return tmp_size;
|
||||
}
|
||||
|
||||
/* Set the data buffer to value f. */
|
||||
void
|
||||
setdata(M_HEADERP this, int f)
|
||||
{
|
||||
memset(getdata(this), f, getdatasize(this));
|
||||
}
|
||||
|
||||
/* At the end of the block, there may be a longword with
|
||||
special meaning. This is the sentinel. If there is a sentinel,
|
||||
there is by definition a next pointer. */
|
||||
unsigned long*
|
||||
getsentinel(M_HEADERP this)
|
||||
{
|
||||
DATA_T* addr = (getend(this) - sizeof(M_HEADERP)); /* location of next pointer. */
|
||||
if (getdata(this) < addr)
|
||||
return ((unsigned long*)addr) - 1; /* Right before next pointer. */
|
||||
else
|
||||
return NULL; /* Block too small. No room for sent. */
|
||||
}
|
||||
|
||||
void
|
||||
setsentinel(M_HEADERP this, unsigned long lflag)
|
||||
{
|
||||
unsigned long* addr = getsentinel(this);
|
||||
if (addr)
|
||||
*addr = lflag;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
testsentinel(M_HEADERP this, unsigned long lflag)
|
||||
{
|
||||
unsigned long* addr = getsentinel(this);
|
||||
if (addr)
|
||||
return *addr == lflag;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* sizeof(struct M_HEADER)+sizeof(M_HEADERP); Alignment */
|
||||
#define M_BLOCKSIZE 8
|
||||
/* 4096 / 8; // M_BLOCKSIZE ; Number of freelist entries. */
|
||||
#define M_FREESIZE 512
|
||||
/* 64 * 1024; Size of incremental memory hunks allocated, */
|
||||
#define M_BRKINC 2048
|
||||
|
||||
static M_HEADERP freelist[M_FREESIZE]; /* Free list. */
|
||||
|
||||
static M_HEADERP alloclist = NULL; /* Pointer to linked list
|
||||
of Allocated blocks. */
|
||||
static int mdebuglevel = M_DBG_NORMAL;
|
||||
|
||||
static DATA_T zerobuf[M_BLOCKSIZE] = { M_ZEROFLAG, M_ZEROFLAG, M_ZEROFLAG,
|
||||
M_ZEROFLAG, M_ZEROFLAG, M_ZEROFLAG,
|
||||
M_ZEROFLAG, M_ZEROFLAG };
|
||||
static M_HEADERP zeroblock = (M_HEADERP)zerobuf;
|
||||
|
||||
static unsigned long totalallocated = 0; /* NOT actually malloced, but
|
||||
rather the size of the pool. */
|
||||
|
||||
static unsigned long totalmalloc = 0; /* Total amount malloced. */
|
||||
|
||||
static unsigned long highwater = 0; /* Largest amount of memory
|
||||
allocated at any time. */
|
||||
static long nummallocs = 0;
|
||||
static long numfrees = 0;
|
||||
static long numreallocs = 0;
|
||||
|
||||
int m_prtflag = 0;
|
||||
int m_stopaddr = 0;
|
||||
int m_stopcnt = 0;
|
||||
int m_reenter = 0;
|
||||
static int m_curcount = 0;
|
||||
|
||||
M_HEADERP
|
||||
getmemblock(size_t n)
|
||||
{
|
||||
M_HEADERP block = (M_HEADERP) sbrk(n);
|
||||
if (block != NULL)
|
||||
totalallocated += n;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
static BOOLEAN
|
||||
die (char* msg)
|
||||
{
|
||||
mdebuglevel = M_DBG_NORMAL;
|
||||
#ifdef DEBUG
|
||||
printf ("%s\n", msg);
|
||||
exit (1);
|
||||
#else
|
||||
/* Go into infinite loop. */
|
||||
for (;;)
|
||||
;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
getfreeindex(size_t size)
|
||||
{
|
||||
return MIN(size / M_BLOCKSIZE, M_FREESIZE - 1);
|
||||
}
|
||||
|
||||
static
|
||||
void coalesce(M_HEADERP h)
|
||||
{
|
||||
/* Coalesce block h with free block any free blocks after it.
|
||||
Assumes that H is currently allocated. Sentinel at end is
|
||||
set to allocated so if H is free, caller has to fix it. */
|
||||
for (;;)
|
||||
{
|
||||
long i;
|
||||
M_HEADERP f;
|
||||
M_HEADERP next = (M_HEADERP)getend(h);
|
||||
|
||||
if (next || isalloced(next))
|
||||
break; /* no more coalscing can be done. */
|
||||
|
||||
/* Take it off the free list. */
|
||||
i = getfreeindex(getsize(next));
|
||||
f = freelist[i];
|
||||
if (f == next)
|
||||
freelist[i] = getnext(next);
|
||||
else
|
||||
{
|
||||
while (f != NULL && getnext(f) != next)
|
||||
f = getnext(f);
|
||||
|
||||
/* Didn't find it in the free list. */
|
||||
if (f == NULL)
|
||||
die ("Coalesce failed.");
|
||||
|
||||
setnext(f, getnext(next));
|
||||
}
|
||||
|
||||
/* Add two blocks together and start over. */
|
||||
setsize(h, getsize(h) + getsize(next));
|
||||
|
||||
if (getdbglev(h) > M_DBG_NORMAL)
|
||||
{
|
||||
setsentinel(h, M_ALLOCED);
|
||||
}
|
||||
} /* forever */
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
checkalloc(M_HEADERP this)
|
||||
{
|
||||
if (!isalloced(this))
|
||||
return die ("checkalloc: pointer header clobbered.");
|
||||
|
||||
if (getdbglev(this) > M_DBG_NORMAL)
|
||||
{
|
||||
if (!testsentinel(this, M_ALLOCED))
|
||||
return die ("checkalloc: pointer length overrun.");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
checkfree(M_HEADERP this)
|
||||
{
|
||||
DATA_T *d;
|
||||
int i;
|
||||
if (!isfree(this))
|
||||
die ("checkfree: pointer header clobbered.");
|
||||
|
||||
if (getdbglev(this) > M_DBG_NORMAL)
|
||||
{
|
||||
if (!testsentinel(this, M_FREE))
|
||||
die ("checkfree: pointer length overrun.");
|
||||
|
||||
d = getdata(this);
|
||||
i = getdatasize(this);
|
||||
while (i-- > 0) {
|
||||
if (*d++ != M_FREEFLAG)
|
||||
die("checkfree: freed data clobbered.");
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
checkfreelist()
|
||||
{
|
||||
long i;
|
||||
for (i = 0; i < M_FREESIZE; i += 1)
|
||||
{
|
||||
M_HEADERP h = (M_HEADERP) freelist[i];
|
||||
while (h != NULL)
|
||||
{
|
||||
checkfree(h);
|
||||
if (i != (M_FREESIZE - 1) && getsize(h) != (i * M_BLOCKSIZE))
|
||||
die ("checkfreelist: free list size mismatch.");
|
||||
h = getnext(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
checkalloclist()
|
||||
{
|
||||
M_HEADERP a = (M_HEADERP) alloclist;
|
||||
while (a != NULL)
|
||||
{
|
||||
checkalloc(a);
|
||||
a = getnext(a);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free a block of memory. This is done by adding to the free list. */
|
||||
static void
|
||||
addtofreelist (M_HEADERP h)
|
||||
{
|
||||
long i;
|
||||
/* Merge freed blocks together. */
|
||||
coalesce(h);
|
||||
|
||||
/* link this block to the front of the appropriate free list. */
|
||||
i = getfreeindex(getsize(h));
|
||||
setnext(h, freelist[i]);
|
||||
freelist[i] = h;
|
||||
|
||||
/* Set the flag info. */
|
||||
setfree(h);
|
||||
setdbglev(h, mdebuglevel);
|
||||
if (mdebuglevel > M_DBG_NORMAL)
|
||||
{
|
||||
/* Fill with some meaningful (and testable) data. */
|
||||
setdata(h, M_FREEFLAG);
|
||||
setsentinel(h, M_FREE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xil_malloc_verify()
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < M_BLOCKSIZE; i += 1)
|
||||
{
|
||||
if (zerobuf[i] != M_ZEROFLAG)
|
||||
die ("malloc_verify: Zero block clobbered.");
|
||||
}
|
||||
checkfreelist();
|
||||
checkalloclist();
|
||||
}
|
||||
|
||||
void
|
||||
xil_malloc_debug (int level)
|
||||
{
|
||||
mdebuglevel = MAX (M_DBG_NORMAL, MIN (M_DBG_FULL, level));
|
||||
}
|
||||
|
||||
void*
|
||||
xil_malloc (size_t nbytes)
|
||||
{
|
||||
int i;
|
||||
int minf;
|
||||
int maxf;
|
||||
size_t msize;
|
||||
M_HEADERP p;
|
||||
M_HEADERP h;
|
||||
|
||||
nummallocs += 1;
|
||||
|
||||
if (nbytes == 0)
|
||||
return getdata(zeroblock);
|
||||
|
||||
if (mdebuglevel == M_DBG_FULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
static unsigned do_cnt = ~0;
|
||||
static unsigned done_cnt = 0;
|
||||
if (do_cnt == ~0)
|
||||
{
|
||||
char *x = (char *)getenv(xil_mem_chkcnt);
|
||||
do_cnt = 1;
|
||||
if (x)
|
||||
do_cnt = atoi(x);
|
||||
}
|
||||
if (do_cnt == 1 || done_cnt % do_cnt == 0)
|
||||
xil_malloc_verify();
|
||||
done_cnt++;
|
||||
#else
|
||||
xil_malloc_verify();
|
||||
#endif
|
||||
}
|
||||
|
||||
nbytes += sizeof (struct M_HEADER);
|
||||
|
||||
/* If debug, leave room for flag and next pointer. */
|
||||
if (mdebuglevel > M_DBG_NORMAL)
|
||||
nbytes += sizeof (long) + sizeof (M_HEADERP*);
|
||||
|
||||
/* Round up to allocation unit */
|
||||
msize = ((nbytes + M_BLOCKSIZE - 1) / M_BLOCKSIZE) * M_BLOCKSIZE;
|
||||
|
||||
/* Look around for a block of approximately the right size. */
|
||||
h = NULL;
|
||||
minf = getfreeindex(msize);
|
||||
maxf = MIN(minf * 2, M_FREESIZE);
|
||||
|
||||
for (i = minf; i < M_FREESIZE; i += 1)
|
||||
{
|
||||
if (i >= maxf)
|
||||
i = M_FREESIZE - 1; /* Skip over blocks too large. */
|
||||
|
||||
h = freelist[i];
|
||||
p = NULL; /* Previous. */
|
||||
while (h != NULL)
|
||||
{
|
||||
if (getsize(h) >= nbytes)
|
||||
{
|
||||
/* Take h out of linked list */
|
||||
if (p)
|
||||
setnext(p, getnext(h));
|
||||
else
|
||||
freelist[i] = getnext(h);
|
||||
|
||||
if (!isfree(h))
|
||||
die ("malloc: freelist clobbered.\n");
|
||||
|
||||
goto gotit;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = h;
|
||||
h = getnext(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Didn't find any free pointers. Allocate more heap.
|
||||
Round up to next heap increment. */
|
||||
i = ((msize + sizeof(long) + M_BRKINC - 1) / M_BRKINC) * M_BRKINC;
|
||||
if ((h = getmemblock (i)) == NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf ("xil_malloc: Out of dynamic memory.\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Mark end of block with zero for four bytes so we don't merge next block
|
||||
into free list accidentally. */
|
||||
setsize(h, i - sizeof(long));
|
||||
*((long*)getend(h)) = 0;
|
||||
|
||||
gotit:
|
||||
/* Merge allocated blocks so we can free a bigger part of what is left! */
|
||||
coalesce(h);
|
||||
if (getsize(h) >= msize + M_BLOCKSIZE)
|
||||
{
|
||||
M_HEADERP r;
|
||||
int rsize;
|
||||
/* add the remainder of this block to the free list. */
|
||||
rsize = getsize(h) - msize;
|
||||
r = (M_HEADERP) (((DATA_T *)h) + msize);
|
||||
setsize (r, rsize);
|
||||
setsize (h, msize);
|
||||
addtofreelist (r);
|
||||
}
|
||||
|
||||
setalloced(h);
|
||||
setdbglev(h, mdebuglevel);
|
||||
if (mdebuglevel > M_DBG_NORMAL)
|
||||
{
|
||||
// Chain into alloc'd list and set sentinel. */
|
||||
setsentinel(h, M_ALLOCED);
|
||||
setnext(h, alloclist);
|
||||
alloclist = h;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!m_reenter && m_prtflag)
|
||||
{
|
||||
m_reenter = 1;
|
||||
printf("%d malloc\n",h+1);
|
||||
fflush(stdout);
|
||||
if (m_stopaddr)
|
||||
{
|
||||
if ((DATA_T *)m_stopaddr == getdata(h))
|
||||
{
|
||||
if (m_stopcnt == ++m_curcount)
|
||||
exit(10);
|
||||
}
|
||||
}
|
||||
m_reenter = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
totalmalloc += getsize(h);
|
||||
if (totalmalloc > highwater)
|
||||
highwater = totalmalloc;
|
||||
|
||||
return getdata(h);
|
||||
}
|
||||
|
||||
void
|
||||
xil_free(void* ap)
|
||||
{
|
||||
M_HEADERP h;
|
||||
numfrees += 1;
|
||||
|
||||
if (ap == NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (mdebuglevel != M_DBG_NORMAL && getenv(xil_mem_null_free))
|
||||
die ("free: tried to free NULL pointer.");
|
||||
else
|
||||
return; /* Let `em do it. */
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Drop through to here if not a smartheap allocation. This
|
||||
handles free of both xil_malloc and libc malloc. */
|
||||
|
||||
h = (M_HEADERP) (((DATA_T *)ap) - sizeof (struct M_HEADER));
|
||||
|
||||
if (h == zeroblock)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!m_reenter && m_prtflag) {
|
||||
m_reenter = 1;
|
||||
printf("%d mfree\n",h+1);
|
||||
fflush(stdout);
|
||||
m_reenter = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!isalloced(h)) {
|
||||
if (isfree(h))
|
||||
die ("free: tried to free pointer twice.");
|
||||
else
|
||||
die ("free: tried to free a block not allocated by malloc.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (getdbglev(h) > M_DBG_NORMAL)
|
||||
{
|
||||
/* Make sure things look reasonable. */
|
||||
checkalloc(h);
|
||||
|
||||
/* Try to find the pointer in the alloc list. */
|
||||
if (alloclist == h)
|
||||
alloclist = getnext(h);
|
||||
else
|
||||
{
|
||||
M_HEADERP a = alloclist;
|
||||
while (a != NULL && getnext(a) != h)
|
||||
a = getnext(a);
|
||||
|
||||
/* If a is NULL, debuglevel must have been reset at some point. */
|
||||
if (a != NULL)
|
||||
setnext(a, getnext(h));
|
||||
}
|
||||
}
|
||||
|
||||
totalmalloc -= getsize(h);
|
||||
|
||||
addtofreelist (h);
|
||||
|
||||
if (mdebuglevel == M_DBG_FULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
static unsigned do_cnt = ~0;
|
||||
static unsigned done_cnt = 0;
|
||||
if (do_cnt == ~0)
|
||||
{
|
||||
char *x = (char *)getenv(xil_mem_chkcnt);
|
||||
do_cnt = 1;
|
||||
if (x)
|
||||
do_cnt = atoi(x);
|
||||
}
|
||||
if (do_cnt == 1 || done_cnt % do_cnt == 0)
|
||||
xil_malloc_verify();
|
||||
done_cnt++;
|
||||
#else
|
||||
xil_malloc_verify();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
unsigned
|
||||
xil_msize (void* ap)
|
||||
{
|
||||
M_HEADERP h = (M_HEADERP) (((DATA_T *)ap) - sizeof (struct M_HEADER));
|
||||
return getdatasize(h);
|
||||
}
|
||||
|
||||
void*
|
||||
xil_realloc (void* oldblk, size_t newsize )
|
||||
{
|
||||
M_HEADERP h;
|
||||
size_t oldsize;
|
||||
void* newblk;
|
||||
|
||||
numreallocs += 1;
|
||||
|
||||
if (oldblk == NULL)
|
||||
{
|
||||
if (mdebuglevel != M_DBG_NORMAL)
|
||||
die ("realloc: tried to realloc NULL pointer.");
|
||||
else
|
||||
return xil_malloc(newsize); /* Don't need to copy anything. */
|
||||
}
|
||||
|
||||
/* Make sure this is a valid block. */
|
||||
h = (M_HEADERP) (((char*)oldblk) - sizeof (struct M_HEADER));
|
||||
|
||||
/* if old block was zero bytes, just alloc a new one. */
|
||||
if (h == zeroblock)
|
||||
return xil_malloc(newsize); /* Source is empty anyway. */
|
||||
|
||||
/* If old block was already freed, error. */
|
||||
if (isfree(h))
|
||||
die ("realloc: tried to realloc freed pointer.");
|
||||
|
||||
if (!isalloced(h))
|
||||
{
|
||||
long* pdesc = *(long**)h; /* Get pointer to the block descriptor. */
|
||||
long* pnextdesc = (long*)*pdesc;
|
||||
if ((pdesc[1] & ~3) != (long)h) /* Should point back to block. */
|
||||
die ("realloc: header clobbered.");
|
||||
|
||||
/* This must be a libc block. We need to figure out how big it is.
|
||||
Length of block is delta between two descriptors - sizeof (void*). */
|
||||
|
||||
oldsize = (size_t) ((pnextdesc[1] & ~3) - (pdesc[1] & ~3)-sizeof(void*));
|
||||
|
||||
/* Don't bother to change anything unless there's not enough room. */
|
||||
if (oldsize < newsize)
|
||||
{
|
||||
/* Alloc a new block with our malloc. */
|
||||
if ((newblk = xil_malloc(newsize)) == NULL )
|
||||
return NULL ;
|
||||
|
||||
/* Copy the old data to it. */
|
||||
memcpy (newblk, oldblk, (newsize < oldsize) ? newsize : oldsize);
|
||||
xil_free(oldblk);
|
||||
return newblk;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the new size is bigger than my allocated
|
||||
size, or if more than 1/4 of the block would be left free, allocate
|
||||
a new block and copy the data. Otherwise, leave well enough alone. */
|
||||
|
||||
coalesce(h);
|
||||
|
||||
oldsize = getdatasize(h);
|
||||
|
||||
if (oldsize < newsize
|
||||
|| (newsize > (2*M_BLOCKSIZE) && (newsize*4) < (oldsize*3)))
|
||||
{
|
||||
if (( newblk = xil_malloc( newsize )) == NULL )
|
||||
return NULL ;
|
||||
|
||||
memcpy (newblk, oldblk, (newsize < oldsize) ? newsize : oldsize);
|
||||
|
||||
xil_free (oldblk);
|
||||
return newblk;
|
||||
}
|
||||
else
|
||||
return oldblk;
|
||||
}
|
||||
|
||||
void*
|
||||
xil_calloc (size_t number, size_t size)
|
||||
{
|
||||
long* longptr ;
|
||||
void* blockptr ;
|
||||
size_t temp = number * size + sizeof (long) - 1;
|
||||
temp -= temp % sizeof (long);
|
||||
|
||||
blockptr = xil_malloc( temp );
|
||||
if ( blockptr != 0 )
|
||||
{
|
||||
longptr = (long*) blockptr ;
|
||||
temp /= sizeof (long);
|
||||
while ( temp-- > 0 )
|
||||
{
|
||||
*longptr++ = 0 ;
|
||||
}
|
||||
}
|
||||
return blockptr ;
|
||||
}
|
||||
|
||||
#define M_STAT_NORMAL 0
|
||||
#define M_STAT_VERBOSE 1
|
||||
#define M_STAT_REALLYVERBOSE 2
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
xil_mstats(int verbosity)
|
||||
{
|
||||
unsigned long totalfree = 0;
|
||||
int i;
|
||||
printf("Memory Statics:\n"
|
||||
"---------------\n");
|
||||
printf(" Number of calls to malloc: %ld.\n", nummallocs);
|
||||
printf(" Number of calls to free: %ld.\n", numfrees);
|
||||
printf(" Number of calls to realloc: %ld.\n", numreallocs);
|
||||
printf(" Total allocated memory: %lu (0x%lx)\n",
|
||||
totalallocated, totalallocated);
|
||||
printf(" Currently malloced memory: %lu (0x%lx)\n",
|
||||
totalmalloc, totalmalloc);
|
||||
fflush(stdout);
|
||||
|
||||
|
||||
for (i = 0; i < M_FREESIZE; i += 1)
|
||||
{
|
||||
M_HEADERP h = freelist[i];
|
||||
unsigned long numblocks = 0;
|
||||
while (h != NULL)
|
||||
{
|
||||
totalfree += getsize(h);
|
||||
numblocks += 1;
|
||||
h = getnext(h);
|
||||
}
|
||||
if (verbosity > M_STAT_NORMAL && numblocks > 0)
|
||||
{
|
||||
printf(" There are %d blocks on freelist for size %d\n",
|
||||
numblocks, i * M_BLOCKSIZE);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
printf(" Currently free memory: %lu (0x%lx)\n",
|
||||
totalfree, totalfree);
|
||||
printf(" High water mark: %lu (0x%lx)\n",
|
||||
highwater, highwater);
|
||||
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
#else
|
||||
void
|
||||
xil_mstats(int verbosity)
|
||||
{
|
||||
}
|
||||
#endif
|
Reference in New Issue
Block a user