Actual source code: mtr.c

petsc-main 2021-03-06
Report Typos and Errors

  2: /*
  3:      Interface to malloc() and free(). This code allows for logging of memory usage and some error checking
  4: */
  5: #include <petscsys.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 at %s() line %d in %s\n",function,line,file);
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 at  %s() line %d in %s\n",function,line,file);
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) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
126:       return PETSC_ERR_MEMC;
127:     }
128:     a    = (char*)(((TrSPACE*)head) + 1);
129:     nend = (PetscClassId*)(a + head->size);
130:     if (*nend != CLASSID_VALUE) {
131:       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
132:       if (*nend == ALREADY_FREED) {
133:         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
134:         return PETSC_ERR_MEMC;
135:       } else {
136:         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
137:         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
138:         return PETSC_ERR_MEMC;
139:       }
140:     }
141:     if (head->prev && head->prev != lasthead) {
142:       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
143:       (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n",head->prev,lasthead);
144:       return PETSC_ERR_MEMC;
145:     }
146:     if (head->next && head != head->next->prev) {
147:       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
148:       (*PetscErrorPrintf)("Next memory header %p has invalid back pointer %p, should be %p\n",head->next,head->next->prev,head);
149:       return PETSC_ERR_MEMC;
150:     }
151:     lasthead = head;
152:     head     = head->next;
153:   }
154:   return 0;
155: }

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

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

165:     Returns:
166:     double aligned pointer to requested storage, or null if not  available.
167:  */
168: PetscErrorCode  PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
169: {
170:   TRSPACE        *head;
171:   char           *inew;
172:   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) PetscFunctionReturn(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:   if (PetscStackActive()) {
213:     PetscStackCopy(petscstack,&head->stack);
215:     head->stack.line[head->stack.currentsize-2] = lineno;
216:   } else {
217:     head->stack.currentsize = 0;
218:   }
219: #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
220:   if (!clear && TRdebugIinitializenan) {
221:     size_t     i, n = a/sizeof(PetscReal);
222:     PetscReal *s = (PetscReal*) inew;
223:     /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
224: #if defined(PETSC_USE_REAL_SINGLE)
225:     int        nas = 0x7F800002;
226: #else
227:     PetscInt64 nas = 0x7FF0000000000002;
228: #endif
229:     for (i=0; i<n; i++) {
230:       memcpy(s+i,&nas,sizeof(PetscReal));
231:     }
232:   }
233: #endif
234: #endif

236:   /*
237:          Allow logging of all mallocs made.
238:          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
239:   */
240:   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
241:     if (!PetscLogMalloc) {
242:       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
243:       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");

245:       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
246:       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");

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

262: /*
263:    PetscTrFreeDefault - Free with tracing.

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

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

283:   PetscMallocValidate(lineno,function,filename);

285:   ahead = a;
286:   a     = a - sizeof(TrSPACE);
287:   head  = (TRSPACE*)a;

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

333:   if (head->next) head->next->prev = head->prev;
334:   PetscFreeAlign(a,lineno,function,filename);
335:   return(0);
336: }

338: /*
339:   PetscTrReallocDefault - Realloc with tracing.

341:   Input Parameters:
342: + len      - number of bytes to allocate
343: . lineno   - line number where used.  Use __LINE__ for this
344: . filename - file name where used.  Use __FILE__ for this
345: - result - original memory

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

350:   Level: developer

352: .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
353: */
354: PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
355: {
356:   char           *a = (char *) *result;
357:   TRSPACE        *head;
358:   char           *ahead, *inew;
359:   PetscClassId   *nend;
360:   size_t         nsize;

364:   /* Realloc requests zero space so just free the current space */
365:   if (!len) {
366:     PetscTrFreeDefault(*result,lineno,function,filename);
367:     *result = NULL;
368:     return(0);
369:   }
370:   /* If the orginal space was NULL just use the regular malloc() */
371:   if (!*result) {
372:     PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);
373:     return(0);
374:   }

376:   PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);

378:   ahead = a;
379:   a     = a - sizeof(TrSPACE);
380:   head  = (TRSPACE *) a;
381:   inew  = a;

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

408:   /* remove original reference to the memory allocated from the PETSc debugging heap */
409:   TRallocated -= TRrequestedSize ? head->rsize : head->size;
410:   TRfrags--;
411:   if (head->prev) head->prev->next = head->next;
412:   else TRhead = head->next;
413:   if (head->next) head->next->prev = head->prev;

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

418:   head  = (TRSPACE*)inew;
419:   inew += sizeof(TrSPACE);

421:   if (TRhead) TRhead->prev = head;
422:   head->next   = TRhead;
423:   TRhead       = head;
424:   head->prev   = NULL;
425:   head->size   = nsize;
426:   head->rsize  = len;
427:   head->id     = TRid;
428:   head->lineno = lineno;

430:   head->filename                 = filename;
431:   head->functionname             = function;
432:   head->classid                  = CLASSID_VALUE;
433:   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;

435:   TRallocated += TRrequestedSize ? head->rsize : head->size;
436:   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
437:   if (PetscLogMemory) {
438:     PetscInt i;
439:     for (i=0; i<NumTRMaxMems; i++) {
440:       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
441:     }
442:   }
443:   TRfrags++;

445: #if defined(PETSC_USE_DEBUG)
446:   if (PetscStackActive()) {
447:     PetscStackCopy(petscstack,&head->stack);
449:     head->stack.line[head->stack.currentsize-2] = lineno;
450:   } else {
451:     head->stack.currentsize = 0;
452:   }
453: #endif

455:   /*
456:          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
457:          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
458:   */
459:   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
460:     if (!PetscLogMalloc) {
461:       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
462:       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");

464:       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
465:       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");

467:       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
468:       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
469:     }
470:     PetscLogMallocLength[PetscLogMalloc]     = nsize;
471:     PetscLogMallocFile[PetscLogMalloc]       = filename;
472:     PetscLogMallocFunction[PetscLogMalloc++] = function;
473:   }
474:   *result = (void*)inew;
475:   return(0);
476: }

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

