Actual source code: mtr.c


  2: /*
  3:      Interface to malloc() and free(). This code allows for logging of memory usage and some error checking
  4: */
  5: #include <petsc/private/petscimpl.h>
  6: #include <petscviewer.h>
  7: #if defined(PETSC_HAVE_MALLOC_H)
  8: #include <malloc.h>
  9: #endif

 11: /*
 12:      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
 13: */
 14: PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,PetscBool,int,const char[],const char[],void**);
 15: PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]);
 16: PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**);

 18: #define CLASSID_VALUE  ((PetscClassId) 0xf0e0d0c9)
 19: #define ALREADY_FREED  ((PetscClassId) 0x0f0e0d9c)

 21: /*  this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */
 22: typedef struct _trSPACE {
 23:   size_t          size, rsize; /* Aligned size and requested size */
 24:   int             id;
 25:   int             lineno;
 26:   const char      *filename;
 27:   const char      *functionname;
 28:   PetscClassId    classid;
 29: #if defined(PETSC_USE_DEBUG)
 30:   PetscStack      stack;
 31: #endif
 32:   struct _trSPACE *next,*prev;
 33: } TRSPACE;

 35: /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
 36:    It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
 37: */
 38: #define HEADER_BYTES  ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))

 40: /* This union is used to insure that the block passed to the user retains
 41:    a minimum alignment of PETSC_MEMALIGN.
 42: */
 43: typedef union {
 44:   TRSPACE sp;
 45:   char    v[HEADER_BYTES];
 46: } TrSPACE;

 48: #define MAXTRMAXMEMS 50
 49: static size_t    TRallocated          = 0;
 50: static int       TRfrags              = 0;
 51: static TRSPACE   *TRhead              = NULL;
 52: static int       TRid                 = 0;
 53: static PetscBool TRdebugLevel         = PETSC_FALSE;
 54: static PetscBool TRdebugIinitializenan= PETSC_FALSE;
 55: static PetscBool TRrequestedSize      = PETSC_FALSE;
 56: static size_t    TRMaxMem             = 0;
 57: static int       NumTRMaxMems         = 0;
 58: static size_t    TRMaxMems[MAXTRMAXMEMS];
 59: static int       TRMaxMemsEvents[MAXTRMAXMEMS];
 60: /*
 61:       Arrays to log information on mallocs for PetscMallocView()
 62: */
 63: static int        PetscLogMallocMax       = 10000;
 64: static int        PetscLogMalloc          = -1;
 65: static size_t     PetscLogMallocThreshold = 0;
 66: static size_t     *PetscLogMallocLength;
 67: static const char **PetscLogMallocFile,**PetscLogMallocFunction;
 68: static int        PetscLogMallocTrace          = -1;
 69: static size_t     PetscLogMallocTraceThreshold = 0;
 70: static PetscViewer PetscLogMallocTraceViewer   = NULL;

 72: /*@C
 73:    PetscMallocValidate - Test the memory for corruption.  This can be called at any time between PetscInitialize() and PetscFinalize()

 75:    Input Parameters:
 76: +  line - line number where call originated.
 77: .  function - name of function calling
 78: -  file - file where function is

 80:    Return value:
 81:    The number of errors detected.

 83:    Options Database:.
 84: +  -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0
 85: -  -malloc_debug - turns this feature on anytime

 87:    Output Effect:
 88:    Error messages are written to stdout.

 90:    Level: advanced

 92:    Notes:
 93:     This is only run if PetscMallocSetDebug() has been called which is set by -malloc_test (if debugging is turned on) or -malloc_debug (any time)

 95:     You should generally use CHKMEMQ as a short cut for calling this  routine.

 97:     The Fortran calling sequence is simply PetscMallocValidate(ierr)

 99:    No output is generated if there are no problems detected.

101:    Developers Note:
102:      Uses the flg TRdebugLevel (set as the first argument to PetscMallocSetDebug()) to determine if it should run

104: .seealso: CHKMEMQ

106: @*/
107: PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
108: {
109:   TRSPACE      *head,*lasthead;
110:   char         *a;
111:   PetscClassId *nend;

113:   if (!TRdebugLevel) return 0;
114:   head = TRhead; lasthead = NULL;
115:   if (head && head->prev) {
116:     (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
117:     (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n",head,head->prev);
118:     return PETSC_ERR_MEMC;
119:   }
120:   while (head) {
121:     if (head->classid != CLASSID_VALUE) {
122:       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
123:       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
124:       (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n");
125:       if (lasthead) {
126:         a    = (char*)(((TrSPACE*)head) + 1);
127:         (*PetscErrorPrintf)("Last intact block [id=%d(%.0f)] at address %p allocated in %s() at %s:%d\n",lasthead->id,(PetscLogDouble)lasthead->size,a,lasthead->functionname,lasthead->filename,lasthead->lineno);
128:       }
129:       abort();
130:       return PETSC_ERR_MEMC;
131:     }
132:     a    = (char*)(((TrSPACE*)head) + 1);
133:     nend = (PetscClassId*)(a + head->size);
134:     if (*nend != CLASSID_VALUE) {
135:       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
136:       if (*nend == ALREADY_FREED) {
137:         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
138:         return PETSC_ERR_MEMC;
139:       } else {
140:         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
141:         (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
142:         return PETSC_ERR_MEMC;
143:       }
144:     }
145:     if (head->prev && head->prev != lasthead) {
146:       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
147:       (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n",head->prev,lasthead);
148:       (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n",lasthead->functionname,lasthead->filename,lasthead->lineno);
149:       (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
150:       return PETSC_ERR_MEMC;
151:     }
152:     lasthead = head;
153:     head     = head->next;
154:   }
155:   return 0;
156: }

158: /*
159:     PetscTrMallocDefault - Malloc with tracing.

161:     Input Parameters:
162: +   a   - number of bytes to allocate
163: .   lineno - line number where used.  Use __LINE__ for this
164: -   filename  - file name where used.  Use __FILE__ for this

166:     Returns:
167:     double aligned pointer to requested storage, or null if not  available.
168:  */
169: PetscErrorCode  PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
170: {
171:   TRSPACE        *head;
172:   char           *inew;
173:   size_t         nsize;

176:   /* Do not try to handle empty blocks */
177:   if (!a) { *result = NULL; return 0; }

179:   PetscMallocValidate(lineno,function,filename); if (ierr) return ierr;

181:   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
182:   PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);

184:   head  = (TRSPACE*)inew;
185:   inew += sizeof(TrSPACE);

187:   if (TRhead) TRhead->prev = head;
188:   head->next   = TRhead;
189:   TRhead       = head;
190:   head->prev   = NULL;
191:   head->size   = nsize;
192:   head->rsize  = a;
193:   head->id     = TRid++;
194:   head->lineno = lineno;

196:   head->filename                 = filename;
197:   head->functionname             = function;
198:   head->classid                  = CLASSID_VALUE;
199:   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;

201:   TRallocated += TRrequestedSize ? head->rsize : head->size;
202:   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
203:   if (PetscLogMemory) {
204:     PetscInt i;
205:     for (i=0; i<NumTRMaxMems; i++) {
206:       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
207:     }
208:   }
209:   TRfrags++;

211: #if defined(PETSC_USE_DEBUG)
212:   PetscStackCopy(&petscstack,&head->stack);
213:   head->stack.line[head->stack.currentsize-2] = lineno;
214: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
215:   if (!clear && TRdebugIinitializenan) {
216:     size_t     i, n = a/sizeof(PetscReal);
217:     PetscReal *s = (PetscReal*) inew;
218:     /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
219: #if defined(PETSC_USE_REAL_SINGLE)
220:     int        nas = 0x7F800002;
221: #else
222:     PetscInt64 nas = 0x7FF0000000000002;
223: #endif
224:     for (i=0; i<n; i++) {
225:       memcpy(s+i,&nas,sizeof(PetscReal));
226:     }
227:   }
228: #endif
229: #endif

231:   /*
232:          Allow logging of all mallocs made.
233:          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
234:   */
235:   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
236:     if (!PetscLogMalloc) {
237:       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));

240:       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));

243:       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
245:     }
246:     PetscLogMallocLength[PetscLogMalloc]     = nsize;
247:     PetscLogMallocFile[PetscLogMalloc]       = filename;
248:     PetscLogMallocFunction[PetscLogMalloc++] = function;
249:   }
250:   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) {
251:     PetscViewerASCIIPrintf(PetscLogMallocTraceViewer,"Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null");
252:   }
253:   *result = (void*)inew;
254:   return 0;
255: }

