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