481:     Collective on PetscViewer

483:     Input Parameter:
484: +    viewer - the viewer that defines the communicator
485: -    message - string printed before values

487:     Options Database:
488: +    -malloc_debug - have PETSc track how much memory it has allocated
489: -    -memory_view - during PetscFinalize() have this routine called

491:     Level: intermediate

493: .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
494:  @*/
495: PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
496: {
497:   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
498:   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
500:   MPI_Comm       comm;

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

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

564:     Not Collective

566:     Output Parameters:
567: .   space - number of bytes currently allocated

569:     Level: intermediate

571: .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
572:           PetscMemoryGetMaximumUsage()
573:  @*/
574: PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
575: {
577:   *space = (PetscLogDouble) TRallocated;
578:   return(0);
579: }

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

585:     Not Collective

587:     Output Parameters:
588: .   space - maximum number of bytes ever allocated at one time

590:     Level: intermediate

592: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
593:           PetscMallocPushMaximumUsage()
594:  @*/
595: PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
596: {
598:   *space = (PetscLogDouble) TRMaxMem;
599:   return(0);
600: }

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

605:     Not Collective

607:     Input Parameter:
608: .   event - an event id; this is just for error checking

610:     Level: developer

612: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
613:           PetscMallocPopMaximumUsage()
614:  @*/
615: PetscErrorCode  PetscMallocPushMaximumUsage(int event)
616: {
618:   if (++NumTRMaxMems > MAXTRMAXMEMS) return(0);
619:   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
620:   TRMaxMemsEvents[NumTRMaxMems-1] = event;
621:   return(0);
622: }

624: /*@
625:     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event

627:     Not Collective

629:     Input Parameter:
630: .   event - an event id; this is just for error checking

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

635:     Level: developer

637: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
638:           PetscMallocPushMaximumUsage()
639:  @*/
640: PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
641: {
643:   *mu = 0;
644:   if (NumTRMaxMems-- > MAXTRMAXMEMS) return(0);
645:   if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
646:   *mu = TRMaxMems[NumTRMaxMems];
647:   return(0);
648: }

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

654:    Collective on PETSC_COMM_WORLD

656:    Input Parameter:
657: .    ptr - the memory location

659:    Output Parameter:
660: .    stack - the stack indicating where the program allocated this memory

662:    Level: intermediate

664: .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView()
665: @*/
666: PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
667: {
668:   TRSPACE *head;

671:   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
672:   *stack = &head->stack;
673:   return(0);
674: }
675: #else
676: PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
677: {
679:   *stack = NULL;
680:   return(0);
681: }
682: #endif

684: /*@C
685:    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
686:    printed is: size of space (in bytes), address of space, id of space,
687:    file in which space was allocated, and line number at which it was
688:    allocated.

690:    Not Collective

692:    Input Parameter:
693: .  fp  - file pointer.  If fp is NULL, stdout is assumed.

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

698:    Level: intermediate

700:    Fortran Note:
701:    The calling sequence in Fortran is PetscMallocDump(integer ierr)
702:    The fp defaults to stdout.

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

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

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

711: .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
712: @*/
713: PetscErrorCode  PetscMallocDump(FILE *fp)
714: {
715:   TRSPACE        *head;
716:   size_t         libAlloc = 0;
718:   PetscMPIInt    rank;

721:   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
722:   if (!fp) fp = PETSC_STDOUT;
723:   head = TRhead;
724:   while (head) {
725:     libAlloc += TRrequestedSize ? head->rsize : head->size;
726:     head = head->next;
727:   }
728:   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
729:   head = TRhead;
730:   while (head) {
731:     PetscBool isLib;

733:     PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);
734:     if (!isLib) {
735:       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->lineno,head->filename);
736: #if defined(PETSC_USE_DEBUG)
737:       PetscStackPrint(&head->stack,fp);
738: #endif
739:     }
740:     head = head->next;
741:   }
742:   return(0);
743: }

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

