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:     The Fortran calling sequence is simply `PetscMallocValidate(ierr)`

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

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

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

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

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

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

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

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

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

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

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

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

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

215: #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
216:   PetscCall(PetscStackCopy(&petscstack, &head->stack));
217:   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
218:   head->stack.line[head->stack.currentsize - 2] = lineno;
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++) memcpy(s + i, &nas, sizeof(PetscReal));
230:   }
231:   #endif
232: #endif

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

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

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

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

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

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

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

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

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

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

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

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

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

345:   Level: developer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

471:     Collective

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

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

482:     Level: intermediate

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

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

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

554:     Not Collective

556:     Output Parameters:
557: .   space - number of bytes currently allocated

559:     Level: intermediate

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

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

575:     Not Collective

577:     Output Parameters:
578: .   space - maximum number of bytes ever allocated at one time

580:     Level: intermediate

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

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

595:     Not Collective

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

600:     Level: developer

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

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

617:     Not Collective

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

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

625:     Level: developer

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

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

643:    Collective on `PETSC_COMM_WORLD`

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

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

651:    Level: intermediate

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

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

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

676:    Not Collective

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

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

684:    Level: intermediate

686:    Fortran Note:
687:    The calling sequence in Fortran is PetscMallocDump(integer ierr)
688:    The fp defaults to stdout.

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

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

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

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

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

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

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

733:     Not Collective

735:     Input Parameter:
736: .   logmin - minimum allocation size to log, or `PETSC_DEFAULT`

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

743:     Level: advanced

745:     Notes:
746:     Must be called after `PetscMallocSetDebug()`

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

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

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

765:     Not Collective

767:     Output Parameter
768: .   logging - `PETSC_TRUE` if logging is active

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

773:     Level: advanced

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

784: /*@
785:   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`

787:   Not Collective

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

794:   Note:
795:   The viewer should not be collective.

797:   Level: advanced

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

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

819:   Not Collective

821:   Output Parameter:
822: . logging - `PETSC_TRUE` if logging is active

824:   Options Database Key:
825: . -malloc_view <optional filename> - Activates PetscMallocView()

827:   Level: advanced

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

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

842:     Not Collective

844:     Input Parameter:
845: .   fp - file pointer; or NULL

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

850:     Level: advanced

852:    Fortran Note:
853:    The calling sequence in Fortran is PetscMallocView(integer ierr)
854:    The fp defaults to stdout.

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

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

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

873:   PetscFunctionBegin;
874:   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
875:   PetscCall(PetscFFlush(fp));

877:   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()");

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

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

914:     (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
915:     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]]);
916:     free(perm);
917:     free(shortlength);
918:     free(shortcount);
919:     free((char **)shortfunction);
920:   }
921:   PetscCall(PetscFFlush(fp));
922:   PetscFunctionReturn(PETSC_SUCCESS);
923: }

925: /* ---------------------------------------------------------------------------- */

927: /*@
928:     PetscMallocSetDebug - Set's PETSc memory debugging

930:     Not Collective

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

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

944:    Level: developer

946:     Note:
947:     This is called in `PetscInitialize()` and should not be called elsewhere

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

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

969: /*@
970:     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.

972:     Not Collective

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

979:    Level: intermediate

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

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

995: /*@
996:   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size

998:   Not Collective

1000:   Input Parameter:
1001: . flg - `PETSC_TRUE` to log the requested memory size

1003:   Options Database Key:
1004: . -malloc_requested_size <bool> - Sets this flag

1006:   Level: developer

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

1017: /*@
1018:   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size

1020:   Not Collective

1022:   Output Parameter:
1023: . flg - `PETSC_TRUE` if we log the requested memory size

1025:   Level: developer

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