xref: /petsc/src/sys/memory/mtr.c (revision fe998a80077c9ee0917a39496df43fc256e1b478)
1 
2 /*
3      Interface to malloc() and free(). This code allows for
4   logging of memory usage and some error checking
5 */
6 #include <petscsys.h>           /*I "petscsys.h" I*/
7 #include <petscviewer.h>
8 #if defined(PETSC_HAVE_MALLOC_H)
9 #include <malloc.h>
10 #endif
11 
12 
13 /*
14      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
15 */
16 extern PetscErrorCode  PetscMallocAlign(size_t,int,const char[],const char[],void**);
17 extern PetscErrorCode  PetscFreeAlign(void*,int,const char[],const char[]);
18 extern PetscErrorCode  PetscTrMallocDefault(size_t,int,const char[],const char[],void**);
19 extern PetscErrorCode  PetscTrFreeDefault(void*,int,const char[],const char[]);
20 
21 
22 #define CLASSID_VALUE   ((PetscClassId) 0xf0e0d0c9)
23 #define ALREADY_FREED  ((PetscClassId) 0x0f0e0d9c)
24 
25 typedef struct _trSPACE {
26   size_t       size;
27   int          id;
28   int          lineno;
29   const char   *filename;
30   const char   *functionname;
31   PetscClassId classid;
32 #if defined(PETSC_USE_DEBUG)
33   PetscStack   stack;
34 #endif
35   struct _trSPACE *next,*prev;
36 } TRSPACE;
37 
38 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
39    It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN.
40 */
41 
42 #define HEADER_BYTES      ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))
43 
44 
45 /* This union is used to insure that the block passed to the user retains
46    a minimum alignment of PETSC_MEMALIGN.
47 */
48 typedef union {
49   TRSPACE sp;
50   char    v[HEADER_BYTES];
51 } TrSPACE;
52 
53 
54 static size_t    TRallocated  = 0;
55 static int       TRfrags      = 0;
56 static TRSPACE   *TRhead      = 0;
57 static int       TRid         = 0;
58 static PetscBool TRdebugLevel = PETSC_FALSE;
59 static size_t    TRMaxMem     = 0;
60 /*
61       Arrays to log information on all Mallocs
62 */
63 static int        PetscLogMallocMax       = 10000,PetscLogMalloc = -1;
64 static size_t     PetscLogMallocThreshold = 0;
65 static size_t     *PetscLogMallocLength;
66 static const char **PetscLogMallocFile,**PetscLogMallocFunction;
67 
68 #undef __FUNCT__
69 #define __FUNCT__ "PetscSetUseTrMalloc_Private"
70 PetscErrorCode PetscSetUseTrMalloc_Private(void)
71 {
72   PetscErrorCode ierr;
73 
74   PetscFunctionBegin;
75   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr);
76 
77   TRallocated       = 0;
78   TRfrags           = 0;
79   TRhead            = 0;
80   TRid              = 0;
81   TRdebugLevel      = PETSC_FALSE;
82   TRMaxMem          = 0;
83   PetscLogMallocMax = 10000;
84   PetscLogMalloc    = -1;
85   PetscFunctionReturn(0);
86 }
87 
88 #undef __FUNCT__
89 #define __FUNCT__ "PetscMallocValidate"
90 /*@C
91    PetscMallocValidate - Test the memory for corruption.  This can be used to
92    check for memory overwrites.
93 
94    Input Parameter:
95 +  line - line number where call originated.
96 .  function - name of function calling
97 -  file - file where function is
98 
99    Return value:
100    The number of errors detected.
101 
102    Output Effect:
103    Error messages are written to stdout.
104 
105    Level: advanced
106 
107    Notes:
108     You should generally use CHKMEMQ as a short cut for calling this
109     routine.
110 
111     The line, function, file are given by the C preprocessor as
112     __LINE__, __FUNCT__, __FILE__
113 
114     The Fortran calling sequence is simply PetscMallocValidate(ierr)
115 
116    No output is generated if there are no problems detected.
117 
118 .seealso: CHKMEMQ
119 
120 @*/
121 PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
122 {
123   TRSPACE      *head,*lasthead;
124   char         *a;
125   PetscClassId *nend;
126 
127   PetscFunctionBegin;
128   head = TRhead; lasthead = NULL;
129   while (head) {
130     if (head->classid != CLASSID_VALUE) {
131       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s\n",function,line,file);
132       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
133       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
134       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
135       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
136     }
137     a    = (char*)(((TrSPACE*)head) + 1);
138     nend = (PetscClassId*)(a + head->size);
139     if (*nend != CLASSID_VALUE) {
140       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
141       if (*nend == ALREADY_FREED) {
142         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
143         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
144       } else {
145         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
146         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
147         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
148       }
149     }
150     lasthead = head;
151     head     = head->next;
152   }
153   PetscFunctionReturn(0);
154 }
155 
156 #undef __FUNCT__
157 #define __FUNCT__ "PetscTrMallocDefault"
158 /*
159     PetscTrMallocDefault - Malloc with tracing.
160 
161     Input Parameters:
162 +   a   - number of bytes to allocate
163 .   lineno - line number where used.  Use __LINE__ for this
164 .   function - function calling routine. Use __FUNCT__ for this
165 -   filename  - file name where used.  Use __FILE__ for this
166 
167     Returns:
168     double aligned pointer to requested storage, or null if not
169     available.
170  */
171 PetscErrorCode  PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],void **result)
172 {
173   TRSPACE        *head;
174   char           *inew;
175   size_t         nsize;
176   PetscErrorCode ierr;
177 
178   PetscFunctionBegin;
179   if (TRdebugLevel) {
180     ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
181   }
182 
183   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
184   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
185 
186   head  = (TRSPACE*)inew;
187   inew += sizeof(TrSPACE);
188 
189   if (TRhead) TRhead->prev = head;
190   head->next   = TRhead;
191   TRhead       = head;
192   head->prev   = 0;
193   head->size   = nsize;
194   head->id     = TRid;
195   head->lineno = lineno;
196 
197   head->filename                 = filename;
198   head->functionname             = function;
199   head->classid                  = CLASSID_VALUE;
200   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
201 
202   TRallocated += nsize;
203   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
204   TRfrags++;
205 
206 #if defined(PETSC_USE_DEBUG)
207   if (PetscStackActive()) {
208     ierr = PetscStackCopy((PetscStack*)PetscThreadLocalGetValue(petscstack),&head->stack);CHKERRQ(ierr);
209     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
210     head->stack.line[head->stack.currentsize-2] = lineno;
211   }
212 #endif
213 
214   /*
215          Allow logging of all mallocs made
216   */
217   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
218     if (!PetscLogMalloc) {
219       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
220       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
221 
222       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
223       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
224 
225       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
226       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
227     }
228     PetscLogMallocLength[PetscLogMalloc]     = nsize;
229     PetscLogMallocFile[PetscLogMalloc]       = filename;
230     PetscLogMallocFunction[PetscLogMalloc++] = function;
231   }
232   *result = (void*)inew;
233   PetscFunctionReturn(0);
234 }
235 
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "PetscTrFreeDefault"
239 /*
240    PetscTrFreeDefault - Free with tracing.
241 
242    Input Parameters:
243 .   a    - pointer to a block allocated with PetscTrMalloc
244 .   lineno - line number where used.  Use __LINE__ for this
245 .   function - function calling routine. Use __FUNCT__ for this
246 .   file  - file name where used.  Use __FILE__ for this
247  */
248 PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
249 {
250   char           *a = (char*)aa;
251   TRSPACE        *head;
252   char           *ahead;
253   PetscErrorCode ierr;
254   PetscClassId   *nend;
255 
256   PetscFunctionBegin;
257   /* Do not try to handle empty blocks */
258   if (!a) PetscFunctionReturn(0);
259 
260   if (TRdebugLevel) {
261     ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr);
262   }
263 
264   ahead = a;
265   a     = a - sizeof(TrSPACE);
266   head  = (TRSPACE*)a;
267 
268   if (head->classid != CLASSID_VALUE) {
269     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
270     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
271     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
272   }
273   nend = (PetscClassId*)(ahead + head->size);
274   if (*nend != CLASSID_VALUE) {
275     if (*nend == ALREADY_FREED) {
276       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
277       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
278       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
279         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
280       } else {
281         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
282       }
283       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
284     } else {
285       /* Damaged tail */
286       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
287       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
288       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
289       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
290     }
291   }
292   /* Mark the location freed */
293   *nend = ALREADY_FREED;
294   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
295   if (line > 0 && line < 50000) {
296     head->lineno       = line;
297     head->filename     = file;
298     head->functionname = function;
299   } else {
300     head->lineno = -head->lineno;
301   }
302   /* zero out memory - helps to find some reuse of already freed memory */
303   ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr);
304 
305   TRallocated -= head->size;
306   TRfrags--;
307   if (head->prev) head->prev->next = head->next;
308   else TRhead = head->next;
309 
310   if (head->next) head->next->prev = head->prev;
311   ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr);
312   PetscFunctionReturn(0);
313 }
314 
315 
316 #undef __FUNCT__
317 #define __FUNCT__ "PetscMemoryShowUsage"
318 /*@C
319     PetscMemoryShowUsage - Shows the amount of memory currently being used
320         in a communicator.
321 
322     Collective on PetscViewer
323 
324     Input Parameter:
325 +    viewer - the viewer that defines the communicator
326 -    message - string printed before values
327 
328     Level: intermediate
329 
330     Concepts: memory usage
331 
332 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage()
333  @*/
334 PetscErrorCode  PetscMemoryShowUsage(PetscViewer viewer,const char message[])
335 {
336   PetscLogDouble allocated,maximum,resident,residentmax;
337   PetscErrorCode ierr;
338   PetscMPIInt    rank;
339   MPI_Comm       comm;
340 
341   PetscFunctionBegin;
342   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
343   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
344   ierr = PetscMallocGetMaximumUsage(&maximum);CHKERRQ(ierr);
345   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
346   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
347   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
348   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
349   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
350   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
351   ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr);
352   if (resident && residentmax && allocated) {
353     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g max process memory %g\n",rank,allocated,maximum,rank,resident,residentmax);CHKERRQ(ierr);
354   } else if (resident && residentmax) {
355     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Run with -malloc to get statistics on PetscMalloc() calls\n[%d]Current process memory %g max process memory %g\n",rank,rank,resident,residentmax);CHKERRQ(ierr);
356   } else if (resident && allocated) {
357     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g, run with -memory_info to get max memory usage\n",rank,allocated,maximum,rank,resident);CHKERRQ(ierr);
358   } else if (allocated) {
359     ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]OS cannot compute process memory\n",rank,allocated,maximum,rank);CHKERRQ(ierr);
360   } else {
361     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
362   }
363   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
364   ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr);
365   PetscFunctionReturn(0);
366 }
367 
368 #undef __FUNCT__
369 #define __FUNCT__ "PetscMallocGetCurrentUsage"
370 /*@C
371     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
372 
373     Not Collective
374 
375     Output Parameters:
376 .   space - number of bytes currently allocated
377 
378     Level: intermediate
379 
380     Concepts: memory usage
381 
382 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
383           PetscMemoryGetMaximumUsage()
384  @*/
385 PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
386 {
387   PetscFunctionBegin;
388   *space = (PetscLogDouble) TRallocated;
389   PetscFunctionReturn(0);
390 }
391 
392 #undef __FUNCT__
393 #define __FUNCT__ "PetscMallocGetMaximumUsage"
394 /*@C
395     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
396         during this run.
397 
398     Not Collective
399 
400     Output Parameters:
401 .   space - maximum number of bytes ever allocated at one time
402 
403     Level: intermediate
404 
405     Concepts: memory usage
406 
407 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
408           PetscMemoryGetCurrentUsage()
409  @*/
410 PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
411 {
412   PetscFunctionBegin;
413   *space = (PetscLogDouble) TRMaxMem;
414   PetscFunctionReturn(0);
415 }
416 
417 #if defined(PETSC_USE_DEBUG)
418 #undef __FUNCT__
419 #define __FUNCT__ "PetscMallocGetStack"
420 /*@C
421    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
422 
423    Collective on PETSC_COMM_WORLD
424 
425    Input Parameter:
426 .    ptr - the memory location
427 
428    Output Paramter:
429 .    stack - the stack indicating where the program allocated this memory
430 
431    Level: intermediate
432 
433 .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
434 @*/
435 PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
436 {
437   TRSPACE *head;
438 
439   PetscFunctionBegin;
440   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
441   *stack = &head->stack;
442   PetscFunctionReturn(0);
443 }
444 #else
445 #undef __FUNCT__
446 #define __FUNCT__ "PetscMallocGetStack"
447 PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
448 {
449   PetscFunctionBegin;
450   *stack = 0;
451   PetscFunctionReturn(0);
452 }
453 #endif
454 
455 #undef __FUNCT__
456 #define __FUNCT__ "PetscMallocDump"
457 /*@C
458    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
459    printed is: size of space (in bytes), address of space, id of space,
460    file in which space was allocated, and line number at which it was
461    allocated.
462 
463    Collective on PETSC_COMM_WORLD
464 
465    Input Parameter:
466 .  fp  - file pointer.  If fp is NULL, stdout is assumed.
467 
468    Options Database Key:
469 .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
470 
471    Level: intermediate
472 
473    Fortran Note:
474    The calling sequence in Fortran is PetscMallocDump(integer ierr)
475    The fp defaults to stdout.
476 
477    Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
478           has been freed.
479 
480    Concepts: memory usage
481    Concepts: memory bleeding
482    Concepts: bleeding memory
483 
484 .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
485 @*/
486 PetscErrorCode  PetscMallocDump(FILE *fp)
487 {
488   TRSPACE        *head;
489   PetscErrorCode ierr;
490   PetscMPIInt    rank;
491 
492   PetscFunctionBegin;
493   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
494   if (!fp) fp = PETSC_STDOUT;
495   if (TRallocated > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
496   head = TRhead;
497   while (head) {
498     fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
499 #if defined(PETSC_USE_DEBUG)
500     ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
501 #endif
502     head = head->next;
503   }
504   PetscFunctionReturn(0);
505 }
506 
507 /* ---------------------------------------------------------------------------- */
508 
509 #undef __FUNCT__
510 #define __FUNCT__ "PetscMallocSetDumpLog"
511 /*@C
512     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
513 
514     Not Collective
515 
516     Options Database Key:
517 +  -malloc_log <filename> - Activates PetscMallocDumpLog()
518 -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
519 
520     Level: advanced
521 
522 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
523 @*/
524 PetscErrorCode PetscMallocSetDumpLog(void)
525 {
526   PetscErrorCode ierr;
527 
528   PetscFunctionBegin;
529   PetscLogMalloc = 0;
530 
531   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
532   PetscFunctionReturn(0);
533 }
534 
535 #undef __FUNCT__
536 #define __FUNCT__ "PetscMallocSetDumpLogThreshold"
537 /*@C
538     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
539 
540     Not Collective
541 
542     Input Arguments:
543 .   logmin - minimum allocation size to log, or PETSC_DEFAULT
544 
545     Options Database Key:
546 +  -malloc_log <filename> - Activates PetscMallocDumpLog()
547 -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
548 
549     Level: advanced
550 
551 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
552 @*/
553 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
554 {
555   PetscErrorCode ierr;
556 
557   PetscFunctionBegin;
558   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
559   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
560   PetscLogMallocThreshold = (size_t)logmin;
561   PetscFunctionReturn(0);
562 }
563 
564 #undef __FUNCT__
565 #define __FUNCT__ "PetscMallocGetDumpLog"
566 /*@C
567     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
568 
569     Not Collective
570 
571     Output Arguments
572 .   logging - PETSC_TRUE if logging is active
573 
574     Options Database Key:
575 .  -malloc_log - Activates PetscMallocDumpLog()
576 
577     Level: advanced
578 
579 .seealso: PetscMallocDump(), PetscMallocDumpLog()
580 @*/
581 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
582 {
583 
584   PetscFunctionBegin;
585   *logging = (PetscBool)(PetscLogMalloc >= 0);
586   PetscFunctionReturn(0);
587 }
588 
589 #undef __FUNCT__
590 #define __FUNCT__ "PetscMallocDumpLog"
591 /*@C
592     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
593        PetscMemoryGetMaximumUsage()
594 
595     Collective on PETSC_COMM_WORLD
596 
597     Input Parameter:
598 .   fp - file pointer; or NULL
599 
600     Options Database Key:
601 .  -malloc_log - Activates PetscMallocDumpLog()
602 
603     Level: advanced
604 
605    Fortran Note:
606    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
607    The fp defaults to stdout.
608 
609 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
610 @*/
611 PetscErrorCode  PetscMallocDumpLog(FILE *fp)
612 {
613   PetscInt       i,j,n,dummy,*perm;
614   size_t         *shortlength;
615   int            *shortcount,err;
616   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
617   PetscBool      match;
618   const char     **shortfunction;
619   PetscLogDouble rss;
620   MPI_Status     status;
621   PetscErrorCode ierr;
622 
623   PetscFunctionBegin;
624   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
625   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
626   /*
627        Try to get the data printed in order by processor. This will only sometimes work
628   */
629   err = fflush(fp);
630   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
631 
632   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
633   if (rank) {
634     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
635   }
636 
637   if (PetscLogMalloc < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocDumpLog() called without call to PetscMallocSetDumpLog() this is often due to\n                      setting the option -malloc_log AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
638 
639   if (!fp) fp = PETSC_STDOUT;
640   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
641   if (rss) {
642     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);CHKERRQ(ierr);
643   } else {
644     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);CHKERRQ(ierr);
645   }
646   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
647   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
648   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
649   for (i=0,n=0; i<PetscLogMalloc; i++) {
650     for (j=0; j<n; j++) {
651       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
652       if (match) {
653         shortlength[j] += PetscLogMallocLength[i];
654         shortcount[j]++;
655         goto foundit;
656       }
657     }
658     shortfunction[n] = PetscLogMallocFunction[i];
659     shortlength[n]   = PetscLogMallocLength[i];
660     shortcount[n]    = 1;
661     n++;
662 foundit:;
663   }
664 
665   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
666   for (i=0; i<n; i++) perm[i] = i;
667   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
668 
669   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
670   for (i=0; i<n; i++) {
671     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr);
672   }
673   free(perm);
674   free(shortlength);
675   free(shortcount);
676   free((char**)shortfunction);
677   err = fflush(fp);
678   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
679   if (rank != size-1) {
680     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
681   }
682   PetscFunctionReturn(0);
683 }
684 
685 /* ---------------------------------------------------------------------------- */
686 
687 #undef __FUNCT__
688 #define __FUNCT__ "PetscMallocDebug"
689 /*@C
690     PetscMallocDebug - Turns on/off debugging for the memory management routines.
691 
692     Not Collective
693 
694     Input Parameter:
695 .   level - PETSC_TRUE or PETSC_FALSE
696 
697    Level: intermediate
698 
699 .seealso: CHKMEMQ(), PetscMallocValidate()
700 @*/
701 PetscErrorCode  PetscMallocDebug(PetscBool level)
702 {
703   PetscFunctionBegin;
704   TRdebugLevel = level;
705   PetscFunctionReturn(0);
706 }
707 
708 #undef __FUNCT__
709 #define __FUNCT__ "PetscMallocGetDebug"
710 /*@C
711     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
712 
713     Not Collective
714 
715     Output Parameter:
716 .    flg - PETSC_TRUE if any debugger
717 
718    Level: intermediate
719 
720     Note that by default, the debug version always does some debugging unless you run with -malloc no
721 
722 
723 .seealso: CHKMEMQ(), PetscMallocValidate()
724 @*/
725 PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
726 {
727   PetscFunctionBegin;
728   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
729   else *flg = PETSC_FALSE;
730   PetscFunctionReturn(0);
731 }
732