source: trunk/libs/newlib/src/libgloss/microblaze/xil_malloc.c @ 650

Last change on this file since 650 was 444, checked in by satin@…, 7 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 20.2 KB
Line 
1/* Copyright (c) 1995, 2002, 2009 Xilinx, Inc.  All rights reserved.
2   
3   Redistribution and use in source and binary forms, with or without
4   modification, are permitted provided that the following conditions are
5   met:
6   
7   1.  Redistributions source code must retain the above copyright notice,
8   this list of conditions and the following disclaimer.
9   
10   2.  Redistributions in binary form must reproduce the above copyright
11   notice, this list of conditions and the following disclaimer in the
12   documentation and/or other materials provided with the distribution.
13   
14   3.  Neither the name of Xilinx nor the names of its contributors may be
15   used to endorse or promote products derived from this software without
16   specific prior written permission.
17   
18   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
19   IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21   PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22   HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24   TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30*/
31
32#ifdef DEBUG
33#include <stdlib.h>
34#include <stddef.h>
35#include <stdio.h>
36#else
37typedef unsigned int size_t;
38#define NULL 0
39#endif
40
41#define sbrk xil_sbrk
42
43/* The only extern functions I need if not printing. */
44extern  void* sbrk(size_t incr);
45extern  void *memcpy(void *s1, const void *s2, size_t n);
46extern  void *memset(void *s, int c, size_t n);
47
48
49typedef unsigned char BOOLEAN;
50const BOOLEAN FALSE=0;
51const BOOLEAN TRUE =1;
52
53#define MIN(a,b) (((a) < (b)) ? (a) : (b))
54#define MAX(a,b) (((a) > (b)) ? (a) : (b))
55
56#define M_DBG_NORMAL 0
57#define M_DBG_PARTIAL 1
58#define M_DBG_FULL 2
59
60/* debugging breakpoint aids */
61static char xil_mem_null_free[] = "xil_mem_null_free";
62static char xil_mem_chkcnt   [] = "xil_mem_chkcnt";
63
64/* Flag values describing the state of a memory block.
65/* Indicator for allocated blk */
66#define M_ALLOCEDFLAG 0x5a
67/* End-of-block if debug level */
68#define M_ALLOCED 0xc99cc99c
69/* Free block indicator. */
70#define M_FREEFLAG 0xa5
71/* End-of-block if debug level */
72#define M_FREE 0x9cc99cc9
73/* Zero length block. */
74#define M_ZEROFLAG 0xaa
75
76/* Header of a memory block. */
77typedef unsigned char DATA_T;
78typedef DATA_T *      DATA_P;
79struct M_HEADER
80{
81  unsigned       dbglev:2;       /* Debug level this was created with. */
82  unsigned       size:22;        /* Size of block / 8. 32 Meg max. */
83  unsigned       flag:8;         /* Indicates whether allocated or freed. */
84};
85typedef struct M_HEADER* M_HEADERP;
86
87BOOLEAN isalloced(M_HEADERP this)     
88{ 
89  return this->flag == M_ALLOCEDFLAG; 
90}
91BOOLEAN isfree(M_HEADERP this)         
92{ 
93  return this->flag == M_FREEFLAG; 
94}
95BOOLEAN iszero(M_HEADERP this)         
96{ 
97  return this->flag == M_ZEROFLAG; 
98}
99
100void           setalloced(M_HEADERP this)     { this->flag = M_ALLOCEDFLAG; }
101void           setfree(M_HEADERP this)        { this->flag = M_FREEFLAG; }
102void           setzero(M_HEADERP this)        { this->flag = M_ZEROFLAG; }
103
104int            getdbglev(M_HEADERP this)      { return this->dbglev; }
105void           setdbglev(M_HEADERP this, int d) { this->dbglev = d; }
106
107size_t         getsize(M_HEADERP this)        { return this->size << 3; }  /* Alignment is 8. */
108void           setsize(M_HEADERP this, size_t s){ this->size = s >> 3; }     
109
110DATA_T *       getend(M_HEADERP this)         { return (((DATA_T *)this)+getsize(this)); }
111
112/* Next pointer is after data in block. */
113M_HEADERP     getnext(M_HEADERP this)        { return *(((M_HEADERP*)getend(this)) - 1); }
114void           setnext(M_HEADERP this, M_HEADERP n) { *(((M_HEADERP*)getend(this)) - 1) = n; }
115
116/* Routines used to set a flag at end of block if debuglevel != normal. */
117/* Sentinel is right BEFORE the next pointer. */
118unsigned long* getsentinel(M_HEADERP this);
119void           setsentinel(M_HEADERP this, unsigned long lflag);
120BOOLEAN        testsentinel(M_HEADERP this, unsigned long lflag);
121
122/* Routines to handle data.  Depend on debug level. */
123DATA_T *       getdata(M_HEADERP this)        { return (((DATA_T*)this)+sizeof(*this)); }
124size_t         getdatasize(M_HEADERP this);
125
126/* Fill data with a pattern. */
127void           setdata(M_HEADERP this, int f);
128
129/* Debug routines */
130BOOLEAN        checkalloc(M_HEADERP this);    /* Is this a valid allocated memory pointer? */
131BOOLEAN        checkfree(M_HEADERP this);     /* Is this a valid freelist entry? */
132
133
134
135/* Get length of data. */
136size_t 
137getdatasize(M_HEADERP this)
138{
139  /* By default, size is size of block - size of header. */
140  int tmp_size = getsize(this) - sizeof(struct M_HEADER);
141
142  if (this->dbglev != M_DBG_NORMAL) 
143    {
144      /* Subtract size of sentinel, and next pointer. */
145      tmp_size -= sizeof(long) + sizeof(M_HEADERP);
146      /* If only eight bytes, no room for sentinel. */
147      if (tmp_size < 0)
148        tmp_size = 0;
149    } 
150  else 
151    {
152      /* Free block always has a next pointer.  Otherwise not. */
153      if (isfree(this))
154        tmp_size -= sizeof(M_HEADERP);
155    }
156  return tmp_size;
157}
158
159/* Set the data buffer to value f. */
160void 
161setdata(M_HEADERP this, int f)
162{ 
163  memset(getdata(this), f, getdatasize(this));
164}
165
166/* At the end of the block, there may be a longword with
167   special meaning.  This is the sentinel.  If there is a sentinel,
168   there is by definition a next pointer. */
169unsigned long* 
170getsentinel(M_HEADERP this)
171{
172  DATA_T* addr = (getend(this) - sizeof(M_HEADERP)); /* location of next pointer. */
173  if (getdata(this) < addr)
174    return ((unsigned long*)addr) - 1;        /* Right before next pointer. */
175  else
176    return NULL;                      /* Block too small.  No room for sent. */
177}
178
179void 
180setsentinel(M_HEADERP this, unsigned long lflag)
181{
182  unsigned long* addr = getsentinel(this);
183  if (addr)
184    *addr = lflag;
185}
186
187BOOLEAN
188testsentinel(M_HEADERP this, unsigned long lflag)
189{
190  unsigned long* addr = getsentinel(this);
191  if (addr)
192    return *addr == lflag;
193  else
194    return TRUE;
195}
196
197/*  sizeof(struct M_HEADER)+sizeof(M_HEADERP);  Alignment */
198#define M_BLOCKSIZE 8
199/*  4096 / 8; // M_BLOCKSIZE ;      Number of freelist entries. */
200#define M_FREESIZE 512
201/*  64 * 1024;                 Size of incremental memory hunks allocated, */
202#define M_BRKINC 2048
203
204static M_HEADERP freelist[M_FREESIZE];       /* Free list. */
205
206static M_HEADERP alloclist = NULL;           /* Pointer to linked list
207                                                of Allocated blocks. */
208static int mdebuglevel = M_DBG_NORMAL;
209
210static DATA_T zerobuf[M_BLOCKSIZE] = { M_ZEROFLAG, M_ZEROFLAG, M_ZEROFLAG,
211                                       M_ZEROFLAG, M_ZEROFLAG, M_ZEROFLAG, 
212                                       M_ZEROFLAG, M_ZEROFLAG };
213static M_HEADERP zeroblock = (M_HEADERP)zerobuf;
214
215static unsigned long totalallocated = 0;        /* NOT actually malloced, but
216                                                   rather the size of the pool. */
217
218static unsigned long totalmalloc = 0;           /* Total amount malloced. */
219
220static unsigned long highwater = 0;             /* Largest amount of memory
221                                                   allocated at any time. */
222static long nummallocs = 0;
223static long numfrees = 0;
224static long numreallocs = 0;
225
226int m_prtflag  = 0;
227int m_stopaddr = 0;
228int m_stopcnt  = 0;
229int m_reenter  = 0;
230static int m_curcount = 0;
231
232M_HEADERP
233getmemblock(size_t n)
234{
235  M_HEADERP block = (M_HEADERP) sbrk(n);
236  if (block != NULL)
237    totalallocated += n;
238
239  return block;
240}
241
242
243static BOOLEAN
244die (char* msg)
245{
246  mdebuglevel = M_DBG_NORMAL;
247#ifdef DEBUG
248  printf ("%s\n", msg);
249  exit (1);
250#else
251  /* Go into infinite loop. */
252  for (;;)
253    ;
254#endif
255  return FALSE;
256}
257
258int 
259getfreeindex(size_t size)
260{
261  return MIN(size / M_BLOCKSIZE, M_FREESIZE - 1);
262}
263
264static
265void coalesce(M_HEADERP h)
266{
267  /* Coalesce block h with free block any free blocks after it.
268     Assumes that H is currently allocated.  Sentinel at end is
269     set to allocated so if H is free, caller has to fix it. */
270  for (;;) 
271    {
272      long i;
273      M_HEADERP f;
274      M_HEADERP next = (M_HEADERP)getend(h);
275
276      if (next || isalloced(next))
277        break; /* no more coalscing can be done. */
278         
279      /* Take it off the free list. */
280      i = getfreeindex(getsize(next));
281      f = freelist[i];
282      if (f == next)
283        freelist[i] = getnext(next);
284      else 
285        {
286          while (f != NULL && getnext(f) != next)
287            f = getnext(f);
288
289          /* Didn't find it in the free list. */
290          if (f == NULL)
291            die ("Coalesce failed.");
292
293          setnext(f, getnext(next));
294        }
295
296      /* Add two blocks together and start over. */
297      setsize(h, getsize(h) + getsize(next));
298
299      if (getdbglev(h) > M_DBG_NORMAL) 
300        {
301          setsentinel(h, M_ALLOCED);
302        }
303    } /* forever */
304}
305
306BOOLEAN
307checkalloc(M_HEADERP this)
308{
309  if (!isalloced(this))
310    return die ("checkalloc: pointer header clobbered.");
311
312  if (getdbglev(this) > M_DBG_NORMAL) 
313    {
314      if (!testsentinel(this, M_ALLOCED))
315        return die ("checkalloc: pointer length overrun.");
316    }
317  return TRUE;
318}
319
320BOOLEAN
321checkfree(M_HEADERP this)
322{
323  DATA_T *d;
324  int i;
325  if (!isfree(this))
326    die ("checkfree: pointer header clobbered.");
327
328  if (getdbglev(this) > M_DBG_NORMAL) 
329    {
330      if (!testsentinel(this, M_FREE))
331        die ("checkfree: pointer length overrun.");
332
333      d = getdata(this);
334      i = getdatasize(this);
335      while (i-- > 0) {
336        if (*d++ != M_FREEFLAG)
337          die("checkfree: freed data clobbered.");
338      }
339    }
340  return TRUE;
341}
342
343static void 
344checkfreelist()
345{
346  long i;
347  for (i = 0; i < M_FREESIZE; i += 1) 
348    {
349      M_HEADERP h = (M_HEADERP) freelist[i];
350      while (h != NULL) 
351        {
352        checkfree(h);
353        if (i != (M_FREESIZE - 1) && getsize(h) != (i * M_BLOCKSIZE))
354          die ("checkfreelist: free list size mismatch.");
355        h = getnext(h);
356        }
357    }
358}
359
360static void 
361checkalloclist()
362{
363  M_HEADERP a = (M_HEADERP) alloclist;
364  while (a != NULL) 
365    {
366      checkalloc(a);
367      a = getnext(a);
368    }
369}
370
371/* Free a block of memory.  This is done by adding to the free list. */
372static void 
373addtofreelist (M_HEADERP h)
374{
375  long i;
376  /* Merge freed blocks together. */
377  coalesce(h);
378
379  /* link this block to the front of the appropriate free list. */
380  i = getfreeindex(getsize(h));
381  setnext(h, freelist[i]);
382  freelist[i] = h;
383
384  /* Set the flag info. */
385  setfree(h);
386  setdbglev(h, mdebuglevel);
387  if (mdebuglevel > M_DBG_NORMAL) 
388    {
389      /* Fill with some meaningful (and testable) data. */
390      setdata(h, M_FREEFLAG);
391      setsentinel(h, M_FREE);
392    }
393}
394
395void 
396xil_malloc_verify()
397{
398  int i;
399  for ( i = 0; i < M_BLOCKSIZE; i += 1) 
400    {
401      if (zerobuf[i] != M_ZEROFLAG)
402        die ("malloc_verify: Zero block clobbered.");
403    }
404  checkfreelist();
405  checkalloclist();
406}
407
408void 
409xil_malloc_debug (int level)
410{
411  mdebuglevel = MAX (M_DBG_NORMAL, MIN (M_DBG_FULL, level));
412}
413
414void* 
415xil_malloc (size_t nbytes)
416{
417  int i;
418  int minf;
419  int maxf;
420  size_t msize;
421  M_HEADERP p;
422  M_HEADERP h;
423
424  nummallocs += 1;
425
426  if (nbytes == 0)
427    return getdata(zeroblock);
428
429  if (mdebuglevel == M_DBG_FULL)
430    {
431#ifdef DEBUG
432      static unsigned do_cnt = ~0;
433      static unsigned done_cnt = 0;
434      if (do_cnt == ~0) 
435        {
436          char *x = (char *)getenv(xil_mem_chkcnt);
437          do_cnt = 1;
438          if (x)
439            do_cnt = atoi(x);
440        }
441      if (do_cnt == 1 || done_cnt % do_cnt == 0)
442        xil_malloc_verify();
443      done_cnt++;
444#else
445      xil_malloc_verify();
446#endif
447    }
448
449  nbytes += sizeof (struct M_HEADER);
450
451  /* If debug, leave room for flag and next pointer. */
452  if (mdebuglevel > M_DBG_NORMAL)
453    nbytes += sizeof (long) + sizeof (M_HEADERP*);
454
455  /* Round up to allocation unit */
456  msize = ((nbytes + M_BLOCKSIZE - 1) / M_BLOCKSIZE) * M_BLOCKSIZE;
457
458  /* Look around for a block of approximately the right size. */
459  h = NULL;
460  minf = getfreeindex(msize);
461  maxf = MIN(minf * 2, M_FREESIZE);
462
463  for (i = minf; i < M_FREESIZE; i += 1) 
464    {
465      if (i >= maxf)
466        i = M_FREESIZE - 1;    /* Skip over blocks too large. */
467
468      h = freelist[i];
469      p = NULL;       /* Previous. */
470      while (h != NULL) 
471        {
472          if (getsize(h) >= nbytes) 
473            {
474              /* Take h out of linked list */
475              if (p)
476                setnext(p, getnext(h));
477              else
478                freelist[i] = getnext(h);
479
480              if (!isfree(h))
481                die ("malloc: freelist clobbered.\n");
482
483              goto gotit;
484            }
485          else 
486            {
487              p = h;
488              h = getnext(h);
489            }
490        }
491    }
492
493  /* Didn't find any free pointers.  Allocate more heap.
494     Round up to next heap increment. */
495  i = ((msize + sizeof(long) + M_BRKINC - 1) / M_BRKINC) * M_BRKINC;
496  if ((h = getmemblock (i)) == NULL) 
497    {
498#ifdef DEBUG
499      printf ("xil_malloc: Out of dynamic memory.\n");
500#endif
501      return NULL;
502    }
503
504  /* Mark end of block with zero for four bytes so we don't merge next block
505     into free list accidentally. */
506  setsize(h, i - sizeof(long));
507  *((long*)getend(h)) = 0;
508
509 gotit:
510  /* Merge allocated blocks so we can free a bigger part of what is left! */
511  coalesce(h);
512  if (getsize(h) >= msize + M_BLOCKSIZE) 
513    {
514      M_HEADERP r;
515      int rsize;
516      /* add the remainder of this block to the free list. */
517      rsize = getsize(h) - msize;
518      r = (M_HEADERP) (((DATA_T *)h) + msize);
519      setsize (r, rsize);
520      setsize (h, msize);
521      addtofreelist (r);
522    }
523
524  setalloced(h);
525  setdbglev(h, mdebuglevel);
526  if (mdebuglevel > M_DBG_NORMAL) 
527    {
528      // Chain into alloc'd list and set sentinel. */
529      setsentinel(h, M_ALLOCED);
530      setnext(h, alloclist);
531      alloclist = h;
532    }
533
534#ifdef DEBUG
535  if (!m_reenter && m_prtflag) 
536    {
537      m_reenter = 1;
538      printf("%d      malloc\n",h+1);
539      fflush(stdout);
540      if (m_stopaddr)
541        {
542          if ((DATA_T *)m_stopaddr == getdata(h))
543            {
544              if (m_stopcnt == ++m_curcount)
545                exit(10);
546            }
547        }
548      m_reenter = 0;
549    }
550#endif
551
552  totalmalloc += getsize(h);
553  if (totalmalloc > highwater)
554    highwater = totalmalloc;
555
556  return getdata(h);
557}
558
559void 
560xil_free(void* ap)
561{
562  M_HEADERP h;
563  numfrees += 1;
564
565  if (ap == NULL) 
566   {
567#ifdef DEBUG
568     if (mdebuglevel != M_DBG_NORMAL && getenv(xil_mem_null_free))
569       die ("free: tried to free NULL pointer.");
570     else
571       return;        /* Let `em do it. */
572#else
573     return;
574#endif
575   }
576
577  /* Drop through to here if not a smartheap allocation.  This
578     handles free of both xil_malloc and libc malloc. */
579
580  h = (M_HEADERP) (((DATA_T *)ap) - sizeof (struct M_HEADER));
581
582  if (h == zeroblock)
583    return;
584
585#ifdef DEBUG
586  if (!m_reenter && m_prtflag) {
587    m_reenter = 1;
588    printf("%d      mfree\n",h+1);
589    fflush(stdout);
590    m_reenter = 0;
591  }
592#endif
593
594  if (!isalloced(h)) {
595    if (isfree(h))
596      die ("free: tried to free pointer twice.");
597    else
598      die ("free: tried to free a block not allocated by malloc.");
599    return;
600  }
601
602  if (getdbglev(h) > M_DBG_NORMAL) 
603    {
604      /* Make sure things look reasonable. */
605      checkalloc(h);
606
607      /* Try to find the pointer in the alloc list. */
608      if (alloclist == h)
609        alloclist = getnext(h);
610      else 
611        {
612          M_HEADERP a = alloclist;
613          while (a != NULL && getnext(a) != h)
614            a = getnext(a);
615
616          /* If a is NULL, debuglevel must have been reset at some point. */
617          if (a != NULL)
618            setnext(a, getnext(h));
619        }
620    }
621
622  totalmalloc -= getsize(h);
623
624  addtofreelist (h);
625
626  if (mdebuglevel == M_DBG_FULL) 
627    {
628#ifdef DEBUG
629      static unsigned do_cnt = ~0;
630      static unsigned done_cnt = 0;
631      if (do_cnt == ~0) 
632        {
633          char *x = (char *)getenv(xil_mem_chkcnt);
634          do_cnt = 1;
635          if (x)
636            do_cnt = atoi(x);
637        }
638      if (do_cnt == 1 || done_cnt % do_cnt == 0)
639        xil_malloc_verify();
640      done_cnt++;
641#else
642      xil_malloc_verify();
643#endif
644    }
645}
646
647unsigned 
648xil_msize (void* ap)
649{
650  M_HEADERP h = (M_HEADERP) (((DATA_T *)ap) - sizeof (struct M_HEADER));
651  return getdatasize(h);
652}
653
654void* 
655xil_realloc (void* oldblk, size_t newsize )
656{
657  M_HEADERP h;
658  size_t oldsize;
659  void* newblk;
660
661  numreallocs += 1;
662
663  if (oldblk == NULL) 
664    {
665      if (mdebuglevel != M_DBG_NORMAL)
666        die ("realloc: tried to realloc NULL pointer.");
667      else
668        return xil_malloc(newsize);        /* Don't need to copy anything. */
669    }
670
671  /* Make sure this is a valid block. */
672  h = (M_HEADERP) (((char*)oldblk) - sizeof (struct M_HEADER));
673
674  /* if old block was zero bytes, just alloc a new one. */
675  if (h == zeroblock)
676    return xil_malloc(newsize);           /* Source is empty anyway. */
677
678  /* If old block was already freed, error. */
679  if (isfree(h))
680    die ("realloc: tried to realloc freed pointer.");
681
682  if (!isalloced(h)) 
683    {
684      long* pdesc = *(long**)h;         /* Get pointer to the block descriptor. */
685      long* pnextdesc = (long*)*pdesc;
686      if ((pdesc[1] & ~3) != (long)h)   /* Should point back to block. */
687        die ("realloc: header clobbered.");
688
689      /* This must be a libc block.  We need to figure out how big it is.
690         Length of block is delta between two descriptors - sizeof (void*). */
691     
692      oldsize = (size_t) ((pnextdesc[1] & ~3) - (pdesc[1] & ~3)-sizeof(void*));
693
694      /* Don't bother to change anything unless there's not enough room. */
695      if (oldsize < newsize) 
696        {
697          /* Alloc a new block with our malloc. */
698          if ((newblk = xil_malloc(newsize)) == NULL )
699            return NULL ;
700
701          /* Copy the old data to it. */
702          memcpy (newblk, oldblk, (newsize < oldsize) ? newsize : oldsize);
703          xil_free(oldblk);
704          return newblk;
705        }
706    }
707
708  /* If the new size is bigger than my allocated
709     size, or if more than 1/4 of the block would be left free, allocate
710     a new block and copy the data.  Otherwise, leave well enough alone. */
711
712  coalesce(h);
713
714  oldsize = getdatasize(h);
715
716  if (oldsize < newsize
717      || (newsize > (2*M_BLOCKSIZE) && (newsize*4) < (oldsize*3))) 
718    {
719      if (( newblk = xil_malloc( newsize )) == NULL )
720        return NULL ;
721
722      memcpy (newblk, oldblk, (newsize < oldsize) ? newsize : oldsize);
723
724      xil_free (oldblk);
725      return newblk;
726    }
727  else
728    return oldblk;
729}
730
731void* 
732xil_calloc (size_t number, size_t size)
733{
734  long*  longptr ;
735  void*  blockptr ;
736  size_t temp   = number * size + sizeof (long) - 1;
737  temp -= temp % sizeof (long);
738
739  blockptr = xil_malloc( temp );
740  if ( blockptr != 0 ) 
741    {
742      longptr = (long*) blockptr ;
743      temp /= sizeof (long);
744      while ( temp-- > 0 ) 
745        {
746          *longptr++ = 0 ;
747        }
748    }
749  return blockptr ;
750}
751
752#define M_STAT_NORMAL 0
753#define M_STAT_VERBOSE 1
754#define M_STAT_REALLYVERBOSE 2
755
756#ifdef DEBUG
757void 
758xil_mstats(int verbosity)
759{ 
760  unsigned long totalfree = 0;
761  int i;
762  printf("Memory Statics:\n"
763         "---------------\n");
764  printf("   Number of calls to malloc:   %ld.\n", nummallocs);
765  printf("   Number of calls to free:     %ld.\n", numfrees);
766  printf("   Number of calls to realloc:  %ld.\n", numreallocs);
767  printf("   Total allocated memory:      %lu (0x%lx)\n",
768         totalallocated, totalallocated);
769  printf("   Currently malloced memory:   %lu (0x%lx)\n",
770         totalmalloc, totalmalloc);
771  fflush(stdout);
772
773 
774  for (i = 0; i < M_FREESIZE; i += 1) 
775    {
776      M_HEADERP h = freelist[i];
777      unsigned long numblocks = 0;
778      while (h != NULL) 
779        {
780          totalfree += getsize(h);
781          numblocks += 1;
782          h = getnext(h);
783        }
784      if (verbosity > M_STAT_NORMAL && numblocks > 0) 
785        {
786          printf("   There are %d blocks on freelist for size %d\n",
787                 numblocks, i * M_BLOCKSIZE);
788          fflush(stdout);
789        }
790    }
791  printf("   Currently free memory:       %lu (0x%lx)\n",
792         totalfree, totalfree);
793  printf("   High water mark:             %lu (0x%lx)\n",
794         highwater, highwater);
795
796  printf("\n");
797  fflush(stdout);
798}
799#else
800void 
801xil_mstats(int verbosity)
802{
803}
804#endif
Note: See TracBrowser for help on using the repository browser.