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) && !defined(PETSC_HAVE_THREADSAFETY)
 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: {
 45:   TRSPACE sp;
 46:   char    v[HEADER_BYTES];
 47: } TrSPACE;

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

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

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

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

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

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

 91:    Level: advanced

 93:    Notes:
 94:     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)

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

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

100:    Fortran Note:
101:     The Fortran calling sequence is simply `PetscMallocValidate(ierr)`

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

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

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

160: /*
161:     PetscTrMallocDefault - Malloc with tracing.

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

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

177:   PetscFunctionBegin;
178:   /* Do not try to handle empty blocks */
179:   if (!a) {
180:     *result = NULL;
181:     PetscFunctionReturn(PETSC_SUCCESS);
182:   }

184:   PetscCall(PetscMallocValidate(lineno, function, filename));

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

189:   head = (TRSPACE *)inew;
190:   inew += sizeof(TrSPACE);

192:   if (TRhead) TRhead->prev = head;
193:   head->next   = TRhead;
194:   TRhead       = head;
195:   head->prev   = NULL;
196:   head->size   = nsize;
197:   head->rsize  = a;
198:   head->id     = TRid++;
199:   head->lineno = lineno;

201:   head->filename                  = filename;
202:   head->functionname              = function;
203:   head->classid                   = CLASSID_VALUE;
204:   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;

206:   TRallocated += TRrequestedSize ? head->rsize : head->size;
207:   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
208:   if (PetscLogMemory) {
209:     PetscInt i;
210:     for (i = 0; i < NumTRMaxMems; i++) {
211:       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
212:     }
213:   }
214:   TRfrags++;

216: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
217:   PetscCall(PetscStackCopy(&petscstack, &head->stack));
218:   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
219:   head->stack.line[head->stack.currentsize - 2] = lineno;
220:   #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
221:   if (!clear && TRdebugIinitializenan) {
222:     size_t     i, n = a / sizeof(PetscReal);
223:     PetscReal *s = (PetscReal *)inew;
224:       /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
225:     #if defined(PETSC_USE_REAL_SINGLE)
226:     int nas = 0x7F800002;
227:     #else
228:     PetscInt64 nas = 0x7FF0000000000002;
229:     #endif
230:     for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
231:   }
232:   #endif
233: #endif

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

244:       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
245:       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");

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

259: /*
260:    PetscTrFreeDefault - Free with tracing.

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

275:   PetscFunctionBegin;
276:   /* Do not try to handle empty blocks */
277:   if (!a) PetscFunctionReturn(PETSC_SUCCESS);

279:   PetscCall(PetscMallocValidate(lineno, function, filename));

281:   ahead = a;
282:   a     = a - sizeof(TrSPACE);
283:   head  = (TRSPACE *)a;

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

329:   if (head->next) head->next->prev = head->prev;
330:   PetscCall(PetscFreeAlign(a, lineno, function, filename));
331:   PetscFunctionReturn(PETSC_SUCCESS);
332: }

334: /*
335:   PetscTrReallocDefault - Realloc with tracing.

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

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

346:   Level: developer

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

358:   PetscFunctionBegin;
359:   /* Realloc requests zero space so just free the current space */
360:   if (!len) {
361:     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
362:     *result = NULL;
363:     PetscFunctionReturn(PETSC_SUCCESS);
364:   }
365:   /* If the original space was NULL just use the regular malloc() */
366:   if (!*result) {
367:     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
368:     PetscFunctionReturn(PETSC_SUCCESS);
369:   }

371:   PetscCall(PetscMallocValidate(lineno, function, filename));

373:   ahead = a;
374:   a     = a - sizeof(TrSPACE);
375:   head  = (TRSPACE *)a;
376:   inew  = a;

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

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

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

413:   head = (TRSPACE *)inew;
414:   inew += sizeof(TrSPACE);

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

425:   head->filename                  = filename;
426:   head->functionname              = function;
427:   head->classid                   = CLASSID_VALUE;
428:   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;

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

440: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
441:   PetscCall(PetscStackCopy(&petscstack, &head->stack));
442:   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
443:   head->stack.line[head->stack.currentsize - 2] = lineno;
444: #endif

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

