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