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