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