257: /*
258:    PetscTrFreeDefault - Free with tracing.

260:    Input Parameters:
261: .   a    - pointer to a block allocated with PetscTrMalloc
262: .   lineno - line number where used.  Use __LINE__ for this
263: .   filename  - file name where used.  Use __FILE__ for this
264:  */
265: PetscErrorCode  PetscTrFreeDefault(void *aa,int lineno,const char function[],const char filename[])
266: {
267:   char           *a = (char*)aa;
268:   TRSPACE        *head;
269:   char           *ahead;
270:   size_t         asize;
271:   PetscClassId   *nend;

273:   /* Do not try to handle empty blocks */
274:   if (!a) return 0;

276:   PetscMallocValidate(lineno,function,filename);

278:   ahead = a;
279:   a     = a - sizeof(TrSPACE);
280:   head  = (TRSPACE*)a;

282:   if (head->classid != CLASSID_VALUE) {
283:     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
284:     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
285:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
286:   }
287:   nend = (PetscClassId*)(ahead + head->size);
288:   if (*nend != CLASSID_VALUE) {
289:     if (*nend == ALREADY_FREED) {
290:       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
291:       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
292:       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
293:         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
294:       } else {
295:         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
296:       }
297:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
298:     } else {
299:       /* Damaged tail */
300:       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
301:       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
302:       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
303:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
304:     }
305:   }
306:   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
307:     PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null");
308:   }
309:   /* Mark the location freed */
310:   *nend = ALREADY_FREED;
311:   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
312:   if (lineno > 0 && lineno < 50000) {
313:     head->lineno       = lineno;
314:     head->filename     = filename;
315:     head->functionname = function;
316:   } else {
317:     head->lineno = -head->lineno;
318:   }
319:   asize = TRrequestedSize ? head->rsize : head->size;
321:   TRallocated -= asize;
322:   TRfrags--;
323:   if (head->prev) head->prev->next = head->next;
324:   else TRhead = head->next;