455:       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
456:       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");

458:       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
459:       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
460:     }
461:     PetscLogMallocLength[PetscLogMalloc]     = nsize;
462:     PetscLogMallocFile[PetscLogMalloc]       = filename;
463:     PetscLogMallocFunction[PetscLogMalloc++] = function;
464:   }
465:   *result = (void *)inew;
466:   PetscFunctionReturn(PETSC_SUCCESS);
467: }

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

472:     Collective

474:     Input Parameters:
475: +    viewer - the viewer that defines the communicator
476: -    message - string printed before values

478:     Options Database Keys:
479: +    -malloc_debug - have PETSc track how much memory it has allocated
480: .    -log_view_memory - print memory usage per event
481: -    -memory_view - during PetscFinalize() have this routine called

483:     Level: intermediate

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

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

552: /*@
553:     PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`

555:     Not Collective

557:     Output Parameter:
558: .   space - number of bytes currently allocated

560:     Level: intermediate

562: .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
563:           `PetscMemoryGetMaximumUsage()`
564:  @*/
565: PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
566: {
567:   PetscFunctionBegin;
568:   *space = (PetscLogDouble)TRallocated;
569:   PetscFunctionReturn(PETSC_SUCCESS);
570: }

572: /*@
573:     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
574:         during this run, the high water mark.

576:     Not Collective

578:     Output Parameter:
579: .   space - maximum number of bytes ever allocated at one time

581:     Level: intermediate

583: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
584:           `PetscMallocPushMaximumUsage()`
585:  @*/
586: PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
587: {
588:   PetscFunctionBegin;
589:   *space = (PetscLogDouble)TRMaxMem;
590:   PetscFunctionReturn(PETSC_SUCCESS);
591: }

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

596:     Not Collective

598:     Input Parameter:
599: .   event - an event id; this is just for error checking

601:     Level: developer

603: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
604:           `PetscMallocPopMaximumUsage()`
605:  @*/
606: PetscErrorCode PetscMallocPushMaximumUsage(int event)
607: {
608:   PetscFunctionBegin;
609:   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
610:   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
611:   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
612:   PetscFunctionReturn(PETSC_SUCCESS);
613: }

615: /*@
616:     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event

618:     Not Collective

620:     Input Parameter:
621: .   event - an event id; this is just for error checking

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

626:     Level: developer

628: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
629:           `PetscMallocPushMaximumUsage()`
630:  @*/
631: PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
632: {
633:   PetscFunctionBegin;
634:   *mu = 0;
635:   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
636:   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
637:   *mu = TRMaxMems[NumTRMaxMems];
638:   PetscFunctionReturn(PETSC_SUCCESS);
639: }

641: /*@C
642:    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory

644:    Collective on `PETSC_COMM_WORLD`

646:    Input Parameter:
647: .    ptr - the memory location

649:    Output Parameter:
650: .    stack - the stack indicating where the program allocated this memory

652:    Level: intermediate

654: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`
655: @*/
656: PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
657: {
658: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
659:   TRSPACE *head;

661:   PetscFunctionBegin;
662:   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
663:   *stack = &head->stack;
664:   PetscFunctionReturn(PETSC_SUCCESS);
665: #else
666:   *stack = NULL;
667:   return PETSC_SUCCESS;
668: #endif
669: }

671: /*@C
672:    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
673:    printed is: size of space (in bytes), address of space, id of space,
674:    file in which space was allocated, and line number at which it was
675:    allocated.

677:    Not Collective

679:    Input Parameter:
680: .  fp  - file pointer.  If fp is NULL, stdout is assumed.

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

685:    Level: intermediate

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

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

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

694:    Fortran Notes:
695:    The calling sequence in Fortran is PetscMallocDump(integer ierr)

697:    The `fp` defaults to stdout.

699: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`
700: @*/
701: PetscErrorCode PetscMallocDump(FILE *fp)
702: {
703:   TRSPACE    *head;
704:   size_t      libAlloc = 0;
705:   PetscMPIInt rank;

707:   PetscFunctionBegin;
708:   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
709:   if (!fp) fp = PETSC_STDOUT;
710:   head = TRhead;
711:   while (head) {
712:     libAlloc += TRrequestedSize ? head->rsize : head->size;
713:     head = head->next;
714:   }
715:   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
716:   head = TRhead;
717:   while (head) {
718:     PetscBool isLib;

720:     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
721:     if (!isLib) {
722:       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
723: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
724:       PetscCall(PetscStackPrint(&head->stack, fp));
725: #endif
726:     }
727:     head = head->next;
728:   }
729:   PetscFunctionReturn(PETSC_SUCCESS);
730: }

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

