Attempt to fix nightly build.
[AROS-Contrib.git] / gfx / povray / mem.c
blob6c1e4a1236a2e94e7e096b40fd7d1e9514f5fb18
1 /****************************************************************************
2 * mem.c
4 * This module contains the code for our own memory allocation/deallocation,
5 * providing memory tracing, statistics, and garbage collection options.
7 * from Persistence of Vision(tm) Ray Tracer
8 * Copyright 1996,1999 Persistence of Vision Team
9 *---------------------------------------------------------------------------
10 * NOTICE: This source code file is provided so that users may experiment
11 * with enhancements to POV-Ray and to port the software to platforms other
12 * than those supported by the POV-Ray Team. There are strict rules under
13 * which you are permitted to use this file. The rules are in the file
14 * named POVLEGAL.DOC which should be distributed with this file.
15 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
16 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
17 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
19 * This program is based on the popular DKB raytracer version 2.12.
20 * DKBTrace was originally written by David K. Buck.
21 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
23 *****************************************************************************/
25 #include "frame.h"
26 #include "povproto.h" /* Error() */
28 #include "mem.h"
29 #include "parse.h" /* MAError() */
30 #include "povray.h" /* stats[] global var */
31 #include <stdlib.h> /* for calloc */
33 /************************************************************************
34 * AUTHOR
36 * Steve Anger:70714,3113
38 * DESCRIPTION
40 This module replaces the memory allocation calls malloc, calloc, realloc
41 and free with the macros POV_MALLOC, POV_CALLOC, POV_REALLOC, and POV_FREE.
42 These macros work the same as the standard C functions except that the
43 POV_xALLOC functions also take a message as the last parameter and
44 automatically call MAError(msg) if the allocation fails. That means that
45 instead of writing
47 if ((New = malloc(sizeof(*New))) == NULL)
49 MAError ("new object");
52 you'd just use
54 New = POV_MALLOC (sizeof(*New), "new object");
56 This also expands the function of the macros to include error checking and
57 memory tracking.
59 The following macros need to be defined in config.h, depending of what
60 features the compile needs:
62 #define MEM_TAG - Enables memory tag debugging
63 --------------------------------------------------
64 Memory tag debugging adds a 32-bit identifier to the beginning of each
65 allocated memory block and erases it after the block has been free'd. This
66 lets POV_FREE verify that the block it's freeing is valid and issue an
67 error message if it isn't. Makes it easy to find those nasty double free's
68 which usually corrupt the heap.
70 #define MEM_RECLAIM - Enables garbage collection
71 ------------------------------------------------
72 Garbage collection maintains a list of all currently allocated memory so
73 that it can be free'd when the program exits. Normally POV-Ray will free all
74 of its memory on its own, however abnormal exits such as parser errors or
75 user aborts bypass the destructors. There are four functions which control
76 the garbage collection:
78 mem_init()
79 Initializes global variables used by the garbage collection routines.
80 This function should be called once before any memory allocation functions
81 are called.
83 mem_mark()
84 Starts a new memory pool. The next call to mem_release() will only release
85 memory allocated after this call.
87 mem_release (int LogFile)
88 Releases all unfree'd memory allocated since the last call to mem_mark().
89 The LogFile parameter determines if it dumps the list of unfree'd memory to
90 a file.
92 mem_release_all (int LogFile)
93 Releases all unfree'd memory allocated since the program started running.
95 POV-Ray only uses the mem_release_all() function however mem_mark() and
96 mem_release() might be useful for implenting a leak-free animation loop.
98 #define MEM_TRACE - Enables garbage collection and memory tracing
99 -------------------------------------------------------------------
100 Memory tracing stores the file name and line number for ever POV_xALLOC
101 call and dumps a list of unfree'd blocks when POV-Ray terminates.
103 #define MEM_STATS 1 - enables tracking of memory statistics
104 -------------------------------------------------------------------
105 Memory statistics enables routines that will track overall memory usage.
106 After all memory allocation/deallocation has taken place, and before you
107 re-initialize everything with another mem_init() call, you can call some
108 accessor routines to determine how memory was used. Setting MEM_STATS
109 to 1 only tracks peak memory usage. Setting it to 2 additionally tracks
110 number of calls to malloc/free and some other statistics.
112 * CHANGES
114 * Aug 1995 : Steve Anger - Creation.
115 * Apr 1996 : Eduard Schwan - Added MEM_STATS code
116 * Jul 1996 : Andreas Dilger - Force mem_header to align on double boundary
117 **************************************************************************/
120 /****************************************************************************/
121 /* Allow user definable replacements for memory functions */
122 /****************************************************************************/
123 #ifndef MALLOC
124 #define MALLOC malloc
125 #endif
127 #ifndef CALLOC
128 #define CALLOC calloc
129 #endif
131 #ifndef REALLOC
132 #define REALLOC realloc
133 #endif
135 #ifndef FREE
136 #define FREE free
137 #endif
140 /****************************************************************************/
141 /* internal use */
142 /****************************************************************************/
144 /* if TRACE is on, the RECLAIM must also be on */
145 #if defined(MEM_TRACE) && !defined (MEM_RECLAIM)
146 #define MEM_RECLAIM
147 #endif
149 /* This is the filename created for memory leakage information */
150 #if defined(MEM_TRACE)
151 #define MEM_LOG_FNAME "Memory.Log"
152 #endif
154 /* determine if we need to add a header to our memory records */
155 #if defined(MEM_TAG) || defined(MEM_RECLAIM) || defined(MEM_TRACE) || defined(MEM_STATS)
156 #define MEM_HEADER
157 #endif
159 #define MEMNODE struct mem_node
161 #if defined(MEM_HEADER)
163 struct mem_node
166 /* We have to do lots of testing here to make sure that the size of the
167 * mem_node struct is an even multiple of the sizeof(double) (usually 8
168 * bytes, or we royally screw up some architectures. Yuck!!! To make
169 * things easier, we have smaller groups of variables, and make them
170 * work out to multiples of 8 bytes, rather than trying to do it for the
171 * whole structure. In most cases, only 4 bytes are wasted, as this is
172 * mostly for debugging anyways.
175 #if defined(MEM_TAG)
176 long tag;
177 #if !defined(MEM_STATS) || defined(MEM_TRACE)
178 long junk1;
179 #endif /* !MEM_STATS */
180 #endif /* MEM_TAG */
182 #if defined(MEM_STATS) && !defined(MEM_TRACE)
183 size_t size;
184 #if !defined(MEM_TAG)
185 long junk1;
186 #endif /* !MEM_TAG */
187 #endif /* MEM_STATS */
189 #if defined(MEM_RECLAIM)
190 MEMNODE *prev;
191 MEMNODE *next;
192 long poolno;
193 #if defined(MEM_TRACE)
194 char *file;
195 long line;
196 size_t size;
197 #else
198 long junk2;
199 #endif /* MEM_TRACE */
200 #endif /* MEM_RECLAIM */
203 #endif /* MEM_HEADER */
206 #if defined(MEM_RECLAIM)
207 static int poolno = 0;
208 static MEMNODE *memlist = NULL;
209 #endif
212 static int leak_msg = FALSE;
215 #if defined(MEM_HEADER)
216 #define NODESIZE ((sizeof(MEMNODE)+3)/4)*4 /* Align memory on 4 byte boundary */
217 #else
218 #define NODESIZE 0
219 #endif
222 #if defined(MEM_RECLAIM)
223 static void add_node(MEMNODE * node);
224 static void remove_node(MEMNODE * node);
225 #endif
228 #if defined(MEM_TAG)
229 /* the tag value that marks our used memory */
230 #define MEMTAG_VALUE 0x4D546167L
232 static int mem_check_tag(MEMNODE * node);
234 #endif
237 #if defined(MEM_RECLAIM)
238 static long num_nodes; /* keep track of valence of node list */
239 #endif /* MEM_RECLAIM */
242 #if defined(MEM_STATS)
244 typedef struct MemStats_Struct MEMSTATS;
246 struct MemStats_Struct
248 size_t smallest_alloc; /* smallest # of bytes in one malloc() */
249 size_t largest_alloc; /* largest # of bytes in one malloc() */
250 size_t current_mem_usage; /* current total # of bytes allocated */
251 size_t largest_mem_usage; /* peak total # of bytes allocated */
252 #if (MEM_STATS>=2)
253 /* could add a running average size too, someday */
254 long int total_allocs; /* total # of alloc calls */
255 long int total_frees; /* total # of free calls */
256 char *smallest_file; /* file name of largest alloc */
257 int smallest_line; /* file line of largest alloc */
258 char *largest_file; /* file name of largest alloc */
259 int largest_line; /* file line of largest alloc */
260 #endif
263 /* keep track of memory allocation statistics */
264 static MEMSTATS mem_stats;
266 /* local prototypes */
267 static void mem_stats_init (void);
268 static void mem_stats_alloc (size_t nbytes, char *file, int line);
269 static void mem_stats_free (size_t nbytes);
271 #endif
274 /****************************************************************************/
275 void mem_init()
277 #if defined(MEM_RECLAIM)
278 num_nodes = 0;
279 poolno = 0;
280 memlist = NULL;
281 #endif
282 #if defined(MEM_STATS)
283 mem_stats_init();
284 #endif
285 leak_msg = FALSE;
289 #if defined(MEM_TAG)
290 /****************************************************************************/
291 /* return TRUE if pointer is non-null and has a valid tag */
292 static int mem_check_tag(MEMNODE *node)
294 int isOK = FALSE;
296 if (node != NULL)
297 if (node->tag == MEMTAG_VALUE)
298 isOK = TRUE;
299 return isOK;
302 #endif /* MEM_TAG */
305 /****************************************************************************/
306 void *pov_malloc(size_t size, char *file, int line, char *msg)
308 void *block;
309 size_t totalsize;
310 #if defined(MEM_HEADER)
311 MEMNODE *node;
312 #endif
314 #if defined(MEM_HEADER)
315 if (size == 0)
317 Error("Attempt to malloc zero size block (File: %s Line: %d).\n", file, line);
319 #endif
321 totalsize=size+NODESIZE; /* number of bytes allocated in OS */
323 block = (void *)MALLOC(totalsize);
325 if (block == NULL)
326 MAError(msg, size);
328 #if defined(MEM_HEADER)
329 node = (MEMNODE *) block;
330 #endif
332 #if defined(MEM_TAG)
333 node->tag = MEMTAG_VALUE;
334 #endif
336 #if defined(MEM_TRACE) || defined(MEM_STATS)
337 node->size = totalsize;
338 #endif
339 #if defined(MEM_TRACE)
340 node->file = file;
341 node->line = line;
342 #endif
344 #if defined(MEM_RECLAIM)
345 add_node(node);
346 #endif
348 #if defined(MEM_STATS)
349 mem_stats_alloc(totalsize, file, line);
350 #endif
352 return (void *)((char *)block + NODESIZE);
356 /****************************************************************************/
357 void *pov_calloc(size_t nitems, size_t size, char *file, int line, char *msg)
359 void *block;
360 size_t actsize;
361 size_t totalsize; /* number of bytes allocated in OS */
362 #if defined(MEM_HEADER)
363 MEMNODE *node;
364 #endif
366 actsize=nitems*size;
367 totalsize=actsize+NODESIZE;
369 #if defined(MEM_HEADER)
370 if (actsize == 0)
372 Error("Attempt to calloc zero size block (File: %s Line: %d).\n", file, line);
374 #endif
376 block = (void *)MALLOC(totalsize);
378 if (block == NULL)
379 MAError(msg, actsize);
381 memset(block, 0, totalsize);
383 #if defined(MEM_HEADER)
384 node = (MEMNODE *) block;
385 #endif
387 #if defined(MEM_TAG)
388 node->tag = MEMTAG_VALUE;
389 #endif
391 #if defined(MEM_TRACE) || defined(MEM_STATS)
392 node->size = totalsize;
393 #endif
394 #if defined(MEM_TRACE)
395 node->file = file;
396 node->line = line;
397 #endif
399 #if defined(MEM_RECLAIM)
400 add_node(node);
401 #endif
403 #if defined(MEM_STATS)
404 mem_stats_alloc(totalsize, file, line);
405 #endif
407 return (void *)((char *)block + NODESIZE);
411 /****************************************************************************/
412 void *pov_realloc(void *ptr, size_t size, char *file, int line, char *msg)
414 void *block;
415 #if defined(MEM_STATS)
416 size_t oldsize;
417 #endif
419 #if defined(MEM_HEADER)
420 MEMNODE *node;
421 #endif
423 #if defined(MEM_RECLAIM)
424 MEMNODE *prev;
425 MEMNODE *next;
427 #endif
429 if (size == 0)
431 if (ptr)
432 pov_free(ptr, file, line);
433 return NULL;
435 else if (ptr == NULL)
436 return pov_malloc(size, file, line, msg);
438 block = (void *)((char *)ptr - NODESIZE);
440 #if defined(MEM_HEADER)
441 node = (MEMNODE *) block;
442 #endif
444 #if defined(MEM_TAG)
445 if (node->tag != MEMTAG_VALUE)
446 Error("Attempt to realloc invalid block (File: %s Line: %d).\n", file, line);
448 node->tag = ~node->tag;
449 #endif
451 #if defined(MEM_RECLAIM)
452 prev = node->prev;
453 next = node->next;
454 #endif
456 block = (void *)REALLOC(block, NODESIZE + size);
458 if (block == NULL)
459 MAError(msg, size);
461 #if defined(MEM_STATS)
462 /* REALLOC does an implied FREE... */
463 oldsize = ((MEMNODE *)block)->size;
464 mem_stats_free(oldsize);
465 /* ...and an implied MALLOC... */
466 mem_stats_alloc(NODESIZE + size, file, line);
467 #endif
469 #if defined(MEM_HEADER)
470 node = (MEMNODE *) block;
471 #endif
473 #if defined(MEM_TAG)
474 node->tag = MEMTAG_VALUE;
475 #endif
477 #if defined(MEM_TRACE) || defined(MEM_STATS)
478 node->size = size + NODESIZE;
479 #endif
480 #if defined(MEM_TRACE)
481 node->file = file;
482 node->line = line;
483 #endif
485 #if defined(MEM_RECLAIM)
486 if (prev == NULL)
487 memlist = node;
488 else
489 prev->next = node;
490 if (node->next != NULL)
491 node->next->prev = node;
492 if (next != NULL)
493 next->prev = node;
494 #endif
496 return (void *)((char *)block + NODESIZE);
500 /****************************************************************************/
501 void pov_free(void *ptr, char *file, int line)
503 void *block;
505 #if defined(MEM_HEADER)
506 MEMNODE *node;
507 #endif
509 if (ptr == NULL)
510 Error("Attempt to free NULL pointer (File: %s Line: %d).\n", file, line);
512 block = (void *)((char *)ptr - NODESIZE);
514 #if defined(MEM_HEADER)
515 node = (MEMNODE *) block;
516 #endif
518 #if defined(MEM_TAG)
519 if (node->tag == ~MEMTAG_VALUE)
521 Warning(0.0, "Attempt to free already free'd block (File: %s Line: %d).\n", file, line);
522 return;
524 else if (node->tag != MEMTAG_VALUE)
526 Warning(0.0, "Attempt to free invalid block (File: %s Line: %d).\n", file, line);
527 return;
530 #endif
532 #if defined(MEM_RECLAIM)
533 remove_node(node);
534 #endif
536 #if defined(MEM_TAG)
537 /* do this After remove_node, so remove_node can check validity of nodes */
538 node->tag = ~node->tag;
539 #endif
541 #if defined(MEM_STATS)
542 mem_stats_free(((MEMNODE*)block)->size);
543 #endif
545 FREE(block);
549 /****************************************************************************/
550 /* Starts a new memory pool. The next mem_release() call will
551 only release memory allocated after this call. */
552 void mem_mark()
554 #if defined(MEM_RECLAIM)
555 poolno++;
556 #endif
560 /****************************************************************************/
561 /* Releases all unfree'd memory from current memory pool */
562 void mem_release(int LogFile)
564 #if defined(MEM_RECLAIM)
565 FILE *f = NULL;
566 MEMNODE *p, *tmp;
567 size_t totsize;
569 p = memlist;
570 totsize = 0;
572 #if defined(MEM_TRACE)
573 if (LogFile)
575 if (p != NULL && (p->poolno == poolno))
576 f = fopen(MEM_LOG_FNAME, APPEND_TXTFILE_STRING);
578 #endif /* MEM_TRACE */
580 while (p != NULL && (p->poolno == poolno))
582 #if defined(MEM_TRACE)
584 #if defined(MEM_TAG)
585 if (!mem_check_tag(p))
586 Debug_Info("mem_release(): Memory pointer corrupt!\n");
587 #endif /* MEM_TAG */
589 totsize += (p->size-NODESIZE);
590 if (LogFile)
592 if (!leak_msg)
594 Debug_Info("Memory leakage detected, see file '%s' for list\n",MEM_LOG_FNAME);
595 leak_msg = TRUE;
598 if (f != NULL)
599 fprintf(f, "File:%13s Line:%4d Size:%lu\n", p->file, p->line, (unsigned long)(p->size-NODESIZE));
601 #endif /* MEM_TRACE */
603 #if defined(MEM_STATS)
604 mem_stats_free(p->size);
605 #endif
607 tmp = p;
608 p = p->next;
609 remove_node(tmp);
610 FREE(tmp);
613 if (f != NULL)
614 fclose(f);
616 if (totsize > 0)
617 Debug_Info("%lu bytes reclaimed (pool #%d)\n", totsize, poolno);
619 if (poolno > 0)
620 poolno--;
622 #if defined(MEM_STATS)
623 /* reinitialize the stats structure for next time through */
624 mem_stats_init();
625 #endif
627 #endif /* MEM_RECLAIM */
631 /****************************************************************************/
632 /* Released all unfree'd memory from all pools */
633 void mem_release_all(int LogFile)
635 #if defined(MEM_RECLAIM)
636 FILE *f = NULL;
637 MEMNODE *p, *tmp;
638 size_t totsize;
640 Status_Info("Reclaiming memory\n");
642 p = memlist;
643 totsize = 0;
645 #if defined(MEM_TRACE)
646 if (LogFile)
648 if (p != NULL)
649 f = fopen(MEM_LOG_FNAME, APPEND_TXTFILE_STRING);
651 #endif
653 while (p != NULL)
655 #if defined(MEM_TRACE)
657 #if defined(MEM_TAG)
658 if (!mem_check_tag(p))
659 Debug_Info("mem_release_all(): Memory pointer corrupt!\n");
660 #endif /* MEM_TAG */
662 totsize += (p->size-NODESIZE);
663 if (LogFile)
665 if (!leak_msg)
667 Debug_Info("Memory leakage detected, see file '%s' for list\n",MEM_LOG_FNAME);
668 leak_msg = TRUE;
671 if (f != NULL)
672 fprintf(f, "File:%13s Line:%4d Size:%lu\n", p->file, p->line, (unsigned long)(p->size-NODESIZE));
674 #endif
676 #if defined(MEM_STATS)
677 /* This is after we have printed stats, and this may slow us down a little, */
678 /* so we may want to simply re-initialize the mem-stats at the end of this loop. */
679 mem_stats_free(p->size);
680 #endif
682 tmp = p;
683 p = p->next;
684 remove_node(tmp);
685 FREE(tmp);
688 if (f != NULL)
689 fclose(f);
691 if (totsize > 0)
692 Debug_Info("\n%lu bytes reclaimed\n", totsize);
694 poolno = 0;
695 #endif
697 #if defined(MEM_STATS)
698 /* reinitialize the stats structure for next time through */
699 mem_stats_init();
700 #endif
705 /****************************************************************************/
706 #if defined(MEM_RECLAIM)
707 /* Adds a new node to the 'allocated' list */
708 static void add_node(MEMNODE *node)
711 #if defined(MEM_TAG)
712 if (!mem_check_tag(node))
713 Debug_Info("add_node(): Memory pointer corrupt!\n");
714 #endif /* MEM_TAG */
716 if (memlist == NULL)
718 memlist = node;
719 node->poolno = poolno;
720 node->prev = NULL;
721 node->next = NULL;
722 num_nodes = 0;
724 else
726 memlist->prev = node;
727 node->poolno = poolno;
728 node->prev = NULL;
729 node->next = memlist;
730 memlist = node;
732 num_nodes++;
736 /****************************************************************************/
737 /* Detatches a node from the 'allocated' list but doesn't free it */
738 static void remove_node(MEMNODE *node)
741 #if defined(MEM_TAG)
742 if (!mem_check_tag(node))
743 Debug_Info("remove_node(): Memory pointer corrupt!\n");
744 #endif /* MEM_TAG */
746 num_nodes--;
747 if (node->prev != NULL)
748 node->prev->next = node->next;
750 if (node->next != NULL)
751 node->next->prev = node->prev;
753 if (memlist == node)
755 #if defined(MEM_TAG)
756 /* check node->next if it is non-null, to insure it is safe to assign. */
757 /* if it is null, it is safe since it is the last in the list. */
758 if (node->next)
759 if (!mem_check_tag(node->next))
760 Debug_Info("remove_node(): memlist pointer corrupt!\n");
761 #endif /* MEM_TAG */
763 memlist = node->next;
768 #endif /* MEM_RECLAIM */
771 /****************************************************************************/
772 /* A strdup routine that uses POV_MALLOC */
773 /****************************************************************************/
774 char *pov_strdup(char *s)
776 char *New;
778 New=(char *)POV_MALLOC(strlen(s)+1,s);
779 strcpy(New,s);
780 return (New);
783 /****************************************************************************/
784 /* A memmove routine for those systems that don't have one */
785 /****************************************************************************/
787 void *pov_memmove (void *dest, void *src, size_t length)
789 char *csrc =(char *)src;
790 char *cdest=(char *)dest;
792 if (csrc < cdest && csrc + length >= cdest)
794 size_t size = cdest - csrc;
796 while (length > 0)
798 memcpy(cdest + length - size, csrc + length - size, size);
800 length -= size;
802 if (length < size)
803 size = length;
806 /* I'm not sure if this is needed, but my docs on memcpy say the regions
807 * can't overlap, so theoretically we need to special case this. If you
808 * don't think it's necessary, you can just comment this part out.
810 else if (cdest < csrc && cdest + length >= csrc)
812 char *new_dest = cdest;
813 size_t size = csrc - cdest;
815 while (length > 0)
817 memcpy(new_dest, csrc, length);
819 new_dest += size;
820 csrc += size;
821 length -= size;
823 if (length < size)
824 size = length;
827 else
829 memcpy(cdest, csrc, length);
832 return cdest;
836 /****************************************************************************/
837 /* Memory Statistics gathering routines */
838 /****************************************************************************/
840 #if defined(MEM_STATS)
842 /****************************************************************************/
843 static void mem_stats_init()
845 mem_stats.smallest_alloc = 65535; /* Must be an unsigned number */
846 mem_stats.largest_alloc = 0;
847 mem_stats.current_mem_usage = 0;
848 mem_stats.largest_mem_usage = 0;
849 #if (MEM_STATS>=2)
850 mem_stats.total_allocs = 0;
851 mem_stats.total_frees = 0;
852 mem_stats.largest_file = "none";
853 mem_stats.largest_line = -1;
854 mem_stats.smallest_file = "none";
855 mem_stats.smallest_line = -1;
856 #endif
859 /****************************************************************************/
860 /* update appropriate fields when an allocation takes place */
861 static void mem_stats_alloc(size_t nbytes, char *file, int line)
863 /* update the fields */
864 if ((mem_stats.smallest_alloc<0) || (nbytes<mem_stats.smallest_alloc))
866 mem_stats.smallest_alloc = nbytes;
867 #if (MEM_STATS>=2)
868 mem_stats.smallest_file = file;
869 mem_stats.smallest_line = line;
870 #endif
873 if (nbytes>mem_stats.largest_alloc)
875 mem_stats.largest_alloc = nbytes;
876 #if (MEM_STATS>=2)
877 mem_stats.largest_file = file;
878 mem_stats.largest_line = line;
879 #endif
882 #if (MEM_STATS>=2)
883 mem_stats.total_allocs++;
884 #endif
886 mem_stats.current_mem_usage += nbytes;
888 if (mem_stats.current_mem_usage>mem_stats.largest_mem_usage)
890 mem_stats.largest_mem_usage = mem_stats.current_mem_usage;
895 /****************************************************************************/
896 /* update appropriate fields when a free takes place */
897 static void mem_stats_free(size_t nbytes)
899 /* update the fields */
900 mem_stats.current_mem_usage -= nbytes;
901 #if (MEM_STATS>=2)
902 mem_stats.total_frees++;
903 #endif
906 /****************************************************************************/
907 /* Level 1 */
909 /****************************************************************************/
910 size_t mem_stats_smallest_alloc()
912 return mem_stats.smallest_alloc;
914 /****************************************************************************/
915 size_t mem_stats_largest_alloc()
917 return mem_stats.largest_alloc;
919 /****************************************************************************/
920 size_t mem_stats_current_mem_usage()
922 return mem_stats.current_mem_usage;
924 /****************************************************************************/
925 size_t mem_stats_largest_mem_usage()
927 return mem_stats.largest_mem_usage;
930 /****************************************************************************/
931 /* Level 2 */
933 #if (MEM_STATS>=2)
935 /****************************************************************************/
936 char *mem_stats_smallest_file()
938 return mem_stats.smallest_file;
940 /****************************************************************************/
941 int mem_stats_smallest_line()
943 return mem_stats.smallest_line;
945 /****************************************************************************/
946 char *mem_stats_largest_file()
948 return mem_stats.largest_file;
950 /****************************************************************************/
951 int mem_stats_largest_line()
953 return mem_stats.largest_line;
955 /****************************************************************************/
956 long int mem_stats_total_allocs()
958 return mem_stats.total_allocs;
960 /****************************************************************************/
961 long int mem_stats_total_frees()
963 return mem_stats.total_frees;
966 #endif
968 #endif /* MEM_STATS */