326:   if (head->next) head->next->prev = head->prev;
327:   PetscFreeAlign(a,lineno,function,filename);
328:   return 0;
329: }

331: /*
332:   PetscTrReallocDefault - Realloc with tracing.

334:   Input Parameters:
335: + len      - number of bytes to allocate
336: . lineno   - line number where used.  Use __LINE__ for this
337: . filename - file name where used.  Use __FILE__ for this
338: - result - original memory

340:   Output Parameter:
341: . result - double aligned pointer to requested storage, or null if not available.

343:   Level: developer

345: .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
346: */
347: PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
348: {
349:   char           *a = (char *) *result;
350:   TRSPACE        *head;
351:   char           *ahead, *inew;
352:   PetscClassId   *nend;
353:   size_t         nsize;

356:   /* Realloc requests zero space so just free the current space */
357:   if (!len) {
358:     PetscTrFreeDefault(*result,lineno,function,filename);
359:     *result = NULL;
360:     return 0;
361:   }
362:   /* If the orginal space was NULL just use the regular malloc() */
363:   if (!*result) {
364:     PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);
365:     return 0;
366:   }

368:   PetscMallocValidate(lineno,function,filename); if (ierr) return ierr;

370:   ahead = a;
371:   a     = a - sizeof(TrSPACE);
372:   head  = (TRSPACE *) a;
373:   inew  = a;

375:   if (head->classid != CLASSID_VALUE) {
376:     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
377:     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
378:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
379:   }
380:   nend = (PetscClassId *)(ahead + head->size);
381:   if (*nend != CLASSID_VALUE) {
382:     if (*nend == ALREADY_FREED) {
383:       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
384:       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
385:       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
386:         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
387:       } else {
388:         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
389:       }
390:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
391:     } else {
392:       /* Damaged tail */
393:       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
394:       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
395:       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
396:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
397:     }
398:   }

400:   /* remove original reference to the memory allocated from the PETSc debugging heap */
401:   TRallocated -= TRrequestedSize ? head->rsize : head->size;
402:   TRfrags--;
403:   if (head->prev) head->prev->next = head->next;
404:   else TRhead = head->next;
405:   if (head->next) head->next->prev = head->prev;

407:   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
408:   PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);

410:   head  = (TRSPACE*)inew;
411:   inew += sizeof(TrSPACE);

413:   if (TRhead) TRhead->prev = head;
414:   head->next   = TRhead;
415:   TRhead       = head;
416:   head->prev   = NULL;
417:   head->size   = nsize;
418:   head->rsize  = len;
419:   head->id     = TRid++;
420:   head->lineno = lineno;

422:   head->filename                 = filename;
423:   head->functionname             = function;
424:   head->classid                  = CLASSID_VALUE;
425:   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;

