xref: /petsc/src/sys/memory/mtr.c (revision 0ed210f43def373c29ffa9a0cb4fff374d073236)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
392f119d6SBarry Smith      Interface to malloc() and free(). This code allows for logging of memory usage and some error checking
4e5c89e4eSSatish Balay */
527104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
6665c2dedSJed Brown #include <petscviewer.h>
7e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
8e5c89e4eSSatish Balay   #include <malloc.h>
9e5c89e4eSSatish Balay #endif
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay /*
12e5c89e4eSSatish Balay      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
13e5c89e4eSSatish Balay */
14071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
1595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
1695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
17e5c89e4eSSatish Balay 
180700a824SBarry Smith #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9)
190700a824SBarry Smith #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c)
20e5c89e4eSSatish Balay 
2192f119d6SBarry Smith /*  this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */
22e5c89e4eSSatish Balay typedef struct _trSPACE {
23608c71bfSMatthew G. Knepley   size_t       size, rsize; /* Aligned size and requested size */
24e5c89e4eSSatish Balay   int          id;
25e5c89e4eSSatish Balay   int          lineno;
26e5c89e4eSSatish Balay   const char  *filename;
27e5c89e4eSSatish Balay   const char  *functionname;
280700a824SBarry Smith   PetscClassId classid;
29dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
30e5c89e4eSSatish Balay   PetscStack stack;
31e5c89e4eSSatish Balay #endif
32e5c89e4eSSatish Balay   struct _trSPACE *next, *prev;
33e5c89e4eSSatish Balay } TRSPACE;
34e5c89e4eSSatish Balay 
3525b53cc9SJed Brown /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
3692f119d6SBarry Smith    It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
3725b53cc9SJed Brown */
38a64a8e02SBarry Smith #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
39e5c89e4eSSatish Balay 
4025b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains
4125b53cc9SJed Brown    a minimum alignment of PETSC_MEMALIGN.
4225b53cc9SJed Brown */
439371c9d4SSatish Balay typedef union
449371c9d4SSatish Balay {
45e5c89e4eSSatish Balay   TRSPACE sp;
4625b53cc9SJed Brown   char    v[HEADER_BYTES];
47e5c89e4eSSatish Balay } TrSPACE;
48e5c89e4eSSatish Balay 
49e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50
50e5c89e4eSSatish Balay static size_t    TRallocated           = 0;
51e5c89e4eSSatish Balay static int       TRfrags               = 0;
52f0ba7cfcSLisandro Dalcin static TRSPACE  *TRhead                = NULL;
53e5c89e4eSSatish Balay static int       TRid                  = 0;
54ace3abfcSBarry Smith static PetscBool TRdebugLevel          = PETSC_FALSE;
552d4ee042Sprj- static PetscBool TRdebugIinitializenan = PETSC_FALSE;
56608c71bfSMatthew G. Knepley static PetscBool TRrequestedSize       = PETSC_FALSE;
57e5c89e4eSSatish Balay static size_t    TRMaxMem              = 0;
58e3ed9ee7SBarry Smith static int       NumTRMaxMems          = 0;
59e3ed9ee7SBarry Smith static size_t    TRMaxMems[MAXTRMAXMEMS];
60e3ed9ee7SBarry Smith static int       TRMaxMemsEvents[MAXTRMAXMEMS];
61e5c89e4eSSatish Balay /*
6292f119d6SBarry Smith       Arrays to log information on mallocs for PetscMallocView()
63e5c89e4eSSatish Balay */
64f0ba7cfcSLisandro Dalcin static int          PetscLogMallocMax       = 10000;
65f0ba7cfcSLisandro Dalcin static int          PetscLogMalloc          = -1;
66574034a9SJed Brown static size_t       PetscLogMallocThreshold = 0;
67e5c89e4eSSatish Balay static size_t      *PetscLogMallocLength;
68efca3c55SSatish Balay static const char **PetscLogMallocFile, **PetscLogMallocFunction;
69608c71bfSMatthew G. Knepley static int          PetscLogMallocTrace          = -1;
70608c71bfSMatthew G. Knepley static size_t       PetscLogMallocTraceThreshold = 0;
71608c71bfSMatthew G. Knepley static PetscViewer  PetscLogMallocTraceViewer    = NULL;
72b022a5c1SBarry Smith 
73e5c89e4eSSatish Balay /*@C
74811af0c4SBarry Smith    PetscMallocValidate - Test the memory for corruption.  This can be called at any time between `PetscInitialize()` and `PetscFinalize()`
75e5c89e4eSSatish Balay 
7692f119d6SBarry Smith    Input Parameters:
77e5c89e4eSSatish Balay +  line - line number where call originated.
78e5c89e4eSSatish Balay .  function - name of function calling
79efca3c55SSatish Balay -  file - file where function is
80e5c89e4eSSatish Balay 
81e5c89e4eSSatish Balay    Return value:
82e5c89e4eSSatish Balay    The number of errors detected.
83e5c89e4eSSatish Balay 
84811af0c4SBarry Smith    Options Database Keys:.
85*0ed210f4SBarry Smith +  -malloc_test - turns this feature on when PETSc was not configured with `--with-debugging=0`
8692f119d6SBarry Smith -  -malloc_debug - turns this feature on anytime
8792f119d6SBarry Smith 
88e5c89e4eSSatish Balay    Level: advanced
89e5c89e4eSSatish Balay 
90e5c89e4eSSatish Balay    Notes:
91*0ed210f4SBarry Smith    Error messages are written to `stdout`.
92*0ed210f4SBarry Smith 
93*0ed210f4SBarry Smith    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)
9438548759SBarry Smith 
95811af0c4SBarry Smith   You should generally use `CHKMEMQ` as a short cut for calling this routine.
96e5c89e4eSSatish Balay 
97e5c89e4eSSatish Balay    No output is generated if there are no problems detected.
98e5c89e4eSSatish Balay 
9920f4b53cSBarry Smith    Fortran Note:
10020f4b53cSBarry Smith     The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
10120f4b53cSBarry Smith 
10292f119d6SBarry Smith    Developers Note:
10320f4b53cSBarry Smith      Uses the flg `TRdebugLevel` (set as the first argument to `PetscMallocSetDebug()`) to determine if it should run
10492f119d6SBarry Smith 
105*0ed210f4SBarry Smith .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()`
106e5c89e4eSSatish Balay @*/
107d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
108d71ae5a4SJacob Faibussowitsch {
1096c093d5bSvictor   TRSPACE      *head, *lasthead;
110e5c89e4eSSatish Balay   char         *a;
1110700a824SBarry Smith   PetscClassId *nend;
112e5c89e4eSSatish Balay 
1133ba16761SJacob Faibussowitsch   if (!TRdebugLevel) return PETSC_SUCCESS;
1149371c9d4SSatish Balay   head     = TRhead;
1159371c9d4SSatish Balay   lasthead = NULL;
1162cba8197SMatthew G. Knepley   if (head && head->prev) {
1173ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1183ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
1194ed0ab5bSBarry Smith     return PETSC_ERR_MEMC;
1202cba8197SMatthew G. Knepley   }
121e5c89e4eSSatish Balay   while (head) {
1220700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
1233ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1243ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
1253ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
126e269983cSBarry Smith       if (lasthead) {
127e269983cSBarry Smith         a = (char *)(((TrSPACE *)head) + 1);
1283ba16761SJacob Faibussowitsch         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));
129e269983cSBarry Smith       }
130e269983cSBarry Smith       abort();
1314ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
132e5c89e4eSSatish Balay     }
133e5c89e4eSSatish Balay     a    = (char *)(((TrSPACE *)head) + 1);
1340700a824SBarry Smith     nend = (PetscClassId *)(a + head->size);
1350700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
1363ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
137e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
1383ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
1394ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
140e5c89e4eSSatish Balay       } else {
1413ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
1423ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1434ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
144e5c89e4eSSatish Balay       }
145e5c89e4eSSatish Balay     }
1462cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
1473ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1483ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
1493ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
1503ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1514ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
1522cba8197SMatthew G. Knepley     }
1536c093d5bSvictor     lasthead = head;
154e5c89e4eSSatish Balay     head     = head->next;
155e5c89e4eSSatish Balay   }
1563ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
157e5c89e4eSSatish Balay }
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay /*
160e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
161e5c89e4eSSatish Balay 
162e5c89e4eSSatish Balay     Input Parameters:
163e5c89e4eSSatish Balay +   a   - number of bytes to allocate
164*0ed210f4SBarry Smith .   lineno - line number where used.  Use `__LINE__` for this
165*0ed210f4SBarry Smith -   filename  - file name where used.  Use `__FILE__` for this
166e5c89e4eSSatish Balay 
167*0ed210f4SBarry Smith     Output Parameter:
168*0ed210f4SBarry Smith     double aligned pointer to requested storage
169e5c89e4eSSatish Balay  */
170d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
171d71ae5a4SJacob Faibussowitsch {
172e5c89e4eSSatish Balay   TRSPACE *head;
173e5c89e4eSSatish Balay   char    *inew;
174e5c89e4eSSatish Balay   size_t   nsize;
175e5c89e4eSSatish Balay 
176e5c89e4eSSatish Balay   PetscFunctionBegin;
177f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
1789371c9d4SSatish Balay   if (!a) {
1799371c9d4SSatish Balay     *result = NULL;
1803ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1819371c9d4SSatish Balay   }
182f0ba7cfcSLisandro Dalcin 
18311cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
184e5c89e4eSSatish Balay 
18525b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
1869566063dSJacob Faibussowitsch   PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
187e3ed9ee7SBarry Smith 
188e5c89e4eSSatish Balay   head = (TRSPACE *)inew;
189e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
190e5c89e4eSSatish Balay 
191e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
192e5c89e4eSSatish Balay   head->next   = TRhead;
193e5c89e4eSSatish Balay   TRhead       = head;
194f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
195e5c89e4eSSatish Balay   head->size   = nsize;
196608c71bfSMatthew G. Knepley   head->rsize  = a;
197e269983cSBarry Smith   head->id     = TRid++;
198e5c89e4eSSatish Balay   head->lineno = lineno;
199e5c89e4eSSatish Balay 
200e5c89e4eSSatish Balay   head->filename                  = filename;
201e5c89e4eSSatish Balay   head->functionname              = function;
2020700a824SBarry Smith   head->classid                   = CLASSID_VALUE;
2030700a824SBarry Smith   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
204e5c89e4eSSatish Balay 
205608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
206a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
207e3ed9ee7SBarry Smith   if (PetscLogMemory) {
208e3ed9ee7SBarry Smith     PetscInt i;
209e3ed9ee7SBarry Smith     for (i = 0; i < NumTRMaxMems; i++) {
210e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
211e3ed9ee7SBarry Smith     }
212e3ed9ee7SBarry Smith   }
213e5c89e4eSSatish Balay   TRfrags++;
214e5c89e4eSSatish Balay 
215dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
2169566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
2172c9581d2SBarry Smith   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2182c9581d2SBarry Smith   head->stack.line[head->stack.currentsize - 2] = lineno;
21992f119d6SBarry Smith   #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2202d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
22192f119d6SBarry Smith     size_t     i, n = a / sizeof(PetscReal);
22292f119d6SBarry Smith     PetscReal *s = (PetscReal *)inew;
22392f119d6SBarry Smith       /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
22492f119d6SBarry Smith     #if defined(PETSC_USE_REAL_SINGLE)
225df282883SBarry Smith     int nas = 0x7F800002;
22692f119d6SBarry Smith     #else
22792f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22892f119d6SBarry Smith     #endif
229ad540459SPierre Jolivet     for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
23092f119d6SBarry Smith   }
23192f119d6SBarry Smith   #endif
232e5c89e4eSSatish Balay #endif
233e5c89e4eSSatish Balay 
234e5c89e4eSSatish Balay   /*
23592f119d6SBarry Smith          Allow logging of all mallocs made.
23692f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
237e5c89e4eSSatish Balay   */
238574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
239e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
240e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
24128b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
242a297a907SKarl Rupp 
243a2ea699eSBarry Smith       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
24428b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
245a297a907SKarl Rupp 
246a2ea699eSBarry Smith       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
24728b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
248e5c89e4eSSatish Balay     }
249e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
250e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
251e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
252e5c89e4eSSatish Balay   }
25348a46eb9SPierre Jolivet   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
254e5c89e4eSSatish Balay   *result = (void *)inew;
2553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
256e5c89e4eSSatish Balay }
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay /*
259e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
260e5c89e4eSSatish Balay 
261e5c89e4eSSatish Balay    Input Parameters:
262*0ed210f4SBarry Smith +   a    - pointer to a block allocated with `PetscTrMallocDefault()`
263*0ed210f4SBarry Smith .   lineno - line number where used.  Use `__LINE__` for this
264*0ed210f4SBarry Smith -   filename  - file name where used.  Use `__FILE__` for this
265*0ed210f4SBarry Smith 
266*0ed210f4SBarry Smith   Level: developer
267e5c89e4eSSatish Balay  */
268d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
269d71ae5a4SJacob Faibussowitsch {
270e5c89e4eSSatish Balay   char         *a = (char *)aa;
271e5c89e4eSSatish Balay   TRSPACE      *head;
272e5c89e4eSSatish Balay   char         *ahead;
273608c71bfSMatthew G. Knepley   size_t        asize;
2740700a824SBarry Smith   PetscClassId *nend;
275e5c89e4eSSatish Balay 
276e5c89e4eSSatish Balay   PetscFunctionBegin;
277e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
2783ba16761SJacob Faibussowitsch   if (!a) PetscFunctionReturn(PETSC_SUCCESS);
279e5c89e4eSSatish Balay 
2809566063dSJacob Faibussowitsch   PetscCall(PetscMallocValidate(lineno, function, filename));
281e5c89e4eSSatish Balay 
282e5c89e4eSSatish Balay   ahead = a;
283e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
284e5c89e4eSSatish Balay   head  = (TRSPACE *)a;
285e5c89e4eSSatish Balay 
2860700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
2873ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2883ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
289e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
290e5c89e4eSSatish Balay   }
2910700a824SBarry Smith   nend = (PetscClassId *)(ahead + head->size);
2920700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
293e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
2943ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2953ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
296e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
2973ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
298e5c89e4eSSatish Balay       } else {
2993ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
300e5c89e4eSSatish Balay       }
301e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
302e5c89e4eSSatish Balay     } else {
303e5c89e4eSSatish Balay       /* Damaged tail */
3043ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
3053ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
3063ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
307e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
308e5c89e4eSSatish Balay     }
309e5c89e4eSSatish Balay   }
310608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
3119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
312608c71bfSMatthew G. Knepley   }
313e5c89e4eSSatish Balay   /* Mark the location freed */
314e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
315e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
316608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
317608c71bfSMatthew G. Knepley     head->lineno       = lineno;
318608c71bfSMatthew G. Knepley     head->filename     = filename;
319e5c89e4eSSatish Balay     head->functionname = function;
320e5c89e4eSSatish Balay   } else {
321e5c89e4eSSatish Balay     head->lineno = -head->lineno;
322e5c89e4eSSatish Balay   }
323608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
32408401ef6SPierre Jolivet   PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
325608c71bfSMatthew G. Knepley   TRallocated -= asize;
326e5c89e4eSSatish Balay   TRfrags--;
327e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
328e5c89e4eSSatish Balay   else TRhead = head->next;
329e5c89e4eSSatish Balay 
330e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
3319566063dSJacob Faibussowitsch   PetscCall(PetscFreeAlign(a, lineno, function, filename));
3323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
333e5c89e4eSSatish Balay }
334e5c89e4eSSatish Balay 
3353221ece2SMatthew G. Knepley /*
3363221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3373221ece2SMatthew G. Knepley 
3383221ece2SMatthew G. Knepley   Input Parameters:
3393221ece2SMatthew G. Knepley + len      - number of bytes to allocate
340*0ed210f4SBarry Smith . lineno   - line number where used.  Use `__LINE__` for this
341*0ed210f4SBarry Smith . filename - file name where used.  Use `__FILE__` for this
34292f119d6SBarry Smith - result - original memory
3433221ece2SMatthew G. Knepley 
3443221ece2SMatthew G. Knepley   Output Parameter:
345*0ed210f4SBarry Smith . result - double aligned pointer to requested storage
3463221ece2SMatthew G. Knepley 
3473221ece2SMatthew G. Knepley   Level: developer
3483221ece2SMatthew G. Knepley 
349db781477SPatrick Sanan .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()`
3503221ece2SMatthew G. Knepley */
351d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
352d71ae5a4SJacob Faibussowitsch {
3533221ece2SMatthew G. Knepley   char         *a = (char *)*result;
3543221ece2SMatthew G. Knepley   TRSPACE      *head;
3553221ece2SMatthew G. Knepley   char         *ahead, *inew;
3563221ece2SMatthew G. Knepley   PetscClassId *nend;
3573221ece2SMatthew G. Knepley   size_t        nsize;
3583221ece2SMatthew G. Knepley 
3593221ece2SMatthew G. Knepley   PetscFunctionBegin;
36092f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
361c22f1541SToby Isaac   if (!len) {
3629566063dSJacob Faibussowitsch     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
363c22f1541SToby Isaac     *result = NULL;
3643ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
365c22f1541SToby Isaac   }
366da81f932SPierre Jolivet   /* If the original space was NULL just use the regular malloc() */
367f590eff4SLisandro Dalcin   if (!*result) {
3689566063dSJacob Faibussowitsch     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
3693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
370f590eff4SLisandro Dalcin   }
3713221ece2SMatthew G. Knepley 
37211cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
3733221ece2SMatthew G. Knepley 
3743221ece2SMatthew G. Knepley   ahead = a;
3753221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3763221ece2SMatthew G. Knepley   head  = (TRSPACE *)a;
3773221ece2SMatthew G. Knepley   inew  = a;
3783221ece2SMatthew G. Knepley 
3793221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3803ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3813ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
3823221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
3833221ece2SMatthew G. Knepley   }
3843221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3853221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3863221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3873ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3883ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
3893221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3903ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3913221ece2SMatthew G. Knepley       } else {
3923ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
3933221ece2SMatthew G. Knepley       }
3943221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
3953221ece2SMatthew G. Knepley     } else {
3963221ece2SMatthew G. Knepley       /* Damaged tail */
3973ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3983ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a));
3993ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
4003221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
4013221ece2SMatthew G. Knepley     }
4023221ece2SMatthew G. Knepley   }
4033221ece2SMatthew G. Knepley 
40492f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
405608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
4063221ece2SMatthew G. Knepley   TRfrags--;
4073221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4083221ece2SMatthew G. Knepley   else TRhead = head->next;
4093221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4103221ece2SMatthew G. Knepley 
4113221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
4129566063dSJacob Faibussowitsch   PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
4133221ece2SMatthew G. Knepley 
4143221ece2SMatthew G. Knepley   head = (TRSPACE *)inew;
4153221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4163221ece2SMatthew G. Knepley 
4173221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4183221ece2SMatthew G. Knepley   head->next   = TRhead;
4193221ece2SMatthew G. Knepley   TRhead       = head;
4203221ece2SMatthew G. Knepley   head->prev   = NULL;
4213221ece2SMatthew G. Knepley   head->size   = nsize;
422608c71bfSMatthew G. Knepley   head->rsize  = len;
423e269983cSBarry Smith   head->id     = TRid++;
4243221ece2SMatthew G. Knepley   head->lineno = lineno;
4253221ece2SMatthew G. Knepley 
4263221ece2SMatthew G. Knepley   head->filename                  = filename;
4273221ece2SMatthew G. Knepley   head->functionname              = function;
4283221ece2SMatthew G. Knepley   head->classid                   = CLASSID_VALUE;
4293221ece2SMatthew G. Knepley   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
4303221ece2SMatthew G. Knepley 
431608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4323221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
433e3ed9ee7SBarry Smith   if (PetscLogMemory) {
434e3ed9ee7SBarry Smith     PetscInt i;
435e3ed9ee7SBarry Smith     for (i = 0; i < NumTRMaxMems; i++) {
436e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
437e3ed9ee7SBarry Smith     }
438e3ed9ee7SBarry Smith   }
4393221ece2SMatthew G. Knepley   TRfrags++;
4403221ece2SMatthew G. Knepley 
441dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
4429566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
4433221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4443221ece2SMatthew G. Knepley   head->stack.line[head->stack.currentsize - 2] = lineno;
4453221ece2SMatthew G. Knepley #endif
4463221ece2SMatthew G. Knepley 
4473221ece2SMatthew G. Knepley   /*
44892f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
44992f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4503221ece2SMatthew G. Knepley   */
4513221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4523221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4533221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
45428b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4553221ece2SMatthew G. Knepley 
4563221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
45728b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4583221ece2SMatthew G. Knepley 
4593221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
46028b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4613221ece2SMatthew G. Knepley     }
4623221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4633221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4643221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4653221ece2SMatthew G. Knepley   }
4663221ece2SMatthew G. Knepley   *result = (void *)inew;
4673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4683221ece2SMatthew G. Knepley }
4693221ece2SMatthew G. Knepley 
470fe7fb379SMatthew Knepley /*@C
47192f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
472e5c89e4eSSatish Balay 
473c3339decSBarry Smith     Collective
474e5c89e4eSSatish Balay 
475d8d19677SJose E. Roman     Input Parameters:
476*0ed210f4SBarry Smith +    viewer - the viewer to output the information on
477e5c89e4eSSatish Balay -    message - string printed before values
478e5c89e4eSSatish Balay 
479811af0c4SBarry Smith     Options Database Keys:
48092f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
481*0ed210f4SBarry Smith .    -log_view_memory - print memory usage per event when `-log_view` is used
482*0ed210f4SBarry Smith -    -memory_view - during `PetscFinalize()` have this routine called
4830841954dSBarry Smith 
484e5c89e4eSSatish Balay     Level: intermediate
485e5c89e4eSSatish Balay 
486*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
487e5c89e4eSSatish Balay  @*/
488d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
489d71ae5a4SJacob Faibussowitsch {
4900841954dSBarry Smith   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax;
4910841954dSBarry Smith   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax;
492e5c89e4eSSatish Balay   MPI_Comm       comm;
493e5c89e4eSSatish Balay 
494e5c89e4eSSatish Balay   PetscFunctionBegin;
495e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4969566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&allocated));
4979566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4989566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&resident));
4999566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
500e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
5019566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
5029566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
503e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5119566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5149566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
5169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5179566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5189566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
520e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5249566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5259566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
529e5c89e4eSSatish Balay   } else if (resident && allocated) {
5309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
539e5c89e4eSSatish Balay   } else if (allocated) {
5409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5419566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
546e5c89e4eSSatish Balay   } else {
5479566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
548e5c89e4eSSatish Balay   }
5499566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
5503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
551e5c89e4eSSatish Balay }
552e5c89e4eSSatish Balay 
55346eb3923SBarry Smith /*@
554811af0c4SBarry Smith     PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
555e5c89e4eSSatish Balay 
556e5c89e4eSSatish Balay     Not Collective
557e5c89e4eSSatish Balay 
5582fe279fdSBarry Smith     Output Parameter:
559e5c89e4eSSatish Balay .   space - number of bytes currently allocated
560e5c89e4eSSatish Balay 
561e5c89e4eSSatish Balay     Level: intermediate
562e5c89e4eSSatish Balay 
563*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
564db781477SPatrick Sanan           `PetscMemoryGetMaximumUsage()`
565e5c89e4eSSatish Balay  @*/
566d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
567d71ae5a4SJacob Faibussowitsch {
568e5c89e4eSSatish Balay   PetscFunctionBegin;
569e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRallocated;
5703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
571e5c89e4eSSatish Balay }
572e5c89e4eSSatish Balay 
573dc37d89fSBarry Smith /*@
574811af0c4SBarry Smith     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
575811af0c4SBarry Smith         during this run, the high water mark.
576e5c89e4eSSatish Balay 
577e5c89e4eSSatish Balay     Not Collective
578e5c89e4eSSatish Balay 
5792fe279fdSBarry Smith     Output Parameter:
580e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
581e5c89e4eSSatish Balay 
582e5c89e4eSSatish Balay     Level: intermediate
583e5c89e4eSSatish Balay 
584*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
585db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
586e5c89e4eSSatish Balay  @*/
587d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
588d71ae5a4SJacob Faibussowitsch {
589e5c89e4eSSatish Balay   PetscFunctionBegin;
590e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRMaxMem;
5913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
592e5c89e4eSSatish Balay }
593e5c89e4eSSatish Balay 
594e3ed9ee7SBarry Smith /*@
595e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
596e3ed9ee7SBarry Smith 
597e3ed9ee7SBarry Smith     Not Collective
598e3ed9ee7SBarry Smith 
599e3ed9ee7SBarry Smith     Input Parameter:
600e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
601e3ed9ee7SBarry Smith 
602e3ed9ee7SBarry Smith     Level: developer
603e3ed9ee7SBarry Smith 
604*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
605db781477SPatrick Sanan           `PetscMallocPopMaximumUsage()`
606e3ed9ee7SBarry Smith  @*/
607d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event)
608d71ae5a4SJacob Faibussowitsch {
609e3ed9ee7SBarry Smith   PetscFunctionBegin;
6103ba16761SJacob Faibussowitsch   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
611e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
612e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
6133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
614e3ed9ee7SBarry Smith }
615e3ed9ee7SBarry Smith 
616e3ed9ee7SBarry Smith /*@
617e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
618e3ed9ee7SBarry Smith 
619e3ed9ee7SBarry Smith     Not Collective
620e3ed9ee7SBarry Smith 
621e3ed9ee7SBarry Smith     Input Parameter:
622e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
623e3ed9ee7SBarry Smith 
624e3ed9ee7SBarry Smith     Output Parameter:
625e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
626e3ed9ee7SBarry Smith 
627e3ed9ee7SBarry Smith     Level: developer
628e3ed9ee7SBarry Smith 
629*0ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
630db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
631e3ed9ee7SBarry Smith  @*/
632d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
633d71ae5a4SJacob Faibussowitsch {
634e3ed9ee7SBarry Smith   PetscFunctionBegin;
635e3ed9ee7SBarry Smith   *mu = 0;
6363ba16761SJacob Faibussowitsch   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
63708401ef6SPierre Jolivet   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
638e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
6393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
640e3ed9ee7SBarry Smith }
641e3ed9ee7SBarry Smith 
642a64a8e02SBarry Smith /*@C
643811af0c4SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
644a64a8e02SBarry Smith 
645*0ed210f4SBarry Smith    Not Collective
646a64a8e02SBarry Smith 
647a64a8e02SBarry Smith    Input Parameter:
648a64a8e02SBarry Smith .    ptr - the memory location
649a64a8e02SBarry Smith 
650fd292e60Sprj-    Output Parameter:
651a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
652a64a8e02SBarry Smith 
653a64a8e02SBarry Smith    Level: intermediate
654a64a8e02SBarry Smith 
655*0ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
656a64a8e02SBarry Smith @*/
657d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
658d71ae5a4SJacob Faibussowitsch {
659dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
660a64a8e02SBarry Smith   TRSPACE *head;
661a64a8e02SBarry Smith 
662a64a8e02SBarry Smith   PetscFunctionBegin;
663a64a8e02SBarry Smith   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
664a64a8e02SBarry Smith   *stack = &head->stack;
6653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66676386721SLisandro Dalcin #else
667f0ba7cfcSLisandro Dalcin   *stack = NULL;
6683ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
669a64a8e02SBarry Smith #endif
670dfb7d7afSStefano Zampini }
671a64a8e02SBarry Smith 
672e5c89e4eSSatish Balay /*@C
67392f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
674e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
675e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
676e5c89e4eSSatish Balay    allocated.
677e5c89e4eSSatish Balay 
67892f119d6SBarry Smith    Not Collective
679e5c89e4eSSatish Balay 
680e5c89e4eSSatish Balay    Input Parameter:
681*0ed210f4SBarry Smith .  fp  - file pointer.  If `fp` is `NULL`, `stdout` is assumed.
682e5c89e4eSSatish Balay 
683e5c89e4eSSatish Balay    Options Database Key:
684*0ed210f4SBarry Smith .  -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given
685e5c89e4eSSatish Balay 
686e5c89e4eSSatish Balay    Level: intermediate
687e5c89e4eSSatish Balay 
68895452b02SPatrick Sanan    Notes:
689811af0c4SBarry Smith      Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
690e5c89e4eSSatish Balay 
691811af0c4SBarry Smith      When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
69292f119d6SBarry Smith 
693811af0c4SBarry Smith      `PetscMallocView()` prints a list of all memory ever allocated
69492f119d6SBarry Smith 
695*0ed210f4SBarry Smith    Fortran Note:
696*0ed210f4SBarry Smith    The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
69720f4b53cSBarry Smith 
698*0ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
699e5c89e4eSSatish Balay @*/
700d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp)
701d71ae5a4SJacob Faibussowitsch {
702e5c89e4eSSatish Balay   TRSPACE    *head;
703e3ed9ee7SBarry Smith   size_t      libAlloc = 0;
704e5c89e4eSSatish Balay   PetscMPIInt rank;
705e5c89e4eSSatish Balay 
706e5c89e4eSSatish Balay   PetscFunctionBegin;
7079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
708da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
709e5c89e4eSSatish Balay   head = TRhead;
710e5c89e4eSSatish Balay   while (head) {
711608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7125486ca60SMatthew G. Knepley     head = head->next;
7135486ca60SMatthew G. Knepley   }
7145486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7155486ca60SMatthew G. Knepley   head = TRhead;
7165486ca60SMatthew G. Knepley   while (head) {
7175486ca60SMatthew G. Knepley     PetscBool isLib;
7185486ca60SMatthew G. Knepley 
7199566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7205486ca60SMatthew G. Knepley     if (!isLib) {
721ccd65f63SJunchao Zhang       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
722dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
7239566063dSJacob Faibussowitsch       PetscCall(PetscStackPrint(&head->stack, fp));
724e5c89e4eSSatish Balay #endif
7255486ca60SMatthew G. Knepley     }
726e5c89e4eSSatish Balay     head = head->next;
727e5c89e4eSSatish Balay   }
7283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
729e5c89e4eSSatish Balay }
730e5c89e4eSSatish Balay 
731dc37d89fSBarry Smith /*@
732811af0c4SBarry Smith     PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
733574034a9SJed Brown 
734574034a9SJed Brown     Not Collective
735574034a9SJed Brown 
7364165533cSJose E. Roman     Input Parameter:
737*0ed210f4SBarry Smith .   logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
738574034a9SJed Brown 
739*0ed210f4SBarry Smith     Options Database Keys:
740811af0c4SBarry Smith +  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
7418b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7428b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
743574034a9SJed Brown 
744574034a9SJed Brown     Level: advanced
745574034a9SJed Brown 
746*0ed210f4SBarry Smith     Note:
747811af0c4SBarry Smith     Must be called after `PetscMallocSetDebug()`
74892f119d6SBarry Smith 
749*0ed210f4SBarry Smith     Developer Note:
750811af0c4SBarry Smith     Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
75192f119d6SBarry Smith 
752*0ed210f4SBarry Smith .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
753574034a9SJed Brown @*/
754d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
755d71ae5a4SJacob Faibussowitsch {
756574034a9SJed Brown   PetscFunctionBegin;
75792f119d6SBarry Smith   PetscLogMalloc = 0;
7589566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
759574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
760574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
7613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
762574034a9SJed Brown }
763574034a9SJed Brown 
764dc37d89fSBarry Smith /*@
765811af0c4SBarry Smith     PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
76618a2528dSJed Brown 
76718a2528dSJed Brown     Not Collective
76818a2528dSJed Brown 
7694165533cSJose E. Roman     Output Parameter
770811af0c4SBarry Smith .   logging - `PETSC_TRUE` if logging is active
77118a2528dSJed Brown 
77218a2528dSJed Brown     Options Database Key:
773811af0c4SBarry Smith .  -malloc_view <optional filename> - Activates `PetscMallocView()`
77418a2528dSJed Brown 
77518a2528dSJed Brown     Level: advanced
77618a2528dSJed Brown 
777*0ed210f4SBarry Smith .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()`
77818a2528dSJed Brown @*/
779d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging)
780d71ae5a4SJacob Faibussowitsch {
78118a2528dSJed Brown   PetscFunctionBegin;
78218a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
7833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78418a2528dSJed Brown }
78518a2528dSJed Brown 
786608c71bfSMatthew G. Knepley /*@
787811af0c4SBarry Smith   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`
788608c71bfSMatthew G. Knepley 
789608c71bfSMatthew G. Knepley   Not Collective
790608c71bfSMatthew G. Knepley 
7914165533cSJose E. Roman   Input Parameters:
792*0ed210f4SBarry Smith + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF`
793608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
794608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
795608c71bfSMatthew G. Knepley 
796*0ed210f4SBarry Smith   Level: advanced
797*0ed210f4SBarry Smith 
798608c71bfSMatthew G. Knepley   Note:
799608c71bfSMatthew G. Knepley   The viewer should not be collective.
800608c71bfSMatthew G. Knepley 
801*0ed210f4SBarry Smith .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
802608c71bfSMatthew G. Knepley @*/
803d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
804d71ae5a4SJacob Faibussowitsch {
805608c71bfSMatthew G. Knepley   PetscFunctionBegin;
8069371c9d4SSatish Balay   if (!active) {
8079371c9d4SSatish Balay     PetscLogMallocTrace = -1;
8083ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8099371c9d4SSatish Balay   }
810*0ed210f4SBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
811*0ed210f4SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
812*0ed210f4SBarry Smith   PetscLogMallocTraceViewer = viewer;
813608c71bfSMatthew G. Knepley   PetscLogMallocTrace       = 0;
8149566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
815608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
816608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t)logmin;
8173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
818608c71bfSMatthew G. Knepley }
819608c71bfSMatthew G. Knepley 
820608c71bfSMatthew G. Knepley /*@
821811af0c4SBarry Smith   PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
822608c71bfSMatthew G. Knepley 
823608c71bfSMatthew G. Knepley   Not Collective
824608c71bfSMatthew G. Knepley 
8254165533cSJose E. Roman   Output Parameter:
826811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
827608c71bfSMatthew G. Knepley 
828608c71bfSMatthew G. Knepley   Options Database Key:
829*0ed210f4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
830608c71bfSMatthew G. Knepley 
831608c71bfSMatthew G. Knepley   Level: advanced
832608c71bfSMatthew G. Knepley 
833*0ed210f4SBarry Smith .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
834608c71bfSMatthew G. Knepley @*/
835d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
836d71ae5a4SJacob Faibussowitsch {
837608c71bfSMatthew G. Knepley   PetscFunctionBegin;
838608c71bfSMatthew G. Knepley   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
8393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
840608c71bfSMatthew G. Knepley }
841608c71bfSMatthew G. Knepley 
842e5c89e4eSSatish Balay /*@C
843811af0c4SBarry Smith     PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls
844811af0c4SBarry Smith        `PetscMemoryGetMaximumUsage()`
845e5c89e4eSSatish Balay 
84692f119d6SBarry Smith     Not Collective
847e5c89e4eSSatish Balay 
848e5c89e4eSSatish Balay     Input Parameter:
849*0ed210f4SBarry Smith .   fp - file pointer; or `NULL`
850e5c89e4eSSatish Balay 
851e5c89e4eSSatish Balay     Options Database Key:
852811af0c4SBarry Smith .  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
853e5c89e4eSSatish Balay 
854e5c89e4eSSatish Balay     Level: advanced
855e5c89e4eSSatish Balay 
85692f119d6SBarry Smith    Notes:
857811af0c4SBarry Smith      `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
85892f119d6SBarry Smith 
859811af0c4SBarry Smith      `PetscMemoryView()` gives a brief summary of current memory usage
86092f119d6SBarry Smith 
86120f4b53cSBarry Smith    Fortran Notes:
862*0ed210f4SBarry Smith    The calling sequence in Fortran is `PetscMallocView`(integer ierr)
86320f4b53cSBarry Smith 
864*0ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
865e5c89e4eSSatish Balay @*/
866d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp)
867d71ae5a4SJacob Faibussowitsch {
86892f119d6SBarry Smith   PetscInt       i, j, n, *perm;
869e5c89e4eSSatish Balay   size_t        *shortlength;
870c69effb2SJacob Faibussowitsch   int           *shortcount;
87192f119d6SBarry Smith   PetscMPIInt    rank;
872ace3abfcSBarry Smith   PetscBool      match;
873e5c89e4eSSatish Balay   const char   **shortfunction;
874e5c89e4eSSatish Balay   PetscLogDouble rss;
875e5c89e4eSSatish Balay 
876e5c89e4eSSatish Balay   PetscFunctionBegin;
8779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
878c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
879f56c2debSBarry Smith 
88008401ef6SPierre Jolivet   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()");
881768aa557SSatish Balay 
882da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
8839566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&rss));
884e5c89e4eSSatish Balay   if (rss) {
88592f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
886e5c89e4eSSatish Balay   } else {
88792f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
888e5c89e4eSSatish Balay   }
889b13f2904SStefano Zampini   if (PetscLogMalloc > 0) {
8909371c9d4SSatish Balay     shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
8919371c9d4SSatish Balay     PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8929371c9d4SSatish Balay     shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
8939371c9d4SSatish Balay     PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8949371c9d4SSatish Balay     shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
8959371c9d4SSatish Balay     PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
89697b9d747SJed Brown     for (i = 0, n = 0; i < PetscLogMalloc; i++) {
897e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
8989566063dSJacob Faibussowitsch         PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
899e5c89e4eSSatish Balay         if (match) {
900e5c89e4eSSatish Balay           shortlength[j] += PetscLogMallocLength[i];
90159ffdab8SBarry Smith           shortcount[j]++;
902e5c89e4eSSatish Balay           goto foundit;
903e5c89e4eSSatish Balay         }
904e5c89e4eSSatish Balay       }
905e5c89e4eSSatish Balay       shortfunction[n] = PetscLogMallocFunction[i];
906e5c89e4eSSatish Balay       shortlength[n]   = PetscLogMallocLength[i];
90759ffdab8SBarry Smith       shortcount[n]    = 1;
908e5c89e4eSSatish Balay       n++;
909e5c89e4eSSatish Balay     foundit:;
910e5c89e4eSSatish Balay     }
911e5c89e4eSSatish Balay 
9129371c9d4SSatish Balay     perm = (PetscInt *)malloc(n * sizeof(PetscInt));
9139371c9d4SSatish Balay     PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
914e5c89e4eSSatish Balay     for (i = 0; i < n; i++) perm[i] = i;
9159566063dSJacob Faibussowitsch     PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
916e5c89e4eSSatish Balay 
91792f119d6SBarry Smith     (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
918ad540459SPierre Jolivet     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]]);
919e5c89e4eSSatish Balay     free(perm);
920e5c89e4eSSatish Balay     free(shortlength);
92159ffdab8SBarry Smith     free(shortcount);
922e5c89e4eSSatish Balay     free((char **)shortfunction);
923b13f2904SStefano Zampini   }
924c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
9253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
926e5c89e4eSSatish Balay }
927e5c89e4eSSatish Balay 
928dc37d89fSBarry Smith /*@
92992f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
930e5c89e4eSSatish Balay 
931e5c89e4eSSatish Balay     Not Collective
932e5c89e4eSSatish Balay 
933d8d19677SJose E. Roman     Input Parameters:
934811af0c4SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
935*0ed210f4SBarry Smith -   initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
936e5c89e4eSSatish Balay 
937811af0c4SBarry Smith     Options Database Keys:
93879dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
939*0ed210f4SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
94079dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
94192f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
942*0ed210f4SBarry Smith .   -malloc no - (deprecated) same as `-malloc_debug no`
943*0ed210f4SBarry Smith -   -malloc_log - (deprecated) same as `-malloc_view`
944e5c89e4eSSatish Balay 
94592f119d6SBarry Smith    Level: developer
94692f119d6SBarry Smith 
947811af0c4SBarry Smith     Note:
948811af0c4SBarry Smith     This is called in `PetscInitialize()` and should not be called elsewhere
94992f119d6SBarry Smith 
950*0ed210f4SBarry Smith .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
951e5c89e4eSSatish Balay @*/
952d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
953d71ae5a4SJacob Faibussowitsch {
954e5c89e4eSSatish Balay   PetscFunctionBegin;
95508401ef6SPierre Jolivet   PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()");
9569566063dSJacob Faibussowitsch   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
95792f119d6SBarry Smith 
95892f119d6SBarry Smith   TRallocated           = 0;
95992f119d6SBarry Smith   TRfrags               = 0;
96092f119d6SBarry Smith   TRhead                = NULL;
96192f119d6SBarry Smith   TRid                  = 0;
96292f119d6SBarry Smith   TRdebugLevel          = eachcall;
96392f119d6SBarry Smith   TRMaxMem              = 0;
96492f119d6SBarry Smith   PetscLogMallocMax     = 10000;
96592f119d6SBarry Smith   PetscLogMalloc        = -1;
9662d4ee042Sprj-   TRdebugIinitializenan = initializenan;
9673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
968e5c89e4eSSatish Balay }
9690acecf5bSBarry Smith 
970dc37d89fSBarry Smith /*@
97192f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9720acecf5bSBarry Smith 
9730acecf5bSBarry Smith     Not Collective
9740acecf5bSBarry Smith 
97592f119d6SBarry Smith     Output Parameters:
97692f119d6SBarry Smith +    basic - doing basic debugging
977811af0c4SBarry Smith .    eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
978*0ed210f4SBarry Smith -    initializenan - initializes memory with `NaN`
9790acecf5bSBarry Smith 
9800acecf5bSBarry Smith    Level: intermediate
9810acecf5bSBarry Smith 
982811af0c4SBarry Smith    Note:
983*0ed210f4SBarry Smith      By default, the debug version always does some debugging unless you run with `-malloc_debug no`
9840acecf5bSBarry Smith 
985*0ed210f4SBarry Smith .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
9860acecf5bSBarry Smith @*/
987d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
988d71ae5a4SJacob Faibussowitsch {
9890acecf5bSBarry Smith   PetscFunctionBegin;
99079dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
99179dccf82SBarry Smith   if (eachcall) *eachcall = TRdebugLevel;
9922d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9940acecf5bSBarry Smith }
995608c71bfSMatthew G. Knepley 
996608c71bfSMatthew G. Knepley /*@
997608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
998608c71bfSMatthew G. Knepley 
999608c71bfSMatthew G. Knepley   Not Collective
1000608c71bfSMatthew G. Knepley 
1001608c71bfSMatthew G. Knepley   Input Parameter:
1002811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size
1003608c71bfSMatthew G. Knepley 
1004811af0c4SBarry Smith   Options Database Key:
1005608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1006608c71bfSMatthew G. Knepley 
1007608c71bfSMatthew G. Knepley   Level: developer
1008608c71bfSMatthew G. Knepley 
1009*0ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1010608c71bfSMatthew G. Knepley @*/
1011d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1012d71ae5a4SJacob Faibussowitsch {
1013608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1014608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
10153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1016608c71bfSMatthew G. Knepley }
1017608c71bfSMatthew G. Knepley 
1018608c71bfSMatthew G. Knepley /*@
1019608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1020608c71bfSMatthew G. Knepley 
1021608c71bfSMatthew G. Knepley   Not Collective
1022608c71bfSMatthew G. Knepley 
1023608c71bfSMatthew G. Knepley   Output Parameter:
1024811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size
1025608c71bfSMatthew G. Knepley 
1026608c71bfSMatthew G. Knepley   Level: developer
1027608c71bfSMatthew G. Knepley 
1028*0ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1029608c71bfSMatthew G. Knepley @*/
1030d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1031d71ae5a4SJacob Faibussowitsch {
1032608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1033608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
10343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1035608c71bfSMatthew G. Knepley }
1036