xref: /petsc/src/sys/memory/mtr.c (revision 5a856986583887c326abe5dfd149e8184a29cd80)
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 PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,PetscBool,int,const char[],const char[],void**);
17 PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]);
18 PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**);
19 PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,PetscBool,int,const char[],const char[],void**);
20 PETSC_EXTERN PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]);
21 PETSC_EXTERN PetscErrorCode PetscTrReallocDefault(size_t,int,const char[],const char[],void**);
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   PetscClassId classid;
34 #if defined(PETSC_USE_DEBUG)
35   PetscStack   stack;
36 #endif
37   struct _trSPACE *next,*prev;
38 } TRSPACE;
39 
40 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
41    It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN.
42 */
43 
44 #define HEADER_BYTES  ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))
45 
46 
47 /* This union is used to insure that the block passed to the user retains
48    a minimum alignment of PETSC_MEMALIGN.
49 */
50 typedef union {
51   TRSPACE sp;
52   char    v[HEADER_BYTES];
53 } TrSPACE;
54 
55 #define MAXTRMAXMEMS 50
56 static size_t    TRallocated  = 0;
57 static int       TRfrags      = 0;
58 static TRSPACE   *TRhead      = NULL;
59 static int       TRid         = 0;
60 static PetscBool TRdebugLevel = PETSC_FALSE;
61 static size_t    TRMaxMem     = 0;
62 static int       NumTRMaxMems = 0;
63 static size_t    TRMaxMems[MAXTRMAXMEMS];
64 static int       TRMaxMemsEvents[MAXTRMAXMEMS];
65 /*
66       Arrays to log information on all Mallocs
67 */
68 static int        PetscLogMallocMax       = 10000;
69 static int        PetscLogMalloc          = -1;
70 static size_t     PetscLogMallocThreshold = 0;
71 static size_t     *PetscLogMallocLength;
72 static const char **PetscLogMallocFile,**PetscLogMallocFunction;
73 static PetscBool  PetscSetUseTrMallocCalled = PETSC_FALSE;
74 
75 PETSC_INTERN PetscErrorCode PetscSetUseTrMalloc_Private(void)
76 {
77   PetscErrorCode ierr;
78 
79   PetscFunctionBegin;
80   if (PetscSetUseTrMallocCalled) PetscFunctionReturn(0);
81   PetscSetUseTrMallocCalled = PETSC_TRUE;
82   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr);
83   PetscTrRealloc = PetscTrReallocDefault;
84 
85   TRallocated       = 0;
86   TRfrags           = 0;
87   TRhead            = NULL;
88   TRid              = 0;
89   TRdebugLevel      = PETSC_FALSE;
90   TRMaxMem          = 0;
91   PetscLogMallocMax = 10000;
92   PetscLogMalloc    = -1;
93   PetscFunctionReturn(0);
94 }
95 
96 /*@C
97    PetscMallocValidate - Test the memory for corruption.  This can be used to
98    check for memory overwrites.
99 
100    Input Parameter:
101 +  line - line number where call originated.
102 .  function - name of function calling
103 -  file - file where function is
104 
105    Return value:
106    The number of errors detected.
107 
108    Output Effect:
109    Error messages are written to stdout.
110 
111    Level: advanced
112 
113    Notes:
114     You should generally use CHKMEMQ as a short cut for calling this
115     routine.
116 
117     The line, function, file are given by the C preprocessor as
118 
119     The Fortran calling sequence is simply PetscMallocValidate(ierr)
120 
121    No output is generated if there are no problems detected.
122 
123 .seealso: CHKMEMQ
124 
125 @*/
126 PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
127 {
128   TRSPACE      *head,*lasthead;
129   char         *a;
130   PetscClassId *nend;
131 
132   PetscFunctionBegin;
133   head = TRhead; lasthead = NULL;
134   while (head) {
135     if (head->classid != CLASSID_VALUE) {
136       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s\n",function,line,file);
137       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
138       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
139       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
140       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
141     }
142     a    = (char*)(((TrSPACE*)head) + 1);
143     nend = (PetscClassId*)(a + head->size);
144     if (*nend != CLASSID_VALUE) {
145       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
146       if (*nend == ALREADY_FREED) {
147         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
148         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
149       } else {
150         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
151         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
152         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
153       }
154     }
155     lasthead = head;
156     head     = head->next;
157   }
158   PetscFunctionReturn(0);
159 }
160 
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 -   filename  - file name where used.  Use __FILE__ for this
168 
169     Returns:
170     double aligned pointer to requested storage, or null if not
171     available.
172  */
173 PetscErrorCode  PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
174 {
175   TRSPACE        *head;
176   char           *inew;
177   size_t         nsize;
178   PetscErrorCode ierr;
179 
180   PetscFunctionBegin;
181   /* Do not try to handle empty blocks */
182   if (!a) { *result = NULL; PetscFunctionReturn(0); }
183 
184   if (TRdebugLevel) {
185     ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
186   }
187 
188   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
189   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
190 
191   head  = (TRSPACE*)inew;
192   inew += sizeof(TrSPACE);
193 
194   if (TRhead) TRhead->prev = head;
195   head->next   = TRhead;
196   TRhead       = head;
197   head->prev   = NULL;
198   head->size   = nsize;
199   head->id     = TRid;
200   head->lineno = lineno;
201 
202   head->filename                 = filename;
203   head->functionname             = function;
204   head->classid                  = CLASSID_VALUE;
205   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
206 
207   TRallocated += nsize;
208   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
209   if (PetscLogMemory) {
210     PetscInt i;
211     for (i=0; i<NumTRMaxMems; i++) {
212       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
213     }
214   }
215   TRfrags++;
216 
217 #if defined(PETSC_USE_DEBUG)
218   if (PetscStackActive()) {
219     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
220     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
221     head->stack.line[head->stack.currentsize-2] = lineno;
222   } else {
223     head->stack.currentsize = 0;
224   }
225 #endif
226 
227   /*
228          Allow logging of all mallocs made
229   */
230   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
231     if (!PetscLogMalloc) {
232       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
233       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
234 
235       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
236       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
237 
238       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
239       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
240     }
241     PetscLogMallocLength[PetscLogMalloc]     = nsize;
242     PetscLogMallocFile[PetscLogMalloc]       = filename;
243     PetscLogMallocFunction[PetscLogMalloc++] = function;
244   }
245   *result = (void*)inew;
246   PetscFunctionReturn(0);
247 }
248 
249 
250 /*
251    PetscTrFreeDefault - Free with tracing.
252 
253    Input Parameters:
254 .   a    - pointer to a block allocated with PetscTrMalloc
255 .   lineno - line number where used.  Use __LINE__ for this
256 .   file  - file name where used.  Use __FILE__ for this
257  */
258 PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
259 {
260   char           *a = (char*)aa;
261   TRSPACE        *head;
262   char           *ahead;
263   PetscErrorCode ierr;
264   PetscClassId   *nend;
265 
266   PetscFunctionBegin;
267   /* Do not try to handle empty blocks */
268   if (!a) PetscFunctionReturn(0);
269 
270   if (TRdebugLevel) {
271     ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr);
272   }
273 
274   ahead = a;
275   a     = a - sizeof(TrSPACE);
276   head  = (TRSPACE*)a;
277 
278   if (head->classid != CLASSID_VALUE) {
279     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
280     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
281     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
282   }
283   nend = (PetscClassId*)(ahead + head->size);
284   if (*nend != CLASSID_VALUE) {
285     if (*nend == ALREADY_FREED) {
286       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
287       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
288       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
289         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
290       } else {
291         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
292       }
293       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
294     } else {
295       /* Damaged tail */
296       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
297       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
298       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
299       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
300     }
301   }
302   /* Mark the location freed */
303   *nend = ALREADY_FREED;
304   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
305   if (line > 0 && line < 50000) {
306     head->lineno       = line;
307     head->filename     = file;
308     head->functionname = function;
309   } else {
310     head->lineno = -head->lineno;
311   }
312   if (TRallocated < head->size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
313   TRallocated -= head->size;
314   TRfrags--;
315   if (head->prev) head->prev->next = head->next;
316   else TRhead = head->next;
317 
318   if (head->next) head->next->prev = head->prev;
319   ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr);
320   PetscFunctionReturn(0);
321 }
322 
323 
324 
325 /*
326   PetscTrReallocDefault - Realloc with tracing.
327 
328   Input Parameters:
329 + len      - number of bytes to allocate
330 . lineno   - line number where used.  Use __LINE__ for this
331 . filename - file name where used.  Use __FILE__ for this
332 - result   - double aligned pointer to initial storage.
333 
334   Output Parameter:
335 . result - double aligned pointer to requested storage, or null if not available.
336 
337   Level: developer
338 
339 .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
340 */
341 PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
342 {
343   char           *a = (char *) *result;
344   TRSPACE        *head;
345   char           *ahead, *inew;
346   PetscClassId   *nend;
347   size_t         nsize;
348   PetscErrorCode ierr;
349 
350   PetscFunctionBegin;
351   /* Realloc to zero = free */
352   if (!len) {
353     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
354     *result = NULL;
355     PetscFunctionReturn(0);
356   }
357   /* Realloc with NULL = malloc */
358   if (!*result) {
359     ierr = PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);CHKERRQ(ierr);
360     PetscFunctionReturn(0);
361   }
362 
363   if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);}
364 
365   ahead = a;
366   a     = a - sizeof(TrSPACE);
367   head  = (TRSPACE *) a;
368   inew  = a;
369 
370   if (head->classid != CLASSID_VALUE) {
371     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
372     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
373     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
374   }
375   nend = (PetscClassId *)(ahead + head->size);
376   if (*nend != CLASSID_VALUE) {
377     if (*nend == ALREADY_FREED) {
378       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
379       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
380       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
381         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
382       } else {
383         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
384       }
385       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
386     } else {
387       /* Damaged tail */
388       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
389       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
390       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
391       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
392     }
393   }
394 
395   TRallocated -= head->size;
396   TRfrags--;
397   if (head->prev) head->prev->next = head->next;
398   else TRhead = head->next;
399   if (head->next) head->next->prev = head->prev;
400 
401   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
402   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
403 
404   head  = (TRSPACE*)inew;
405   inew += sizeof(TrSPACE);
406 
407   if (TRhead) TRhead->prev = head;
408   head->next   = TRhead;
409   TRhead       = head;
410   head->prev   = NULL;
411   head->size   = nsize;
412   head->id     = TRid;
413   head->lineno = lineno;
414 
415   head->filename                 = filename;
416   head->functionname             = function;
417   head->classid                  = CLASSID_VALUE;
418   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
419 
420   TRallocated += nsize;
421   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
422   if (PetscLogMemory) {
423     PetscInt i;
424     for (i=0; i<NumTRMaxMems; i++) {
425       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
426     }
427   }
428   TRfrags++;
429 
430 #if defined(PETSC_USE_DEBUG)
431   if (PetscStackActive()) {
432     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
433     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
434     head->stack.line[head->stack.currentsize-2] = lineno;
435   } else {
436     head->stack.currentsize = 0;
437   }
438 #endif
439 
440   /*
441          Allow logging of all mallocs made
442   */
443   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
444     if (!PetscLogMalloc) {
445       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
446       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
447 
448       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
449       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
450 
451       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
452       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
453     }
454     PetscLogMallocLength[PetscLogMalloc]     = nsize;
455     PetscLogMallocFile[PetscLogMalloc]       = filename;
456     PetscLogMallocFunction[PetscLogMalloc++] = function;
457   }
458   *result = (void*)inew;
459   PetscFunctionReturn(0);
460 }
461 
462 
463 /*@C
464     PetscMemoryView - Shows the amount of memory currently being used
465         in a communicator.
466 
467     Collective on PetscViewer
468 
469     Input Parameter:
470 +    viewer - the viewer that defines the communicator
471 -    message - string printed before values
472 
473     Options Database:
474 +    -malloc - have PETSc track how much memory it has allocated
475 -    -memory_view - during PetscFinalize() have this routine called
476 
477     Level: intermediate
478 
479 .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage()
480  @*/
481 PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
482 {
483   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
484   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
485   PetscErrorCode ierr;
486   MPI_Comm       comm;
487 
488   PetscFunctionBegin;
489   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
490   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
491   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
492   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
493   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
494   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
495   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
496   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
497   if (resident && residentmax && allocated) {
498     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
499     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
500     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
501     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr);
502     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
503     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
504     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
505     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
506     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
507     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
508     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
509     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);CHKERRQ(ierr);
510     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
511     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
512     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
513     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
514   } else if (resident && residentmax) {
515     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
516     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
517     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
518     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr);
519     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
520     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
521     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
522     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
523   } else if (resident && allocated) {
524     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
525     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
526     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
527     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
528     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
529     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
530     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
531     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
532     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
533   } else if (allocated) {
534     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
535     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
536     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
537     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
538     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
539     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
540   } else {
541     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
542   }
543   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
544   PetscFunctionReturn(0);
545 }
546 
547 /*@
548     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
549 
550     Not Collective
551 
552     Output Parameters:
553 .   space - number of bytes currently allocated
554 
555     Level: intermediate
556 
557 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
558           PetscMemoryGetMaximumUsage()
559  @*/
560 PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
561 {
562   PetscFunctionBegin;
563   *space = (PetscLogDouble) TRallocated;
564   PetscFunctionReturn(0);
565 }
566 
567 /*@
568     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
569         during this run.
570 
571     Not Collective
572 
573     Output Parameters:
574 .   space - maximum number of bytes ever allocated at one time
575 
576     Level: intermediate
577 
578 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
579           PetscMallocPushMaximumUsage()
580  @*/
581 PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
582 {
583   PetscFunctionBegin;
584   *space = (PetscLogDouble) TRMaxMem;
585   PetscFunctionReturn(0);
586 }
587 
588 /*@
589     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
590 
591     Not Collective
592 
593     Input Parameter:
594 .   event - an event id; this is just for error checking
595 
596     Level: developer
597 
598 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
599           PetscMallocPopMaximumUsage()
600  @*/
601 PetscErrorCode  PetscMallocPushMaximumUsage(int event)
602 {
603   PetscFunctionBegin;
604   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
605   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
606   TRMaxMemsEvents[NumTRMaxMems-1] = event;
607   PetscFunctionReturn(0);
608 }
609 
610 /*@
611     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
612 
613     Not Collective
614 
615     Input Parameter:
616 .   event - an event id; this is just for error checking
617 
618     Output Parameter:
619 .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
620 
621     Level: developer
622 
623 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
624           PetscMallocPushMaximumUsage()
625  @*/
626 PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
627 {
628   PetscFunctionBegin;
629   *mu = 0;
630   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
631   if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
632   *mu = TRMaxMems[NumTRMaxMems];
633   PetscFunctionReturn(0);
634 }
635 
636 #if defined(PETSC_USE_DEBUG)
637 /*@C
638    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
639 
640    Collective on PETSC_COMM_WORLD
641 
642    Input Parameter:
643 .    ptr - the memory location
644 
645    Output Paramter:
646 .    stack - the stack indicating where the program allocated this memory
647 
648    Level: intermediate
649 
650 .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
651 @*/
652 PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
653 {
654   TRSPACE *head;
655 
656   PetscFunctionBegin;
657   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
658   *stack = &head->stack;
659   PetscFunctionReturn(0);
660 }
661 #else
662 PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
663 {
664   PetscFunctionBegin;
665   *stack = NULL;
666   PetscFunctionReturn(0);
667 }
668 #endif
669 
670 /*@C
671    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
672    printed is: size of space (in bytes), address of space, id of space,
673    file in which space was allocated, and line number at which it was
674    allocated.
675 
676    Collective on PETSC_COMM_WORLD
677 
678    Input Parameter:
679 .  fp  - file pointer.  If fp is NULL, stdout is assumed.
680 
681    Options Database Key:
682 .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
683 
684    Level: intermediate
685 
686    Fortran Note:
687    The calling sequence in Fortran is PetscMallocDump(integer ierr)
688    The fp defaults to stdout.
689 
690    Notes:
691     uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
692           has been freed.
693 
694 .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
695 @*/
696 PetscErrorCode  PetscMallocDump(FILE *fp)
697 {
698   TRSPACE        *head;
699   size_t         libAlloc = 0;
700   PetscErrorCode ierr;
701   PetscMPIInt    rank;
702 
703   PetscFunctionBegin;
704   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
705   if (!fp) fp = PETSC_STDOUT;
706   head = TRhead;
707   while (head) {
708     libAlloc += head->size;
709     head = head->next;
710   }
711   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
712   head = TRhead;
713   while (head) {
714     PetscBool isLib;
715 
716     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
717     if (!isLib) {
718       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
719 #if defined(PETSC_USE_DEBUG)
720       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
721 #endif
722     }
723     head = head->next;
724   }
725   PetscFunctionReturn(0);
726 }
727 
728 /* ---------------------------------------------------------------------------- */
729 
730 /*@
731     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
732 
733     Not Collective
734 
735     Options Database Key:
736 +  -malloc_log <filename> - Activates PetscMallocDumpLog()
737 -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
738 
739     Level: advanced
740 
741 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
742 @*/
743 PetscErrorCode PetscMallocSetDumpLog(void)
744 {
745   PetscErrorCode ierr;
746 
747   PetscFunctionBegin;
748   PetscLogMalloc = 0;
749 
750   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
751   PetscFunctionReturn(0);
752 }
753 
754 /*@
755     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
756 
757     Not Collective
758 
759     Input Arguments:
760 .   logmin - minimum allocation size to log, or PETSC_DEFAULT
761 
762     Options Database Key:
763 +  -malloc_log <filename> - Activates PetscMallocDumpLog()
764 -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
765 
766     Level: advanced
767 
768 .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
769 @*/
770 PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
771 {
772   PetscErrorCode ierr;
773 
774   PetscFunctionBegin;
775   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
776   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
777   PetscLogMallocThreshold = (size_t)logmin;
778   PetscFunctionReturn(0);
779 }
780 
781 /*@
782     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
783 
784     Not Collective
785 
786     Output Arguments
787 .   logging - PETSC_TRUE if logging is active
788 
789     Options Database Key:
790 .  -malloc_log - Activates PetscMallocDumpLog()
791 
792     Level: advanced
793 
794 .seealso: PetscMallocDump(), PetscMallocDumpLog()
795 @*/
796 PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
797 {
798 
799   PetscFunctionBegin;
800   *logging = (PetscBool)(PetscLogMalloc >= 0);
801   PetscFunctionReturn(0);
802 }
803 
804 /*@C
805     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
806        PetscMemoryGetMaximumUsage()
807 
808     Collective on PETSC_COMM_WORLD
809 
810     Input Parameter:
811 .   fp - file pointer; or NULL
812 
813     Options Database Key:
814 .  -malloc_log - Activates PetscMallocDumpLog()
815 
816     Level: advanced
817 
818    Fortran Note:
819    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
820    The fp defaults to stdout.
821 
822 .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
823 @*/
824 PetscErrorCode  PetscMallocDumpLog(FILE *fp)
825 {
826   PetscInt       i,j,n,dummy,*perm;
827   size_t         *shortlength;
828   int            *shortcount,err;
829   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
830   PetscBool      match;
831   const char     **shortfunction;
832   PetscLogDouble rss;
833   MPI_Status     status;
834   PetscErrorCode ierr;
835 
836   PetscFunctionBegin;
837   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
838   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
839   /*
840        Try to get the data printed in order by processor. This will only sometimes work
841   */
842   err = fflush(fp);
843   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
844 
845   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
846   if (rank) {
847     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
848   }
849 
850   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()");
851 
852   if (!fp) fp = PETSC_STDOUT;
853   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
854   if (rss) {
855     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);
856   } else {
857     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);
858   }
859   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
860   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
861   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
862   for (i=0,n=0; i<PetscLogMalloc; i++) {
863     for (j=0; j<n; j++) {
864       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
865       if (match) {
866         shortlength[j] += PetscLogMallocLength[i];
867         shortcount[j]++;
868         goto foundit;
869       }
870     }
871     shortfunction[n] = PetscLogMallocFunction[i];
872     shortlength[n]   = PetscLogMallocLength[i];
873     shortcount[n]    = 1;
874     n++;
875 foundit:;
876   }
877 
878   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
879   for (i=0; i<n; i++) perm[i] = i;
880   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
881 
882   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
883   for (i=0; i<n; i++) {
884     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr);
885   }
886   free(perm);
887   free(shortlength);
888   free(shortcount);
889   free((char**)shortfunction);
890   err = fflush(fp);
891   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
892   if (rank != size-1) {
893     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
894   }
895   PetscFunctionReturn(0);
896 }
897 
898 /* ---------------------------------------------------------------------------- */
899 
900 /*@
901     PetscMallocDebug - Turns on/off debugging for the memory management routines.
902 
903     Not Collective
904 
905     Input Parameter:
906 .   level - PETSC_TRUE or PETSC_FALSE
907 
908    Level: intermediate
909 
910 .seealso: CHKMEMQ(), PetscMallocValidate()
911 @*/
912 PetscErrorCode  PetscMallocDebug(PetscBool level)
913 {
914   PetscFunctionBegin;
915   TRdebugLevel = level;
916   PetscFunctionReturn(0);
917 }
918 
919 /*@
920     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
921 
922     Not Collective
923 
924     Output Parameter:
925 .    flg - PETSC_TRUE if any debugger
926 
927    Level: intermediate
928 
929     Note that by default, the debug version always does some debugging unless you run with -malloc no
930 
931 
932 .seealso: CHKMEMQ(), PetscMallocValidate()
933 @*/
934 PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
935 {
936   PetscFunctionBegin;
937   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
938   else *flg = PETSC_FALSE;
939   PetscFunctionReturn(0);
940 }
941