427:   TRallocated += TRrequestedSize ? head->rsize : head->size;
428:   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
429:   if (PetscLogMemory) {
430:     PetscInt i;
431:     for (i=0; i<NumTRMaxMems; i++) {
432:       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
433:     }
434:   }
435:   TRfrags++;

437: #if defined(PETSC_USE_DEBUG)
438:   PetscStackCopy(&petscstack,&head->stack);
439:   head->stack.line[head->stack.currentsize-2] = lineno;
440: #endif

442:   /*
443:          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
444:          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
445:   */
446:   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
447:     if (!PetscLogMalloc) {
448:       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));

451:       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));

454:       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
456:     }
457:     PetscLogMallocLength[PetscLogMalloc]     = nsize;
458:     PetscLogMallocFile[PetscLogMalloc]       = filename;
459:     PetscLogMallocFunction[PetscLogMalloc++] = function;
460:   }
461:   *result = (void*)inew;
462:   return 0;
463: }

465: /*@C
466:     PetscMemoryView - Shows the amount of memory currently being used in a communicator.

468:     Collective on PetscViewer

470:     Input Parameters:
471: +    viewer - the viewer that defines the communicator
472: -    message - string printed before values

474:     Options Database:
475: +    -malloc_debug - have PETSc track how much memory it has allocated
476: -    -memory_view - during PetscFinalize() have this routine called

478:     Level: intermediate

480: .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
481:  @*/
482: PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
483: {
484:   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
485:   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
486:   MPI_Comm       comm;

488:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
489:   PetscMallocGetCurrentUsage(&allocated);
490:   PetscMallocGetMaximumUsage(&allocatedmax);
491:   PetscMemoryGetCurrentUsage(&resident);
492:   PetscMemoryGetMaximumUsage(&residentmax);
493:   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
494:   PetscObjectGetComm((PetscObject)viewer,&comm);
495:   PetscViewerASCIIPrintf(viewer,"%s",message);
496:   if (resident && residentmax && allocated) {
497:     MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
498:     MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
499:     MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
500:     PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
501:     MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
502:     MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
503:     MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
504:     PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
505:     MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
506:     MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
507:     MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
508:     PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);
509:     MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
510:     MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
511:     MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
512:     PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
513:   } else if (resident && residentmax) {
514:     MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
515:     MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
516:     MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
517:     PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);
518:     MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
519:     MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
520:     MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
521:     PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
522:   } else if (resident && allocated) {
523:     MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
524:     MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
525:     MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
526:     PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);
527:     MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
528:     MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
529:     MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
530:     PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
531:     PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
532:   } else if (allocated) {
533:     MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);
534:     MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);
535:     MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);
536:     PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);
537:     PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");
538:     PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");
539:   } else {
540:     PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");
541:   }
542:   PetscViewerFlush(viewer);
543:   return 0;
544: }

546: /*@
547:     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed

549:     Not Collective

551:     Output Parameters:
552: .   space - number of bytes currently allocated

554:     Level: intermediate

556: .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
557:           PetscMemoryGetMaximumUsage()
558:  @*/
559: PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
560: {
561:   *space = (PetscLogDouble) TRallocated;
562:   return 0;
563: }

565: /*@
566:     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
567:         during this run.

569:     Not Collective

571:     Output Parameters:
572: .   space - maximum number of bytes ever allocated at one time

574:     Level: intermediate

576: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
577:           PetscMallocPushMaximumUsage()
578:  @*/
579: PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
580: {
581:   *space = (PetscLogDouble) TRMaxMem;
582:   return 0;
583: }

585: /*@
586:     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event

588:     Not Collective

590:     Input Parameter:
591: .   event - an event id; this is just for error checking

593:     Level: developer

595: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
596:           PetscMallocPopMaximumUsage()
597:  @*/
598: PetscErrorCode  PetscMallocPushMaximumUsage(int event)
599: {
600:   if (++NumTRMaxMems > MAXTRMAXMEMS) return 0;
601:   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
602:   TRMaxMemsEvents[NumTRMaxMems-1] = event;
603:   return 0;
604: }

606: /*@
607:     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event

609:     Not Collective

611:     Input Parameter:
612: .   event - an event id; this is just for error checking

614:     Output Parameter:
615: .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event

617:     Level: developer

619: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
620:           PetscMallocPushMaximumUsage()
621:  @*/
622: PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
623: {
624:   *mu = 0;
625:   if (NumTRMaxMems-- > MAXTRMAXMEMS) return 0;
627:   *mu = TRMaxMems[NumTRMaxMems];
628:   return 0;
629: }

