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