source: git/Singular/mmheap.c @ a70441f

spielwiese
Last change on this file since a70441f was 416465, checked in by Olaf Bachmann <obachman@…>, 24 years ago
* bug-fixes from work with Thomas git-svn-id: file:///usr/local/Singular/svn/trunk@3826 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 19.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: mmheap.c,v 1.16 1999-11-15 17:20:24 obachman Exp $ */
5#include <stdio.h>
6#include "mod2.h"
7#include "structs.h"
8#include "mmpage.h"
9#include "mmemory.h"
10#include "mmprivate.h"
11
12
13/*****************************************************************
14 *
15 * Implementation of basic routines
16 *
17 *****************************************************************/
18#ifndef HEAP_DEBUG
19void mmDestroyHeap(memHeap *heap)
20#else
21static int mmPrintHeapError(char* msg, void* addr, memHeap heap,
22                            const char* fn, int l);
23void mmDebugDestroyHeap(memHeap *heap, const char* file, int line)
24#endif
25{
26#ifndef HEAP_DEBUG
27  mmClearHeap(*heap);
28#else
29  mmDebugClearHeap(*heap, file, line);
30#endif
31  FreeSizeOf(*heap, ip_memHeap);
32  *heap = NULL;
33}
34
35memHeapPage mmAllocNewHeapPage(memHeap heap)
36{
37#ifndef HAVE_AUTOMATIC_GC
38  if (heap->size > MAX_HEAP_CHUNK_SIZE)
39  {
40    heap->current = mmMallocFromSystem(heap->size);
41    *((void**) heap->current) = NULL;
42    heap->pages = (void*) ((int)heap->pages + 1);
43#ifdef MDEBUG
44    mmDBInitNewHeapPage(heap, NULL);
45#endif
46    return NULL;
47  }
48  else
49#endif /* ! HAVE_AUTOMATIC_GC */
50  {
51    memHeapPage newpage;
52    int i = 1, n = SIZE_OF_HEAP_PAGE / heap->size;
53    void* tmp;
54    if (n > 0) newpage = mmGetPage();
55    else newpage = mmVallocFromSystem(heap->size + SIZE_OF_HEAP_PAGE_HEADER);
56   
57    assume(mmIsAddrPageAligned((void*) newpage));
58
59#ifndef HAVE_AUTOMATIC_GC
60    newpage->next = heap->pages;
61    heap->pages = newpage;
62    heap->current = (void*) (((char*)newpage) + SIZE_OF_HEAP_PAGE_HEADER);
63    tmp = heap->current;
64#else
65    newpage->used_blocks = 0;
66    newpage->current = (void*) (((char*)newpage) + SIZE_OF_HEAP_PAGE_HEADER);
67    tmp = newpage->current;
68#endif   /* ! HAVE_AUTOMATIC_GC */ 
69
70    while (i < n)
71    {
72      *((void**)tmp) = (void*) (((char*)tmp) + heap->size);
73      tmp = *((void**)tmp);
74      i++;
75    }
76    *((void**)tmp) = NULL;
77#ifdef MDEBUG
78    mmDBInitNewHeapPage(heap, newpage);
79#endif
80    return newpage;
81  }
82}
83
84#ifndef HAVE_AUTOMATIC_GC
85memHeap mmCreateHeap(size_t size)
86{
87  memHeap heap = (memHeap) AllocSizeOf(ip_memHeap);
88  heap->current = NULL;
89  heap->pages = NULL;
90  heap->size = size;
91  heap->last_gc= NULL;
92  return heap;
93}
94
95#ifndef HEAP_DEBUG
96void mmClearHeap(memHeap heap)
97{
98  memHeapPage page, next_page;
99
100  page = heap->pages;
101
102#if 0 
103  while(page != NULL)
104  {
105    next_page = page->next;
106    mmFreePage((void*) page);
107    page = next_page;
108  }
109#endif
110  heap->current = NULL;
111  heap->pages = NULL;
112  heap->last_gc = NULL;
113}
114#else
115void mmDebugClearHeap(memHeap heap, const char* file, int line)
116{
117  mmCheckHeap(heap);
118  mmGarbageCollectHeap(heap, 1);
119  if (heap->current != NULL)
120  {
121    mmPrintHeapError("ClearHeap: Heap not empty", 0, heap, file, line);
122  }
123}
124#endif
125
126void mmMergeHeap(memHeap into, memHeap what)
127{
128  void* last;
129 
130  assume(into != NULL && what != NULL && into->size == what->size);
131
132  if (into == what) return;
133#ifdef MDEBUG
134  mmDBSetHeapsOfBlocks(what, into);
135#endif 
136
137  if (into->size > MAX_HEAP_CHUNK_SIZE)
138  {
139    into->pages = (void*) ((int) what->pages + (int) into->pages);
140  }
141  else
142  {
143    if (what->pages != NULL)
144    {
145      last = mmListLast(what->pages);
146      *((void**) last) = into->pages;
147      into->pages = what->pages;
148    }
149  }
150
151  if (what->current != NULL)
152  {
153    last = mmListLast(what->current);
154    *((void**) last) = into->current;
155    into->current = what->current;
156  }
157 
158  what->pages = NULL;
159  what->current = NULL;
160
161  mmCheckHeap(into);
162}
163
164static void mmRemoveHeapBlocksOfPage(memHeap heap, memHeapPage hpage)
165{
166  void *prev = NULL, *new_current = NULL, *current = heap->current;
167  int nblocks = SIZE_OF_HEAP_PAGE / heap->size;
168 
169#ifdef HAVE_ASSUME
170  int l = mmListLength(current);
171#endif
172  assume(nblocks > 0);
173
174  while (mmIsAddrOnPage(current, hpage))
175  {
176#ifdef MDEBUG
177    mmTakeOutDBMCB((DBMCB*) current);
178#endif   
179    if (--(nblocks) == 0) 
180    {
181      new_current = *((void**) current);
182      goto Finish;
183    }
184    current = *((void**) current);
185  }
186 
187  new_current = current;
188 
189  while (1)
190  {
191    assume(mmListLength(new_current) == 
192           l - (SIZE_OF_HEAP_PAGE / heap->size) + nblocks);
193    prev = current;
194    current = *((void**) current);
195   
196    while (! mmIsAddrOnPage(current, hpage))
197    {
198      prev = current;
199      current = *((void**) current);
200    }
201   
202#ifdef MDEBUG
203    mmTakeOutDBMCB((DBMCB*) current);
204#endif   
205    if (--(nblocks) == 0) goto Finish;
206
207    current = *((void**) current);
208    while (mmIsAddrOnPage(current, hpage))
209    {
210#ifdef MDEBUG
211      mmTakeOutDBMCB((DBMCB*) current);
212#endif   
213      if (--(nblocks) == 0) goto Finish;
214      current = *((void**) current);
215    }
216    *((void**) prev) = current;
217  }
218
219  Finish:
220  heap->current = new_current;
221  if (prev != NULL)
222    *((void**) prev) = *((void**) current);
223  heap->pages = mmRemoveFromList(heap->pages, hpage);
224  mmFreePage(hpage);
225  assume(mmListLength(heap->current) == l -  (SIZE_OF_HEAP_PAGE / heap->size));
226  mmCheckHeap(heap);
227}
228
229void mmGarbageCollectHeap(memHeap heap, int strict)
230{
231  if (heap->size > MAX_HEAP_CHUNK_SIZE)
232  {
233    void* current = heap->current;
234    void* next;
235    while (current != NULL)
236    {
237      next = *((void**) current);
238#ifdef MDEBUG
239      mmTakeOutDBMCB((DBMCB*) current);
240#endif     
241      mmFreeToSystem(current, heap->size);
242      current = next;
243      heap->pages = (void*) ((int) heap->pages - 1);
244    }
245    heap->current = NULL;
246    heap->last_gc = NULL;
247    return;
248  }
249
250  if (! strict && heap->current == heap->last_gc)
251  {
252    return;
253  }
254  else
255  {
256    memHeapPage hpage = heap->pages;
257    void* current = heap->current;
258    int nblocks = SIZE_OF_HEAP_PAGE / (heap->size);
259 
260    assume(heap != NULL);
261    mmCheckHeap(heap);
262
263    while (hpage != NULL)
264    {
265      hpage->counter = nblocks;
266      hpage = hpage->next;
267    }
268
269    while (current != NULL)
270    {
271      hpage = mmGetHeapPageOfAddr(current);
272      current = *((void**) current);
273      if (--(hpage->counter) == 0)
274        mmRemoveHeapBlocksOfPage(heap, hpage);
275    }
276    heap->last_gc = heap->current;
277  }
278}
279int mmNumberOfAllocatedHeapPages(memHeap heap)
280{
281  return mmListLength(heap->pages);
282}
283
284int mmNumberOfFreeHeapBlocks(memHeap heap)
285{
286  return mmListLength(heap->current);
287}
288
289#else /* HAVE_AUTOMATIC_GC */
290
291int mmNumberOfAllocatedHeapPages(memHeap heap)
292{
293  return mmGListLength(heap->last_page, 
294                       (void*) &(heap->last_page->prev) - (void*)heap->last_page);
295}
296
297int mmNumberOfFreeHeapBlocks(memHeap heap)
298{
299  int n = 0;
300  memHeapPage page;
301 
302  if (heap->current_page == mmZeroPage) return 0;
303 
304  page = heap->last_page;
305  do
306  {
307    n += mmListLength(page->current);
308    if (page == heap->current_page) break;
309    page = page->prev;
310  }
311  while (page != NULL);
312 
313  return n;
314}
315                       
316
317memHeapPage mmGetNewCurrentPage(memHeap heap)
318{
319  assume(heap->current_page->current == NULL);
320  if (heap->current_page == mmZeroPage)
321  {
322    memHeapPage new_page = mmAllocNewHeapPage(heap);
323    new_page->next = mmZeroPage;
324    new_page->prev = heap->last_page;
325    if (heap->last_page != NULL)
326      heap->last_page->next = new_page;
327    heap->current_page = new_page;
328    heap->last_page = new_page;
329  }
330  else 
331  {
332    heap->current_page->used_blocks = 1;
333    if (heap->current_page != heap->last_page)
334    {
335      assume(heap->current_page->next->current != NULL);
336      heap->current_page = heap->current_page->next;
337    }
338    else
339    {
340      memHeapPage new_page = mmAllocNewHeapPage(heap);
341      new_page->next = mmZeroPage;
342      new_page->prev = heap->last_page;
343      new_page->prev->next = new_page;
344      heap->current_page = new_page;
345      heap->last_page = new_page;
346    }
347  }
348#ifdef HEAP_DEBUG
349  if (mm_HEAP_DEBUG > 1) mmDebugCheckHeap(heap, __FILE__, __LINE__);
350#endif
351  return heap->current_page;
352}
353
354
355static void mmTakeOutHeapPage(memHeapPage page, memHeap heap)
356{
357  if (heap->current_page == page) heap->current_page = page->next;
358  if (heap->last_page == page) heap->last_page = page->prev;
359  if (page->prev != NULL) page->prev->next = page->next;
360  if (page->next != mmZeroPage) page->next->prev = page->prev;
361}
362
363static void mmInsertHeapPage(memHeapPage after, memHeapPage page, memHeap heap)
364{
365  if (after == NULL)
366  {
367    assume(heap->current_page == mmZeroPage);
368    page->next = mmZeroPage;
369    page->prev = NULL;
370    heap->current_page = page;
371    heap->last_page = page;
372  }
373  else
374  {
375    if (after == heap->last_page) heap->last_page = page;
376    page->prev = after;
377    page->next = after->next;
378    if (after->next != mmZeroPage) after->next->prev = page;
379    after->next = page;
380    if (heap->current_page == mmZeroPage && page->current != NULL)
381      heap->current_page = page;
382  }
383}
384
385void mmRearrangeHeapPages(memHeapPage page, void* addr, memHeap heap)
386{
387  assume(page->used_blocks == 0);
388  if (page->current != NULL)
389  {
390    // all blocks of page are now collected
391    // get heap
392    mmTakeOutHeapPage(page, heap);
393    // page can be freed
394    mmFreePage(page);
395  }
396  else
397  {
398    // page was full
399    if (heap->max_blocks == 1) 
400    {
401      mmTakeOutHeapPage(page, heap);
402      mmFreePage(page);
403    }
404    else
405    {
406      page->current = addr;
407      page->used_blocks = heap->max_blocks - 1;
408      *((void**)addr) = NULL;
409      mmTakeOutHeapPage(page, heap);
410#if defined(PAGE_BEFORE_CURRENT)
411      if (heap->current_page->prev != NULL)
412        mmInsertHeapPage(heap->current_page->prev, page);
413      else
414        mmInsertHeapPage(heap->current_page, page, heap);
415      heap->current_page = page;
416#elsif defined(PAGE_AFTER_CURRENT)
417      mmInsertHeapPage(heap->current_page, page, heap);
418#else
419      mmInsertHeapPage(heap->last_page, page, heap);
420#endif   
421    }
422  }
423#ifdef HEAP_DEBUG
424  if (mm_HEAP_DEBUG > 1) mmDebugCheckHeap(heap, __FILE__, __LINE__);
425#endif
426}
427
428
429memHeap mmCreateHeap(size_t size)
430{
431  memHeap heap = (memHeap) AllocSizeOf(ip_memHeap);
432  heap->current_page = mmZeroPage;
433  heap->last_page = NULL;
434  heap->size = size;
435  heap->max_blocks = SIZE_OF_HEAP_PAGE / size;
436  if (heap->max_blocks == 0) heap->max_blocks = 1;
437  return heap;
438}
439
440#ifndef HEAP_DEBUG
441void mmClearHeap(memHeap heap)
442#else
443void mmDebugClearHeap(memHeap heap, const char* file, int line)
444#endif
445{
446#ifdef HEAP_DEBUG 
447  mmCheckHeap(heap);
448  if (heap->current_page != mmZeroPage)
449  {
450    mmPrintHeapError("ClearHeap: Heap not empty", NULL, heap, file, line);
451  }
452#endif
453}
454
455void  mmMergeHeap(memHeap into, memHeap what)
456{/* TBC */}
457
458#endif /* HAVE_AUTOMATIC_GC */
459 
460#ifdef HEAP_DEBUG
461int mm_HEAP_DEBUG = HEAP_DEBUG;
462
463static int mmPrintHeapError(char* msg, void* addr, memHeap heap,
464                            const char* fn, int l)
465{
466  fprintf(stderr, "\n%s: occured for addr:%p heap:%p of size %ld in %s:%d\n",
467          msg, addr, (void*) heap, heap->size, fn, l);
468  assume(0);
469  return 0;
470}
471
472#ifndef HAVE_AUTOMATIC_GC
473static int mmDebugCheckSingleHeapAddr(void* addr, memHeap heap,
474                                      const char* fn, int l)
475{
476  void* page;
477  memHeapPage hpage;
478 
479  if (heap == NULL)
480  {
481    fprintf(stderr, "NULL heap in %s:%d\n", fn, l);
482    assume(0);
483    return 0;
484  }
485
486  if (addr == NULL)
487    return mmPrintHeapError("NULL addr", addr, heap, fn, l);
488
489  if (heap->size > MAX_HEAP_CHUNK_SIZE) return 1;
490
491  if (! mmIsNotAddrOnFreePage(addr))
492    return mmPrintHeapError("Addr on freed page", addr, heap, fn, l);
493 
494  page = mmGetPageOfAddr(addr);
495 
496  if (! mmIsAddrOnList(page, heap->pages))
497    return mmPrintHeapError("addr not on heap page", addr, heap, fn, l);
498
499  if ( (((long) (((char*) addr) - ((char*) page + SIZE_OF_HEAP_PAGE_HEADER)))
500        % heap->size) != 0)
501    return mmPrintHeapError("addr unaligned within heap", addr, heap, fn, l);
502  hpage = (memHeapPage) page;
503  return 1;
504}
505
506
507static int mmDebugCheckHeapAddrContainment(void* addr, memHeap heap, int flag,
508                                           const char* fn, int l)
509{
510  if (flag == MM_HEAP_ADDR_FREE_FLAG)
511  {
512    if (! mmIsAddrOnList(addr, heap->current))
513      return mmPrintHeapError("addr not on heap free list",
514                              addr, heap, fn, l);
515  }
516  else if (flag == MM_HEAP_ADDR_USED_FLAG)
517  {
518    if (mmIsAddrOnList(addr, heap->current))
519      return mmPrintHeapError("used addr on heap free list",
520                              addr, heap, fn, l);
521  }
522  return 1;
523}
524
525int mmDebugCheckHeap(memHeap heap, const char* fn, int l)
526{
527  void* p;
528 
529  if (heap->size <= MAX_HEAP_CHUNK_SIZE && mmListHasCycle(heap->pages))
530    return mmPrintHeapError("heap pages list has cycles",
531                            NULL, heap, fn, l);
532
533  if (mmListHasCycle(heap->current))
534    return mmPrintHeapError("heap current list has cycles",
535                            NULL, heap, fn, l);
536   
537  p = heap->current;
538  while (p != NULL)
539  {
540    if (!mmDebugCheckSingleHeapAddr(p, heap, fn, l)  ||
541        !mmDebugCheckHeapAddrContainment(p, heap, MM_HEAP_ADDR_FREE_FLAG,
542                                         fn, l))
543      return 0;
544    p = *((void**) p);
545  }
546  return 1;
547}
548
549
550#else /* HAVE_AUTOMATIC_GC */
551
552
553static int mmDebugCheckSingleHeapAddr(void* addr, memHeap heap,
554                                      const char* fn, int l)
555{
556  memHeapPage page;
557 
558  if (heap == NULL)
559  {
560    fprintf(stderr, "NULL heap in %s:%d\n", fn, l);
561    assume(0);
562    return 0;
563  }
564
565  if (addr == NULL)
566    return mmPrintHeapError("NULL addr", addr, heap, fn, l);
567
568  if (! mmIsNotAddrOnFreePage(addr))
569    return mmPrintHeapError("Addr on freed page", addr, heap, fn, l);
570
571  page = mmGetPageOfAddr(addr);
572 
573  if (! mmIsAddrOnGList(page, heap->last_page, (void*) &page->prev - (void*) page))
574    return mmPrintHeapError("addr not on page of this heap", 
575                            addr, heap, fn, l);
576
577  if ( (((long) (((char*) addr) - ((char*) page + SIZE_OF_HEAP_PAGE_HEADER)))
578        % heap->size) != 0)
579    return mmPrintHeapError("addr unaligned within heap", addr, heap, fn, l);
580  return 1;
581}
582
583
584static int mmDebugCheckHeapAddrContainment(void* addr, memHeap heap, int flag,
585                                           const char* fn, int l)
586{
587  memHeapPage page = heap->last_page;
588  int where;
589  if (heap->current_page != mmZeroPage) where = 1;
590  else where = -1;
591 
592 
593  while (page != NULL && mmGetPageOfAddr(addr) != page) 
594  {
595    if (page == heap->current_page) where = -1;
596    page = page->prev;
597  }
598
599  if (page == NULL) mmPrintHeapError("addr not from heap", addr, heap, fn, l);
600 
601  if (flag == MM_HEAP_ADDR_FREE_FLAG)
602  {
603    if (where == -1 || ! mmIsAddrOnList(addr, heap->current_page->current))
604      return mmPrintHeapError("free addr not on a page free list",
605                              addr, heap, fn, l);
606  }
607  else if (flag == MM_HEAP_ADDR_USED_FLAG)
608  {
609    if (where == 1 &&  mmIsAddrOnList(addr, heap->current_page->current))
610      return mmPrintHeapError("used addr on a page free list",
611                              addr, heap, fn, l);
612  }
613  return 1;
614}
615
616int mmDebugCheckHeap(memHeap heap, const char* fn, int l)
617{
618  void* p;
619  int where;
620  memHeapPage page;
621 
622  if (heap->last_page == NULL)
623  {
624    if (heap->current_page != mmZeroPage)
625      return mmPrintHeapError("last_page out of sunc", NULL, heap, fn, l);
626    return 1;
627  }
628 
629  if (heap->last_page != mmGetPageOfAddr(heap->last_page))
630    return mmPrintHeapError("last_page not page aligned", heap->last_page,
631                            heap, fn, l);
632
633  if (heap->current_page != mmZeroPage && 
634      mmGetPageOfAddr(heap->current_page) != heap->current_page)
635    return mmPrintHeapError("current_page not page aligned", 
636                            heap->current_page,
637                            heap, fn, l);
638   
639
640  if (heap->last_page->next != mmZeroPage) 
641    return mmPrintHeapError("last_page out of sunc", NULL, heap, fn, l);
642
643  /* check page list for cycles */
644  if (mmGListHasCycle(heap->last_page, (void*) &page->prev - (void*) page))
645    return mmPrintHeapError("prev chain of heap has cycles", NULL, heap, fn,l);
646  page = heap->last_page;
647  while (page->prev != NULL) page = page->prev;
648  if (mmGListHasCycle(heap->last_page, (void*) &page->next - (void*) page))
649    return mmPrintHeapError("next chain of heap has cycles", NULL, heap, fn,l);
650
651  /* check prev/next relations of pages */
652  page = heap->last_page;
653  do
654  {
655    if (page != mmGetPageOfAddr(page))
656      return mmPrintHeapError("page not aligned", page, heap, fn, l);
657    if (page->prev != NULL && page->prev->next != page)
658      return mmPrintHeapError("page list damaged (prev)", page, heap, fn, l);
659    if (page->next != mmZeroPage && page->next->prev != page)
660      return mmPrintHeapError("page list damaged (next)", page, heap, fn, l);
661    page = page->prev;
662  }
663  while (page != NULL);
664
665  /* check that current_page is on list of pages */
666  if (heap->current_page != mmZeroPage && 
667      ! mmIsAddrOnGList(heap->current_page, heap->last_page, 
668                        (void*) &page->prev - (void*) page))
669    return mmPrintHeapError("current_page not in page list", 
670                            heap->current_page, heap, fn, l);
671
672  /* now check single pages */
673  page = heap->last_page;
674  if (heap->current_page != mmZeroPage) where = 1;
675  else where = -1;
676  while (page != NULL)
677  {
678    if (page == heap->current_page) where = 0;
679    if (where > 0 && page->used_blocks <= 0) 
680      return mmPrintHeapError("used_blocks of page <= 0", page, heap, fn, l);
681
682    if (where >= 0)
683    {
684      if (mmListHasCycle(page->current))
685        return mmPrintHeapError("current of page has cycle", page, heap, fn, l);
686
687      if (heap->max_blocks - page->used_blocks != mmListLength(page->current))
688      return mmPrintHeapError("used_blocks of fpage out of sync", 
689                              page, heap, fn, l);
690    }
691    else
692    {
693      if (page->used_blocks != 1)
694        return mmPrintHeapError("used_blocks of upage not 1", 
695                                page, heap, fn, l); 
696    }
697   
698    if (mm_HEAP_DEBUG > 2 && where >= 0)
699    {
700      p = page->current;
701      if (mmListHasCycle(p))
702        return mmPrintHeapError("current list of fpage has cycle", page,
703                                heap, fn, l);
704      while (p != NULL)
705      {
706        if (mmGetPageOfAddr(p) != page)
707          return mmPrintHeapError("addr not on heap page", p, heap, fn, l);
708        p = *((void**) p);
709      }
710    }
711    if (where == 0) where = -1;
712    page = page->prev;
713  }
714  return 1;
715}
716#endif /* ! HAVE_AUTOMATIC_GC */
717
718
719int mmDebugCheckHeapAddr(void* addr, memHeap heap, int flag,
720                         const char* fn, int l)
721{
722  if (mm_HEAP_DEBUG > 2 && ! mmDebugCheckHeap(heap, fn, l)) return 0;
723
724  if (! mmDebugCheckSingleHeapAddr(addr, heap, fn, l)) return 0;
725
726  return mmDebugCheckHeapAddrContainment(addr, heap, flag, fn, l);
727}
728 
729void * mmDebugAllocHeap(memHeap heap, const char* fn, int l)
730{
731  void* res;
732 
733  if (mm_HEAP_DEBUG > 1 && ! mmDebugCheckHeap(heap, fn, l))
734    return NULL;
735
736  _mmAllocHeap(res, heap, void*);
737
738  if (mm_HEAP_DEBUG > 2)
739    mmDebugCheckHeapAddr(res, heap, MM_HEAP_ADDR_USED_FLAG, fn, l);
740
741  return res;
742}
743 
744void  mmDebugFreeHeap(void* addr, memHeap heap, const char* fn, int l)
745{
746  if (mm_HEAP_DEBUG > 0)
747    mmDebugCheckHeapAddr(addr, heap, MM_HEAP_ADDR_USED_FLAG, fn, l);
748 
749  _mmFreeHeap(addr, heap);
750
751  if (mm_HEAP_DEBUG > 2)
752    mmDebugCheckHeapAddr(addr, heap, MM_HEAP_ADDR_FREE_FLAG, fn, l);
753}
754
755#endif /* HEAP_DEBUG */
Note: See TracBrowser for help on using the repository browser.