* 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.
		
	
		
			
				
	
	
		
			805 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			805 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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
 |