748:     Not Collective

750:     Input Arguments:
751: .   logmin - minimum allocation size to log, or PETSC_DEFAULT

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

758:     Level: advanced

760:     Notes: Must be called after PetscMallocSetDebug()

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

764: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
765: @*/
766: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
767: {

771:   PetscLogMalloc = 0;
772:   PetscMemorySetGetMaximumUsage();
773:   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
774:   PetscLogMallocThreshold = (size_t)logmin;
775:   return(0);
776: }

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

781:     Not Collective

783:     Output Arguments
784: .   logging - PETSC_TRUE if logging is active

786:     Options Database Key:
787: .  -malloc_view <optional filename> - Activates PetscMallocView()

789:     Level: advanced

791: .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
792: @*/
793: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
794: {

797:   *logging = (PetscBool)(PetscLogMalloc >= 0);
798:   return(0);
799: }

801: /*@
802:   PetscMallocTraceSet - Trace all calls to PetscMalloc()

804:   Not Collective

806:   Input Arguments:
807: + viewer - The viewer to use for tracing, or NULL to use stdout
808: . active - Flag to activate or deactivate tracing
809: - logmin - The smallest memory size that will be logged

811:   Note:
812:   The viewer should not be collective.

814:   Level: advanced

816: .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
817: @*/
818: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
819: {

823:   if (!active) {PetscLogMallocTrace = -1; return(0);}
824:   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
825:   PetscLogMallocTrace = 0;
826:   PetscMemorySetGetMaximumUsage();
827:   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
828:   PetscLogMallocTraceThreshold = (size_t) logmin;
829:   return(0);
830: }

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

835:   Not Collective

837:   Output Argument:
838: . logging - PETSC_TRUE if logging is active

840:   Options Database Key:
841: . -malloc_view <optional filename> - Activates PetscMallocView()

843:   Level: advanced

845: .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
846: @*/
847: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
848: {

851:   *logging = (PetscBool) (PetscLogMallocTrace >= 0);
852:   return(0);
853: }

