source: git/Singular/mmcheck.c @ 416465

spielwiese
Last change on this file since 416465 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: 14.9 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: mmcheck.c,v 1.17 1999-11-15 17:20:23 obachman Exp $ */
5
6/*
7* ABSTRACT: several checking routines to help debugging the memory subsystem
8*/
9
10#define _POSIX_SOURCE 1
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include "mod2.h"
16
17#ifdef MDEBUG
18
19#include "mmemory.h"
20#include "mmprivate.h"
21#include "mmpage.h"
22#ifdef MTRACK
23#include "mmbt.h"
24#endif
25
26DBMCB mm_theDBused;
27DBMCB mm_theDBfree;
28
29void * mm_maxAddr = NULL;
30void * mm_minAddr = NULL;
31
32/* int mm_MDEBUG = MDEBUG; */
33int mm_MDEBUG = 0;
34
35int mm_markCurrentUsage = 0;
36int mm_referenceWatch = 0;
37
38/**********************************************************************
39 *
40 * Auxillary routines
41 *
42 **********************************************************************/
43
44void mmMoveDBMCB ( pDBMCB from, pDBMCB to, DBMCB * what )
45{
46  what->prev->next = what->next;
47  if ( what->next != NULL )
48    what->next->prev = what->prev;
49  what->prev = to;
50  what->next = to->next;
51  if (to->next!=NULL)
52    to->next->prev=what;
53  to->next = what;
54}
55
56void mmMoveDBMCBInto ( pDBMCB to, pDBMCB what )
57{
58  if (to->next !=NULL)
59  {
60    what->next = to->next;
61    what->next->prev = what;
62  }
63  to->next = what;
64  what->prev = to;
65}
66
67void mmTakeOutDBMCB ( pDBMCB what )
68{
69  what->prev->next = what->next;
70  if ( what->next != NULL )
71    what->next->prev = what->prev;
72}
73
74#ifndef HAVE_AUTOMATIC_GC
75void mmDBSetHeapsOfBlocks(memHeap fromheap, memHeap toheap)
76{
77
78  memHeapPage pages = fromheap->pages;
79  int nblocks = SIZE_OF_HEAP_PAGE / toheap->size;
80  int i;
81
82  assume(fromheap->size == toheap->size);
83  while (pages != NULL)
84  {
85    DBMCB *what = (DBMCB*) (((char*) pages) + SIZE_OF_HEAP_PAGE_HEADER);
86
87    for (i=0; i<nblocks; i++)
88    {
89      what->heap = toheap;
90      what = (DBMCB*) (((char*) what)  + toheap->size);
91    }
92    pages = pages->next;
93  }
94}
95#endif
96
97void mmDBInitNewHeapPage(memHeap heap, memHeapPage page)
98{
99#ifndef HAVE_AUTOMATIC_GC
100  DBMCB* what = (DBMCB*) heap->current;
101#else
102  DBMCB* what =  (DBMCB*) page->current;
103#endif
104 
105  DBMCB* prev = NULL;
106  size_t size = SizeFromRealSize(heap->size);
107
108  if (mm_minAddr == 0 || mm_minAddr > (void*) what)
109    mm_minAddr = (void*) what;
110
111  while (what != NULL)
112  {
113    memset(&(what->next), 0, sizeof(DBMCB) - sizeof(void*));
114    mmFillDBMCB(what, size, heap, MM_FREEFLAG, __FILE__, __LINE__);
115    mmMoveDBMCBInto(&mm_theDBfree, what);
116    prev = what;
117    what = *((void**) what);
118  }
119
120  if (mm_maxAddr == 0 || mm_maxAddr < (void*) prev)
121    mm_maxAddr = (void*) prev;
122}
123
124static int mmPrintDBMCB ( DBMCB * what, char* msg , int given_size)
125{
126  (void)fprintf( stderr, "warning: %s\n", msg );
127  (void)fprintf( stderr, "block %p allocated in: %s:%d ",
128                 &(what->data),
129                 what->allocated_fname, what->freed_lineno );
130#ifdef MTRACK
131  mmDBPrintThisStack(stderr, what, MM_PRINT_ALL_STACK, 0);
132#endif
133
134  if ((what->flags & MM_FREEFLAG) && what->freed_fname != NULL)
135  {
136    (void)fprintf( stderr, "freed in: %s:%d ",
137                   what->freed_fname, what->freed_lineno );
138#ifdef MTRACK_FREE
139    mmDBPrintThisStack(what, MM_PRINT_ALL_STACK, 1);
140#endif
141  }
142#ifndef MTRACK
143  fprintf(stderr, "\n");
144#endif
145
146  if (strcmp(msg,"size")==0)
147    (void)fprintf( stderr, "size is: %d, but check said %d \n",
148      (int)what->size, given_size );
149  else
150    (void)fprintf( stderr, "size is: %d\n", (int)what->size );
151  return 0;
152}
153
154void mmPrintUsedList( )
155{
156  DBMCB * what;
157  what=mm_theDBused.next;
158  fprintf(stderr,"list of used blocks:\n");
159  while (what!=NULL)
160  {
161    (void)fprintf( stderr, "%d bytes at %p in: %s:%d\n",
162      (int)what->size, what, what->allocated_fname, what->allocated_lineno);
163    what=what->next;
164  }
165}
166
167void mmPrintFL( const char* fname, const int lineno )
168{
169  (void)fprintf( stderr, "occured in %s:%d\n", fname, lineno );
170}
171
172/**********************************************************************
173 *
174 * Init routines
175 *
176 **********************************************************************/
177
178#define MM_USED_PATTERN 255
179#define MM_FREE_PATTERN 251
180#define MM_FRONT_PATTERN 247
181#define MM_BACK_PATTERN  249
182
183void mmFillDBMCB(DBMCB* what, size_t size, memHeap heap,
184                 int flags, char* fname, int lineno)
185{
186  void* addr = &(what->data);
187
188  what->heap = heap;
189  what->size = size;
190  if ((what->flags & MM_USEDFLAG) && (flags && MM_FREEFLAG))
191  {
192    what->freed_fname = fname;
193    what->freed_lineno = lineno;
194  }
195  else
196  {
197    what->allocated_fname = fname;
198    what->allocated_lineno = lineno;
199  }
200
201  if (flags == MM_FREEFLAG)
202  {
203    what->flags &= ~ MM_USEDFLAG;
204    what->flags |= MM_FREEFLAG;
205    what->flags &= ~ MM_CURRENTLY_USEDFLAG;
206  }
207  else if (flags == MM_USEDFLAG)
208  {
209    what->flags &= ~ MM_FREEFLAG;
210    what->flags |= MM_USEDFLAG;
211    if (mm_markCurrentUsage == 1)
212      what->flags |= MM_CURRENTLY_USEDFLAG;
213  }
214
215  if (flags & MM_FREEFLAG)
216    memset(addr, MM_FREE_PATTERN, size);
217
218  memset(what->front_pattern, MM_FRONT_PATTERN, MM_NUMBER_OF_FRONT_PATTERNS);
219  memset(addr, 255, size);
220  memset((char*) addr + size, MM_BACK_PATTERN, DebugOffsetBack);
221}
222
223void mmMarkInitDBMCB()
224{
225  DBMCB * what=mm_theDBused.next;
226  while (what != NULL)
227  {
228    what->flags |= MM_INITFLAG;
229    what = what->next;
230  }
231}
232
233/**********************************************************************
234 *
235 * Check routines
236 *
237 **********************************************************************/
238
239static int mmCheckPattern(char* ptr, char pattern, size_t size)
240{
241  int i;
242
243  for (i = 0; i<size; i++)
244    if (ptr[i] != pattern) return 0;
245  return 1;
246}
247
248#ifdef unix
249extern int _end;
250#endif
251static int mmCheckSingleDBMCB ( DBMCB * what, int size , int flags)
252{
253  char * patptr;
254  int i;
255  int ok=1;
256  if ( ((long)what % 4 ) != 0 )
257  {
258    fprintf( stderr, "warning: odd address\n" );
259    assume(0);
260    return 0;
261  }
262  if ( (void*)what > mm_maxAddr && mm_maxAddr != NULL)
263  {
264    fprintf( stderr, "warning: address too high\n" );
265    assume(0);
266    return 0;
267  }
268  if ( (void*)what < mm_minAddr && mm_minAddr != NULL)
269  {
270    fprintf( stderr, "warning: address too low\n" );
271    assume(0);
272    return 0;
273  }
274  if (! mmIsNotAddrOnFreePage(what))
275  {
276    fprintf(stderr, "warning: address on freed page\n");
277    assume(0);
278    return 0;
279  }
280
281  if ( ((long)what->allocated_fname<1000)
282  #ifdef unix
283       ||((long)what->allocated_fname>(long)&(_end))
284  #endif
285  )
286  { /* fname should be in the text segment */
287    fprintf(stderr, "warning: allocated_fname (%lx) out of range\n", (long)what->allocated_fname );
288    assume(0);
289    what->allocated_fname="???";
290    ok=0;
291  }
292  if ( (what->allocated_lineno< -9999) ||(what->allocated_lineno>9999) )
293  {
294    fprintf( stderr, "warning: allocated_lineno %d out of range\n",what->allocated_lineno );
295    assume(0);
296    what->allocated_lineno=0;
297    ok=0;
298  }
299
300  if ((what->flags & MM_FREEFLAG) && what->freed_fname != NULL)
301  {
302    if ( ((long)what->freed_fname<1000)
303#ifdef unix
304         ||((long)what->freed_fname>(long)&(_end))
305#endif
306         )
307    { /* fname should be in the text segment */
308      fprintf(stderr, "warning: freed_fname (%lx) out of range\n", (long)what->freed_fname );
309      assume(0);
310      what->freed_fname="???";
311      ok=0;
312    }
313    if ( (what->freed_lineno< -9999) ||(what->freed_lineno>9999) )
314    {
315      fprintf( stderr, "warning: freed_lineno %d out of range\n",what->freed_lineno );
316      assume(0);
317      what->freed_lineno=0;
318      ok=0;
319    }
320  }
321
322
323  #ifdef unix
324  if ( (what->next!=NULL)
325       && (((long)what->next>(long)mm_maxAddr)
326           || ((long)what->next<(long)mm_minAddr) )
327       && (((long)what->next>(long)&_end)
328           || ((long)what->next<1000))
329  )
330  {
331    fprintf( stderr, "warning: next (%lx) out of range\n", (long)what->next );
332    assume(0);
333    what->next=NULL;
334    ok=0;
335  }
336  if ( (what->prev!=NULL)
337       && (((long)what->prev>(long)mm_maxAddr)
338           || ((long)what->prev<(long)mm_minAddr) )
339       && (((long)what->prev>(long)&_end)
340           || ((long)what->prev<1000)))
341  {
342    fprintf( stderr, "warning: prev (%lx) out of range\n", (long)what->prev );
343    assume(0);
344    what->prev=NULL;
345    ok=0;
346  }
347  #endif
348
349  if ( ( what->flags & flags ) != flags )
350  {
351    if (flags & MM_USEDFLAG)
352    {
353      mmMoveDBMCB(&mm_theDBfree, &mm_theDBused, what);
354      what->flags |= MM_USEDFLAG;
355      return mmPrintDBMCB( what, "block has been freed but still in use (fixed)", 0 );
356    }
357    return mmPrintDBMCB(what, "block still in use but should be free", 0);
358  }
359
360  if (mm_referenceWatch)
361  {
362    if (what->flags & MM_REFERENCEFLAG)
363    {
364//      mm_referenceWatch = 0;
365      return mmPrintDBMCB(what, "reference", 0);
366    }
367    else
368      what->flags |= MM_REFERENCEFLAG;
369  }
370
371  if ( what->size != size )
372    return mmPrintDBMCB( what, "size", size );
373
374  i = mmGetIndex(size);
375
376  if (! mmCheckPattern(what->front_pattern, MM_FRONT_PATTERN,
377                       MM_NUMBER_OF_FRONT_PATTERNS))
378    return mmPrintDBMCB(what , "front pattern", 0);
379  if ((what->flags & MM_FREEFLAG)  &&
380      ! mmCheckPattern((char*)&(what->data), MM_FREE_PATTERN, 0))
381    return mmPrintDBMCB(what, "free pattern", 0);
382  if (! mmCheckPattern((char*) &(what->data) + size,
383                       MM_BACK_PATTERN, DebugOffsetBack))
384    return mmPrintDBMCB(what, "back pattern", 0);
385
386  if ( ( what->next != NULL ) && ( what->next->prev != what ) )
387  {
388    mmPrintDBMCB( what->next, "next", 0 );
389    what->next->prev=what;
390    return mmPrintDBMCB( what, "chain:n", 0 );
391  }
392  if ( ( what->prev != NULL ) && ( what->prev->next != what ) )
393  {
394    mmPrintDBMCB( what->prev, "prev", 0 );
395    what->prev->next=what;
396    return mmPrintDBMCB( what, "chain:p", 0 );
397  }
398  if(ok==0)
399  {
400    return mmPrintDBMCB( what, "see above", 0 );
401  }
402  if (mm_markCurrentUsage == 1)
403  {
404    what->flags |= MM_CURRENTLY_USEDFLAG;
405  }
406  return 1;
407}
408
409static int mmCheckDBMCBList(DBMCB * list, int flags)
410{
411  assume(flags == MM_FREEFLAG || flags == MM_USEDFLAG);
412
413  if (mmGListHasCycle(list,
414                      (void*) &(mm_theDBfree.next) -
415                      (void*) &(mm_theDBfree)))
416  {
417    fprintf(stderr, "%s list contains cycles\n",
418            (flags == MM_FREEFLAG ? "Free" : "Used"));
419    assume(0);
420    return 0;
421  }
422
423  while (list != NULL)
424  {
425    if (! mmCheckSingleDBMCB(list, list->size, flags))
426    {
427      fprintf(stderr, "while check of %s list\n",
428            (flags == MM_FREEFLAG ? "free" : "used"));
429      return 0;
430    }
431    list = list->next;
432  }
433
434  return 1;
435}
436
437int mmTestMemory()
438{
439  if (mmCheckDBMCBList(mm_theDBused.next, MM_USEDFLAG))
440    return mmCheckDBMCBList(mm_theDBfree.next, MM_FREEFLAG);
441  return 0;
442}
443
444
445static int   mmIsAddrOnDList(DBMCB *what, DBMCB* list, int s)
446{
447  while (list != NULL)
448  {
449    if (list == what) return 1;
450    list = list->next;
451  }
452  return 0;
453}
454
455static int mmCheckListContainment(DBMCB * what, int flags)
456{
457  if ( mmIsAddrOnDList((void*) what, mm_theDBused.next,
458                       (void*) &(mm_theDBused.next) -
459                       (void*) &(mm_theDBused)))
460  {
461    if (flags == MM_FREEFLAG)
462      return mmPrintDBMCB(what, "Free flag and in used list", 0);
463  }
464  else
465  {
466    if (flags == MM_USEDFLAG)
467      return mmPrintDBMCB(what, "Used flag but not in used list", 0);
468  }
469
470  if ( mmIsAddrOnDList((void*) what, mm_theDBfree.next,
471                       (void*) &(mm_theDBfree.next) -
472                       (void*) &(mm_theDBfree)))
473  {
474    if (flags == MM_USEDFLAG)
475      return mmPrintDBMCB(what, "Used flag and in free list", 0);
476  }
477  else
478  {
479    if (flags == MM_FREEFLAG)
480      return mmPrintDBMCB(what,"Free flag but not in free list", 0);
481  }
482  return 1;
483}
484
485int mmCheckDBMCB ( DBMCB * what, int size , int flags)
486{
487
488  assume(flags == MM_FREEFLAG || flags == MM_USEDFLAG);
489  if (! mmCheckSingleDBMCB(what, size, flags))
490    return 0;
491
492  if (mm_MDEBUG > 1 && ! mmTestMemory()) return 0;
493
494  if (mm_MDEBUG > 0 && ! mmCheckListContainment(what, flags)) return 0;
495
496  return 1;
497}
498
499/**********************************************************************
500 *
501 * Test routines
502 *
503 **********************************************************************/
504static BOOLEAN mmDBTestHeapBlockS(const void* adr, const memHeap heap,
505                                  const size_t size,
506                                  const char * fname, const int lineno )
507{
508  DBMCB * what;
509
510  if ( adr == NULL || size == 0)
511    return TRUE;
512
513  if (mm_MDEBUG > 2 && ! mmTestHeaps())
514  {
515    mmPrintFL( fname, lineno );
516    return FALSE;
517  }
518
519  what = (DBMCB*)((char*)(adr) - DebugOffsetFront);
520
521  if ( ! mmCheckDBMCB( what, size, MM_USEDFLAG) )
522  {
523    mmPrintFL( fname, lineno );
524    return FALSE;
525  }
526
527  if (what->heap != heap)
528  {
529    mmPrintDBMCB(what, "Not from specified heap", 0);
530    mmPrintFL( fname, lineno );
531    return FALSE;
532  }
533
534#ifdef HEAP_DEBUG
535  return
536    mmDebugCheckHeapAddr(what, heap, MM_HEAP_ADDR_USED_FLAG, fname, lineno);
537#else
538  return TRUE;
539#endif
540}
541
542BOOLEAN mmDBTestHeapBlock(const void* adr, const memHeap heap,
543                          const char * fname, const int lineno )
544{
545  return mmDBTestHeapBlockS(adr, heap,
546                            SizeFromRealSize(heap->size),
547                            fname, lineno);
548}
549
550BOOLEAN mmDBTestBlock(const void* adr, const size_t size,
551                      const char * fname, const int lineno)
552{
553  int i;
554  DBMCB * what;
555
556  if ( ( adr == NULL ) || ( size == 0 ) ) return TRUE;
557
558  i = mmGetIndex(size);
559  if (i < 0)
560  {
561    what = (DBMCB*)((char*)(adr) - DebugOffsetFront);
562    if ( ! mmCheckDBMCB( what, size, MM_USEDFLAG) )
563    {
564      mmPrintFL( fname, lineno );
565      return FALSE;
566    }
567    return TRUE;
568  }
569  else
570  {
571    return mmDBTestHeapBlockS(adr, &(mm_theList[i]), size, fname, lineno);
572  }
573}
574
575
576BOOLEAN mmDBTest( const void* adr, const char * fname, const int lineno )
577{
578  if (adr!=NULL)
579  {
580    size_t l;
581    adr = (size_t*)adr-1;
582#ifdef ALIGN_8
583    l= (adr<=mm_maxAddr) ? (*(size_t*)((long)adr&(~((long)7)))) :0;
584#else
585    l= (adr<=mm_maxAddr) ? (*(size_t*)((long)adr&(~((long)3)))) :0;
586#endif
587    return mmDBTestBlock( adr,l, fname, lineno );
588  }
589  return TRUE;
590}
591
592/**********************************************************************
593 *
594 * Routines fro marking
595 *
596 **********************************************************************/
597void mmMarkCurrentUsageState()
598{
599  DBMCB* what = mm_theDBused.next;
600  mm_markCurrentUsage = -1;
601  while (what != NULL)
602  {
603    what->flags |= MM_CURRENTLY_USEDFLAG;
604    what = what->next;
605  }
606}
607
608void mmMarkCurrentUsageStart()
609{
610  mm_markCurrentUsage = 1;
611}
612
613void mmMarkCurrentUsageStop()
614{
615  mm_markCurrentUsage = 0;
616}
617
618void mmPrintUnMarkedBlocks()
619{
620  DBMCB* what = mm_theDBused.next;
621  int found = 0;
622  while (what != NULL)
623  {
624    if (! (what->flags & MM_CURRENTLY_USEDFLAG))
625    {
626      mmPrintDBMCB(what, "unused", 0);
627      what->flags |= MM_CURRENTLY_USEDFLAG;
628      found = 1;
629    }
630    what = what->next;
631  }
632  if (found) fprintf(stderr, "\nFinished found\n");
633}
634
635void mmStartReferenceWatch()
636{
637  DBMCB* what = mm_theDBused.next;
638  mm_referenceWatch = 1;
639  while (what != NULL)
640  {
641    what->flags &= ~ MM_REFERENCEFLAG;
642    what = what->next;
643  }
644}
645
646void mmStopReferenceWatch()
647{
648  mm_referenceWatch = 0;
649}
650
651#endif /* MDEBUG */
652
653
654
Note: See TracBrowser for help on using the repository browser.