735:     Not Collective

737:     Input Parameter:
738: .   logmin - minimum allocation size to log, or `PETSC_DEFAULT`

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

745:     Level: advanced

747:     Notes:
748:     Must be called after `PetscMallocSetDebug()`

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

752: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`
753: @*/
754: PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
755: {
756:   PetscFunctionBegin;
757:   PetscLogMalloc = 0;
758:   PetscCall(PetscMemorySetGetMaximumUsage());
759:   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
760:   PetscLogMallocThreshold = (size_t)logmin;
761:   PetscFunctionReturn(PETSC_SUCCESS);
762: }

764: /*@
765:     PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged

767:     Not Collective

769:     Output Parameter
770: .   logging - `PETSC_TRUE` if logging is active

772:     Options Database Key:
773: .  -malloc_view <optional filename> - Activates `PetscMallocView()`

775:     Level: advanced

777: .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`
778: @*/
779: PetscErrorCode PetscMallocViewGet(PetscBool *logging)
780: {
781:   PetscFunctionBegin;
782:   *logging = (PetscBool)(PetscLogMalloc >= 0);
783:   PetscFunctionReturn(PETSC_SUCCESS);
784: }

786: /*@
787:   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`

789:   Not Collective

791:   Input Parameters:
792: + viewer - The viewer to use for tracing, or NULL to use stdout
793: . active - Flag to activate or deactivate tracing
794: - logmin - The smallest memory size that will be logged

796:   Note:
797:   The viewer should not be collective.

799:   Level: advanced

801: .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
802: @*/
803: PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
804: {
805:   PetscFunctionBegin;
806:   if (!active) {
807:     PetscLogMallocTrace = -1;
808:     PetscFunctionReturn(PETSC_SUCCESS);
809:   }
810:   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
811:   PetscLogMallocTrace       = 0;
812:   PetscCall(PetscMemorySetGetMaximumUsage());
813:   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
814:   PetscLogMallocTraceThreshold = (size_t)logmin;
815:   PetscFunctionReturn(PETSC_SUCCESS);
816: }

818: /*@
819:   PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced

821:   Not Collective

823:   Output Parameter:
824: . logging - `PETSC_TRUE` if logging is active

826:   Options Database Key:
827: . -malloc_view <optional filename> - Activates PetscMallocView()

829:   Level: advanced

831: .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
832: @*/
833: PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
834: {
835:   PetscFunctionBegin;
836:   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
837:   PetscFunctionReturn(PETSC_SUCCESS);
838: }