855: /*@C
856:     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
857:        PetscMemoryGetMaximumUsage()

859:     Not Collective

861:     Input Parameter:
862: .   fp - file pointer; or NULL

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

867:     Level: advanced

869:    Fortran Note:
870:    The calling sequence in Fortran is PetscMallocView(integer ierr)
871:    The fp defaults to stdout.

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

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

878: .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
879: @*/
880: PetscErrorCode  PetscMallocView(FILE *fp)
881: {
882:   PetscInt       i,j,n,*perm;
883:   size_t         *shortlength;
884:   int            *shortcount,err;
885:   PetscMPIInt    rank;
886:   PetscBool      match;
887:   const char     **shortfunction;
888:   PetscLogDouble rss;

892:   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
893:   err = fflush(fp);
894:   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");

896:   if (PetscLogMalloc < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocView() called without call to PetscMallocViewSet() this is often due to\n                      setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");

898:   if (!fp) fp = PETSC_STDOUT;
899:   PetscMemoryGetMaximumUsage(&rss);
900:   if (rss) {
901:     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
902:   } else {
903:     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
904:   }
905:   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
906:   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
907:   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
908:   for (i=0,n=0; i<PetscLogMalloc; i++) {
909:     for (j=0; j<n; j++) {
910:       PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);
911:       if (match) {
912:         shortlength[j] += PetscLogMallocLength[i];
913:         shortcount[j]++;
914:         goto foundit;
915:       }
916:     }
917:     shortfunction[n] = PetscLogMallocFunction[i];
918:     shortlength[n]   = PetscLogMallocLength[i];
919:     shortcount[n]    = 1;
920:     n++;
921: foundit:;
922:   }

924:   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
925:   for (i=0; i<n; i++) perm[i] = i;
926:   PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);

928:   (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
929:   for (i=0; i<n; i++) {
930:     (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
931:   }
932:   free(perm);
933:   free(shortlength);
934:   free(shortcount);
935:   free((char**)shortfunction);
936:   err = fflush(fp);
937:   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
938:   return(0);
939: }

941: /* ---------------------------------------------------------------------------- */

943: /*@
944:     PetscMallocSetDebug - Set's PETSc memory debugging

946:     Not Collective

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

952:     Options Database:
953: +   -malloc_debug <true or false> - turns on or off debugging
954: .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
955: .   -malloc_view_threshold t - log only allocations larger than t
956: .   -malloc_dump <filename> - print a list of all memory that has not been freed
957: .   -malloc no - (deprecated) same as -malloc_debug no
958: -   -malloc_log - (deprecated) same as -malloc_view

960:    Level: developer

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

964: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
965: @*/
966: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
967: {

971:   if (PetscTrMalloc == PetscTrMallocDefault) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call this routine more than once, it can only be called in PetscInitialize()");
972:   PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);

974:   TRallocated         = 0;
975:   TRfrags             = 0;
976:   TRhead              = NULL;
977:   TRid                = 0;
978:   TRdebugLevel        = eachcall;
979:   TRMaxMem            = 0;
980:   PetscLogMallocMax   = 10000;
981:   PetscLogMalloc      = -1;
982:   TRdebugIinitializenan = initializenan;
983:   return(0);
984: }

986: /*@
987:     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.

989:     Not Collective

991:     Output Parameters:
992: +    basic - doing basic debugging
993: .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
994: -    initializenan - initializes memory with NaN

996:    Level: intermediate

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

1001: .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
1002: @*/
1003: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
1004: {
1006:   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
1007:   if (eachcall) *eachcall           = TRdebugLevel;
1008:   if (initializenan) *initializenan = TRdebugIinitializenan;
1009:   return(0);
1010: }

1012: /*@
1013:   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size

1015:   Not Collective

1017:   Input Parameter:
1018: . flg - PETSC_TRUE to log the requested memory size

1020:   Options Database:
1021: . -malloc_requested_size <bool> - Sets this flag

1023:   Level: developer

1025: .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
1026: @*/
1027: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1028: {
1030:   TRrequestedSize = flg;
1031:   return(0);
1032: }

1034: /*@
1035:   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size

1037:   Not Collective

1039:   Output Parameter:
1040: . flg - PETSC_TRUE if we log the requested memory size

1042:   Level: developer

1044: .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1045: @*/
1046: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1047: {
1049:   *flg = TRrequestedSize;
1050:   return(0);
1051: }