631: #if defined(PETSC_USE_DEBUG)
632: /*@C
633:    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory

635:    Collective on PETSC_COMM_WORLD

637:    Input Parameter:
638: .    ptr - the memory location

640:    Output Parameter:
641: .    stack - the stack indicating where the program allocated this memory

643:    Level: intermediate

645: .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView()
646: @*/
647: PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
648: {
649:   TRSPACE *head;

651:   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
652:   *stack = &head->stack;
653:   return 0;
654: }
655: #else
656: PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
657: {
658:   *stack = NULL;
659:   return 0;
660: }
661: #endif

663: /*@C
664:    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
665:    printed is: size of space (in bytes), address of space, id of space,
666:    file in which space was allocated, and line number at which it was
667:    allocated.

669:    Not Collective

671:    Input Parameter:
672: .  fp  - file pointer.  If fp is NULL, stdout is assumed.

674:    Options Database Key:
675: .  -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()

677:    Level: intermediate

679:    Fortran Note:
680:    The calling sequence in Fortran is PetscMallocDump(integer ierr)
681:    The fp defaults to stdout.

683:    Notes:
684:      Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.

686:      When called in PetscFinalize() dumps only the allocations that have not been properly freed

688:      PetscMallocView() prints a list of all memory ever allocated

690: .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
691: @*/
692: PetscErrorCode  PetscMallocDump(FILE *fp)
693: {
694:   TRSPACE        *head;
695:   size_t         libAlloc = 0;
696:   PetscMPIInt    rank;

698:   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
699:   if (!fp) fp = PETSC_STDOUT;
700:   head = TRhead;
701:   while (head) {
702:     libAlloc += TRrequestedSize ? head->rsize : head->size;
703:     head = head->next;
704:   }
705:   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
706:   head = TRhead;
707:   while (head) {
708:     PetscBool isLib;

710:     PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);
711:     if (!isLib) {
712:       fprintf(fp,"[%2d] %.0f bytes %s() at %s:%d\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->filename,head->lineno);
713: #if defined(PETSC_USE_DEBUG)
714:       PetscStackPrint(&head->stack,fp);
715: #endif
716:     }
717:     head = head->next;
718:   }
719:   return 0;
720: }

722: /*@
723:     PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view

725:     Not Collective

727:     Input Parameter:
728: .   logmin - minimum allocation size to log, or PETSC_DEFAULT

730:     Options Database Key:
731: +  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
732: .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
733: -  -log_view_memory - view the memory usage also with the -log_view option

735:     Level: advanced

737:     Notes: Must be called after PetscMallocSetDebug()

739:     Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available

741: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
742: @*/
743: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
744: {
745:   PetscLogMalloc = 0;
746:   PetscMemorySetGetMaximumUsage();
747:   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
748:   PetscLogMallocThreshold = (size_t)logmin;
749:   return 0;
750: }

752: /*@
753:     PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged

755:     Not Collective

757:     Output Parameter
758: .   logging - PETSC_TRUE if logging is active

760:     Options Database Key:
761: .  -malloc_view <optional filename> - Activates PetscMallocView()

763:     Level: advanced

765: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
766: @*/
767: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
768: {
769:   *logging = (PetscBool)(PetscLogMalloc >= 0);
770:   return 0;
771: }

773: /*@
774:   PetscMallocTraceSet - Trace all calls to PetscMalloc()

776:   Not Collective

778:   Input Parameters:
779: + viewer - The viewer to use for tracing, or NULL to use stdout
780: . active - Flag to activate or deactivate tracing
781: - logmin - The smallest memory size that will be logged

783:   Note:
784:   The viewer should not be collective.

786:   Level: advanced

788: .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
789: @*/
790: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
791: {
792:   if (!active) {PetscLogMallocTrace = -1; return 0;}
793:   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
794:   PetscLogMallocTrace = 0;
795:   PetscMemorySetGetMaximumUsage();
796:   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
797:   PetscLogMallocTraceThreshold = (size_t) logmin;
798:   return 0;
799: }

801: /*@
802:   PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced

804:   Not Collective

806:   Output Parameter:
807: . logging - PETSC_TRUE if logging is active

809:   Options Database Key:
810: . -malloc_view <optional filename> - Activates PetscMallocView()

812:   Level: advanced

814: .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
815: @*/
816: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
817: {
818:   *logging = (PetscBool) (PetscLogMallocTrace >= 0);
819:   return 0;
820: }