840: /*@C
841:     PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls
842:        `PetscMemoryGetMaximumUsage()`

844:     Not Collective

846:     Input Parameter:
847: .   fp - file pointer; or NULL

849:     Options Database Key:
850: .  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`

852:     Level: advanced

854:    Notes:
855:      `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated

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

859:    Fortran Notes:
860:    The calling sequence in Fortran is PetscMallocView(integer ierr)

862:    The `fp` defaults to stdout.

864: .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`
865: @*/
866: PetscErrorCode PetscMallocView(FILE *fp)
867: {
868:   PetscInt       i, j, n, *perm;
869:   size_t        *shortlength;
870:   int           *shortcount;
871:   PetscMPIInt    rank;
872:   PetscBool      match;
873:   const char   **shortfunction;
874:   PetscLogDouble rss;

876:   PetscFunctionBegin;
877:   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
878:   PetscCall(PetscFFlush(fp));

880:   PetscCheck(PetscLogMalloc >= 0, 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()");

882:   if (!fp) fp = PETSC_STDOUT;
883:   PetscCall(PetscMemoryGetMaximumUsage(&rss));
884:   if (rss) {
885:     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
886:   } else {
887:     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
888:   }
889:   if (PetscLogMalloc > 0) {
890:     shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
891:     PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
892:     shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
893:     PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
894:     shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
895:     PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
896:     for (i = 0, n = 0; i < PetscLogMalloc; i++) {
897:       for (j = 0; j < n; j++) {
898:         PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
899:         if (match) {
900:           shortlength[j] += PetscLogMallocLength[i];
901:           shortcount[j]++;
902:           goto foundit;
903:         }
904:       }
905:       shortfunction[n] = PetscLogMallocFunction[i];
906:       shortlength[n]   = PetscLogMallocLength[i];
907:       shortcount[n]    = 1;
908:       n++;
909:     foundit:;
910:     }

912:     perm = (PetscInt *)malloc(n * sizeof(PetscInt));
913:     PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
914:     for (i = 0; i < n; i++) perm[i] = i;
915:     PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));

917:     (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
918:     for (i = 0; i < n; i++) (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]);
919:     free(perm);
920:     free(shortlength);
921:     free(shortcount);
922:     free((char **)shortfunction);
923:   }
924:   PetscCall(PetscFFlush(fp));
925:   PetscFunctionReturn(PETSC_SUCCESS);
926: }

928: /* ---------------------------------------------------------------------------- */

930: /*@
931:     PetscMallocSetDebug - Set's PETSc memory debugging

933:     Not Collective

935:     Input Parameters:
936: +   eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
937: -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays

939:     Options Database Keys:
940: +   -malloc_debug <true or false> - turns on or off debugging
941: .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
942: .   -malloc_view_threshold t - log only allocations larger than t
943: .   -malloc_dump <filename> - print a list of all memory that has not been freed
944: .   -malloc no - (deprecated) same as -malloc_debug no
945: -   -malloc_log - (deprecated) same as -malloc_view

947:    Level: developer

949:     Note:
950:     This is called in `PetscInitialize()` and should not be called elsewhere

952: .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`
953: @*/
954: PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
955: {
956:   PetscFunctionBegin;
957:   PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
958:   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));

960:   TRallocated           = 0;
961:   TRfrags               = 0;
962:   TRhead                = NULL;
963:   TRid                  = 0;
964:   TRdebugLevel          = eachcall;
965:   TRMaxMem              = 0;
966:   PetscLogMallocMax     = 10000;
967:   PetscLogMalloc        = -1;
968:   TRdebugIinitializenan = initializenan;
969:   PetscFunctionReturn(PETSC_SUCCESS);
970: }

972: /*@
973:     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.

975:     Not Collective

977:     Output Parameters:
978: +    basic - doing basic debugging
979: .    eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
980: -    initializenan - initializes memory with NaN

982:    Level: intermediate

984:    Note:
985:      By default, the debug version always does some debugging unless you run with -malloc_debug no

987: .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`
988: @*/
989: PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
990: {
991:   PetscFunctionBegin;
992:   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
993:   if (eachcall) *eachcall = TRdebugLevel;
994:   if (initializenan) *initializenan = TRdebugIinitializenan;
995:   PetscFunctionReturn(PETSC_SUCCESS);
996: }

998: /*@
999:   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size

1001:   Not Collective

1003:   Input Parameter:
1004: . flg - `PETSC_TRUE` to log the requested memory size

1006:   Options Database Key:
1007: . -malloc_requested_size <bool> - Sets this flag

1009:   Level: developer

1011: .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`
1012: @*/
1013: PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1014: {
1015:   PetscFunctionBegin;
1016:   TRrequestedSize = flg;
1017:   PetscFunctionReturn(PETSC_SUCCESS);
1018: }

1020: /*@
1021:   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size

1023:   Not Collective

1025:   Output Parameter:
1026: . flg - `PETSC_TRUE` if we log the requested memory size

1028:   Level: developer

1030: .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()`
1031: @*/
1032: PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1033: {
1034:   PetscFunctionBegin;
1035:   *flg = TRrequestedSize;
1036:   PetscFunctionReturn(PETSC_SUCCESS);
1037: }