822: /*@C
823:     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
824:        PetscMemoryGetMaximumUsage()

826:     Not Collective

828:     Input Parameter:
829: .   fp - file pointer; or NULL

831:     Options Database Key:
832: .  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()

834:     Level: advanced

836:    Fortran Note:
837:    The calling sequence in Fortran is PetscMallocView(integer ierr)
838:    The fp defaults to stdout.

840:    Notes:
841:      PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated

843:      PetscMemoryView() gives a brief summary of current memory usage

845: .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
846: @*/
847: PetscErrorCode  PetscMallocView(FILE *fp)
848: {
849:   PetscInt       i,j,n,*perm;
850:   size_t         *shortlength;
851:   int            *shortcount,err;
852:   PetscMPIInt    rank;
853:   PetscBool      match;
854:   const char     **shortfunction;
855:   PetscLogDouble rss;

857:   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
858:   err = fflush(fp);


863:   if (!fp) fp = PETSC_STDOUT;
864:   PetscMemoryGetMaximumUsage(&rss);
865:   if (rss) {
866:     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
867:   } else {
868:     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
869:   }
873:   for (i=0,n=0; i<PetscLogMalloc; i++) {
874:     for (j=0; j<n; j++) {
875:       PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);
876:       if (match) {
877:         shortlength[j] += PetscLogMallocLength[i];
878:         shortcount[j]++;
879:         goto foundit;
880:       }
881:     }
882:     shortfunction[n] = PetscLogMallocFunction[i];
883:     shortlength[n]   = PetscLogMallocLength[i];
884:     shortcount[n]    = 1;
885:     n++;
886: foundit:;
887:   }

890:   for (i=0; i<n; i++) perm[i] = i;
891:   PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);

893:   (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
894:   for (i=0; i<n; i++) {
895:     (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
896:   }
897:   free(perm);
898:   free(shortlength);
899:   free(shortcount);
900:   free((char**)shortfunction);
901:   err = fflush(fp);
903:   return 0;
904: }

906: /* ---------------------------------------------------------------------------- */

908: /*@
909:     PetscMallocSetDebug - Set's PETSc memory debugging

911:     Not Collective

913:     Input Parameters:
914: +   eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
915: -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays

917:     Options Database:
918: +   -malloc_debug <true or false> - turns on or off debugging
919: .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
920: .   -malloc_view_threshold t - log only allocations larger than t
921: .   -malloc_dump <filename> - print a list of all memory that has not been freed
922: .   -malloc no - (deprecated) same as -malloc_debug no
923: -   -malloc_log - (deprecated) same as -malloc_view

925:    Level: developer

927:     Notes: This is called in PetscInitialize() and should not be called elsewhere

929: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
930: @*/
931: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
932: {
934:   PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);

936:   TRallocated         = 0;
937:   TRfrags             = 0;
938:   TRhead              = NULL;
939:   TRid                = 0;
940:   TRdebugLevel        = eachcall;
941:   TRMaxMem            = 0;
942:   PetscLogMallocMax   = 10000;
943:   PetscLogMalloc      = -1;
944:   TRdebugIinitializenan = initializenan;
945:   return 0;
946: }

948: /*@
949:     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.

951:     Not Collective

953:     Output Parameters:
954: +    basic - doing basic debugging
955: .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
956: -    initializenan - initializes memory with NaN

958:    Level: intermediate

960:    Notes:
961:      By default, the debug version always does some debugging unless you run with -malloc_debug no

963: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
964: @*/
965: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
966: {
967:   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
968:   if (eachcall) *eachcall           = TRdebugLevel;
969:   if (initializenan) *initializenan = TRdebugIinitializenan;
970:   return 0;
971: }

973: /*@
974:   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size

976:   Not Collective

978:   Input Parameter:
979: . flg - PETSC_TRUE to log the requested memory size

981:   Options Database:
982: . -malloc_requested_size <bool> - Sets this flag

984:   Level: developer

986: .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
987: @*/
988: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
989: {
990:   TRrequestedSize = flg;
991:   return 0;
992: }

994: /*@
995:   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size

997:   Not Collective

999:   Output Parameter:
1000: . flg - PETSC_TRUE if we log the requested memory size

1002:   Level: developer

1004: .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1005: @*/
1006: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1007: {
1008:   *flg = TRrequestedSize;
1009:   return 0;
1010: }