xref: /petsc/src/sys/memory/mtr.c (revision 834855d6effb0d027771461c8e947ee1ce5a1e17)
1e5c89e4eSSatish Balay /*
22d853995SBarry Smith      Logging of memory usage and some error checking
3e5c89e4eSSatish Balay */
427104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
5665c2dedSJed Brown #include <petscviewer.h>
6e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
7e5c89e4eSSatish Balay   #include <malloc.h>
8e5c89e4eSSatish Balay #endif
9e5c89e4eSSatish Balay 
10e5c89e4eSSatish Balay /*
11e5c89e4eSSatish Balay      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
12e5c89e4eSSatish Balay */
13071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
1495c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
1595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
16e5c89e4eSSatish Balay 
17835f2295SStefano Zampini #define COOKIE_VALUE  -253701943
18835f2295SStefano Zampini #define ALREADY_FREED 252579228
19e5c89e4eSSatish Balay 
202d853995SBarry Smith /*  this is the header put at the beginning of each PetscTrMallocDefault() for tracking allocated space and checking of allocated space heap */
21e5c89e4eSSatish Balay typedef struct _trSPACE {
22608c71bfSMatthew G. Knepley   size_t      size, rsize; /* Aligned size and requested size */
23e5c89e4eSSatish Balay   int         id;
24e5c89e4eSSatish Balay   int         lineno;
25e5c89e4eSSatish Balay   const char *filename;
26e5c89e4eSSatish Balay   const char *functionname;
27835f2295SStefano Zampini   PetscInt    specialcookie;
28dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
29e5c89e4eSSatish Balay   PetscStack stack;
30e5c89e4eSSatish Balay #endif
31e5c89e4eSSatish Balay   struct _trSPACE *next, *prev;
32e5c89e4eSSatish Balay } TRSPACE;
33e5c89e4eSSatish Balay 
342d853995SBarry Smith /* HEADER_BYTES is the number of bytes in a PetscTrMallocDefault() header.
3592f119d6SBarry Smith    It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
3625b53cc9SJed Brown */
37a64a8e02SBarry Smith #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
38e5c89e4eSSatish Balay 
3925b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains
4025b53cc9SJed Brown    a minimum alignment of PETSC_MEMALIGN.
4125b53cc9SJed Brown */
429371c9d4SSatish Balay typedef union
439371c9d4SSatish Balay {
44e5c89e4eSSatish Balay   TRSPACE sp;
4525b53cc9SJed Brown   char    v[HEADER_BYTES];
46e5c89e4eSSatish Balay } TrSPACE;
47e5c89e4eSSatish Balay 
48e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50
49e5c89e4eSSatish Balay static size_t    TRallocated           = 0;
50e5c89e4eSSatish Balay static int       TRfrags               = 0;
51f0ba7cfcSLisandro Dalcin static TRSPACE  *TRhead                = NULL;
52e5c89e4eSSatish Balay static int       TRid                  = 0;
532d853995SBarry Smith static PetscBool TRdebug               = PETSC_FALSE;
542d4ee042Sprj- static PetscBool TRdebugIinitializenan = PETSC_FALSE;
55608c71bfSMatthew G. Knepley static PetscBool TRrequestedSize       = PETSC_FALSE;
56e5c89e4eSSatish Balay static size_t    TRMaxMem              = 0;
57e3ed9ee7SBarry Smith static int       NumTRMaxMems          = 0;
58e3ed9ee7SBarry Smith static size_t    TRMaxMems[MAXTRMAXMEMS];
59e3ed9ee7SBarry Smith static int       TRMaxMemsEvents[MAXTRMAXMEMS];
60e5c89e4eSSatish Balay /*
6192f119d6SBarry Smith       Arrays to log information on mallocs for PetscMallocView()
62e5c89e4eSSatish Balay */
63f0ba7cfcSLisandro Dalcin static int          PetscLogMallocMax       = 10000;
64f0ba7cfcSLisandro Dalcin static int          PetscLogMalloc          = -1;
65574034a9SJed Brown static size_t       PetscLogMallocThreshold = 0;
66e5c89e4eSSatish Balay static size_t      *PetscLogMallocLength;
67efca3c55SSatish Balay static const char **PetscLogMallocFile, **PetscLogMallocFunction;
68608c71bfSMatthew G. Knepley static int          PetscLogMallocTrace          = -1;
69608c71bfSMatthew G. Knepley static size_t       PetscLogMallocTraceThreshold = 0;
70608c71bfSMatthew G. Knepley static PetscViewer  PetscLogMallocTraceViewer    = NULL;
71b022a5c1SBarry Smith 
72e5c89e4eSSatish Balay /*@C
73811af0c4SBarry Smith   PetscMallocValidate - Test the memory for corruption.  This can be called at any time between `PetscInitialize()` and `PetscFinalize()`
74e5c89e4eSSatish Balay 
7592f119d6SBarry Smith   Input Parameters:
76e5c89e4eSSatish Balay + line     - line number where call originated.
77e5c89e4eSSatish Balay . function - name of function calling
78efca3c55SSatish Balay - file     - file where function is
79e5c89e4eSSatish Balay 
8010450e9eSJacob Faibussowitsch   Options Database Keys:
810ed210f4SBarry Smith + -malloc_test  - turns this feature on when PETSc was not configured with `--with-debugging=0`
8292f119d6SBarry Smith - -malloc_debug - turns this feature on anytime
8392f119d6SBarry Smith 
84e5c89e4eSSatish Balay   Level: advanced
85e5c89e4eSSatish Balay 
86e5c89e4eSSatish Balay   Notes:
872d853995SBarry Smith   You should generally use `CHKMEMQ` as a short cut for calling this routine.
882d853995SBarry Smith 
890ed210f4SBarry Smith   Error messages are written to `stdout`.
900ed210f4SBarry Smith 
910ed210f4SBarry 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)
9238548759SBarry Smith 
93e5c89e4eSSatish Balay   No output is generated if there are no problems detected.
94e5c89e4eSSatish Balay 
95aec76313SJacob Faibussowitsch   Fortran Notes:
9620f4b53cSBarry Smith   The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
9720f4b53cSBarry Smith 
980ed210f4SBarry Smith .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()`
99e5c89e4eSSatish Balay @*/
PetscMallocValidate(int line,const char function[],const char file[])100d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
101d71ae5a4SJacob Faibussowitsch {
1026c093d5bSvictor   TRSPACE  *head, *lasthead;
103e5c89e4eSSatish Balay   char     *a;
104835f2295SStefano Zampini   PetscInt *nend;
105e5c89e4eSSatish Balay 
1062d853995SBarry Smith   if (!TRdebug) return PETSC_SUCCESS;
1079371c9d4SSatish Balay   head     = TRhead;
1089371c9d4SSatish Balay   lasthead = NULL;
1092cba8197SMatthew G. Knepley   if (head && head->prev) {
1102d853995SBarry Smith     TRdebug = PETSC_FALSE;
1113ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1123ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
1134ed0ab5bSBarry Smith     return PETSC_ERR_MEMC;
1142cba8197SMatthew G. Knepley   }
115e5c89e4eSSatish Balay   while (head) {
116835f2295SStefano Zampini     if (head->specialcookie != COOKIE_VALUE) {
1172d853995SBarry Smith       TRdebug = PETSC_FALSE;
1183ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1193ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
1203ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
121e269983cSBarry Smith       if (lasthead) {
122e269983cSBarry Smith         a = (char *)(((TrSPACE *)head) + 1);
1233ba16761SJacob 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));
124e269983cSBarry Smith       }
125e269983cSBarry Smith       abort();
1264ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
127e5c89e4eSSatish Balay     }
128e5c89e4eSSatish Balay     a    = (char *)(((TrSPACE *)head) + 1);
129835f2295SStefano Zampini     nend = (PetscInt *)(a + head->size);
130835f2295SStefano Zampini     if (*nend != COOKIE_VALUE) {
1312d853995SBarry Smith       TRdebug = PETSC_FALSE;
1323ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
133e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
1343ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
1354ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
136e5c89e4eSSatish Balay       } else {
1373ba16761SJacob 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));
1383ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1394ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
140e5c89e4eSSatish Balay       }
141e5c89e4eSSatish Balay     }
1422cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
1432d853995SBarry Smith       TRdebug = PETSC_FALSE;
1443ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1453ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
1463ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
1473ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1484ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
1492cba8197SMatthew G. Knepley     }
1506c093d5bSvictor     lasthead = head;
151e5c89e4eSSatish Balay     head     = head->next;
152e5c89e4eSSatish Balay   }
1533ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
154e5c89e4eSSatish Balay }
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay /*
1572d853995SBarry Smith     PetscTrMallocDefault - Malloc with logging and error checking
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay */
PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void ** result)16066976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
161d71ae5a4SJacob Faibussowitsch {
162e5c89e4eSSatish Balay   TRSPACE *head;
163e5c89e4eSSatish Balay   char    *inew;
164e5c89e4eSSatish Balay   size_t   nsize;
165e5c89e4eSSatish Balay 
166e5c89e4eSSatish Balay   PetscFunctionBegin;
1679371c9d4SSatish Balay   if (!a) {
1689371c9d4SSatish Balay     *result = NULL;
1693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1709371c9d4SSatish Balay   }
171f0ba7cfcSLisandro Dalcin 
17211cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
173e5c89e4eSSatish Balay 
17425b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
175835f2295SStefano Zampini   PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscInt), clear, lineno, function, filename, (void **)&inew));
176e3ed9ee7SBarry Smith 
177e5c89e4eSSatish Balay   head = (TRSPACE *)inew;
178e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
179e5c89e4eSSatish Balay 
180e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
181e5c89e4eSSatish Balay   head->next   = TRhead;
182e5c89e4eSSatish Balay   TRhead       = head;
183f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
184e5c89e4eSSatish Balay   head->size   = nsize;
185608c71bfSMatthew G. Knepley   head->rsize  = a;
186e269983cSBarry Smith   head->id     = TRid++;
187e5c89e4eSSatish Balay   head->lineno = lineno;
188e5c89e4eSSatish Balay 
189e5c89e4eSSatish Balay   head->filename              = filename;
190e5c89e4eSSatish Balay   head->functionname          = function;
191835f2295SStefano Zampini   head->specialcookie         = COOKIE_VALUE;
192835f2295SStefano Zampini   *(PetscInt *)(inew + nsize) = COOKIE_VALUE;
193e5c89e4eSSatish Balay 
194608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
195a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
196e3ed9ee7SBarry Smith   if (PetscLogMemory) {
1972d853995SBarry Smith     for (PetscInt i = 0; i < NumTRMaxMems; i++) {
198e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
199e3ed9ee7SBarry Smith     }
200e3ed9ee7SBarry Smith   }
201e5c89e4eSSatish Balay   TRfrags++;
202e5c89e4eSSatish Balay 
203dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
2049566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
2052d853995SBarry Smith   /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */
20653dcd878SStefano Zampini   head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
2072d853995SBarry Smith   head->stack.currentsize--;
20892f119d6SBarry Smith   #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2092d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
2102d853995SBarry Smith     size_t     n = a / sizeof(PetscReal);
21192f119d6SBarry Smith     PetscReal *s = (PetscReal *)inew;
21292f119d6SBarry Smith       /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
21392f119d6SBarry Smith     #if defined(PETSC_USE_REAL_SINGLE)
214df282883SBarry Smith     int nas = 0x7F800002;
21592f119d6SBarry Smith     #else
21692f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
21792f119d6SBarry Smith     #endif
2182d853995SBarry Smith     for (size_t i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
21992f119d6SBarry Smith   }
22092f119d6SBarry Smith   #endif
221e5c89e4eSSatish Balay #endif
222e5c89e4eSSatish Balay 
223e5c89e4eSSatish Balay   /*
22492f119d6SBarry Smith          Allow logging of all mallocs made.
22592f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
226e5c89e4eSSatish Balay   */
227574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
228e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
229e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
23028b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
231a297a907SKarl Rupp 
232a2ea699eSBarry Smith       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
23328b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
234a297a907SKarl Rupp 
235a2ea699eSBarry Smith       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
23628b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
237e5c89e4eSSatish Balay     }
238e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
239e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
240e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
241e5c89e4eSSatish Balay   }
24248a46eb9SPierre Jolivet   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
243e5c89e4eSSatish Balay   *result = (void *)inew;
2443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
245e5c89e4eSSatish Balay }
246e5c89e4eSSatish Balay 
247e5c89e4eSSatish Balay /*
2482d853995SBarry Smith    PetscTrFreeDefault - Free with logging and error checking
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay */
PetscTrFreeDefault(void * aa,int lineno,const char function[],const char filename[])25166976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
252d71ae5a4SJacob Faibussowitsch {
253e5c89e4eSSatish Balay   char     *a = (char *)aa;
254e5c89e4eSSatish Balay   TRSPACE  *head;
255e5c89e4eSSatish Balay   char     *ahead;
256608c71bfSMatthew G. Knepley   size_t    asize;
257835f2295SStefano Zampini   PetscInt *nend;
258e5c89e4eSSatish Balay 
259e5c89e4eSSatish Balay   PetscFunctionBegin;
2603ba16761SJacob Faibussowitsch   if (!a) PetscFunctionReturn(PETSC_SUCCESS);
261e5c89e4eSSatish Balay 
2629566063dSJacob Faibussowitsch   PetscCall(PetscMallocValidate(lineno, function, filename));
263e5c89e4eSSatish Balay 
264e5c89e4eSSatish Balay   ahead = a;
265e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
266e5c89e4eSSatish Balay   head  = (TRSPACE *)a;
267e5c89e4eSSatish Balay 
268835f2295SStefano Zampini   if (head->specialcookie != COOKIE_VALUE) {
2692d853995SBarry Smith     TRdebug = PETSC_FALSE;
2703ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2713ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
272e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
273e5c89e4eSSatish Balay   }
274835f2295SStefano Zampini   nend = (PetscInt *)(ahead + head->size);
275835f2295SStefano Zampini   if (*nend != COOKIE_VALUE) {
2762d853995SBarry Smith     TRdebug = PETSC_FALSE;
277e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
2783ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2793ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
280e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
2813ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
282e5c89e4eSSatish Balay       } else {
2833ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
284e5c89e4eSSatish Balay       }
285e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
286e5c89e4eSSatish Balay     } else {
287e5c89e4eSSatish Balay       /* Damaged tail */
2883ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2893ba16761SJacob 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));
2903ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
291e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
292e5c89e4eSSatish Balay     }
293e5c89e4eSSatish Balay   }
294*3a7d0413SPierre Jolivet   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
295e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
296e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as allocated location */
297608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
298608c71bfSMatthew G. Knepley     head->lineno       = lineno;
299608c71bfSMatthew G. Knepley     head->filename     = filename;
300e5c89e4eSSatish Balay     head->functionname = function;
301e5c89e4eSSatish Balay   } else {
302e5c89e4eSSatish Balay     head->lineno = -head->lineno;
303e5c89e4eSSatish Balay   }
304608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
30508401ef6SPierre Jolivet   PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
306608c71bfSMatthew G. Knepley   TRallocated -= asize;
307e5c89e4eSSatish Balay   TRfrags--;
308e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
309e5c89e4eSSatish Balay   else TRhead = head->next;
310e5c89e4eSSatish Balay 
311e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
3129566063dSJacob Faibussowitsch   PetscCall(PetscFreeAlign(a, lineno, function, filename));
3133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
314e5c89e4eSSatish Balay }
315e5c89e4eSSatish Balay 
3163221ece2SMatthew G. Knepley /*
3172d853995SBarry Smith   PetscTrReallocDefault - Realloc with logging and error checking
3183221ece2SMatthew G. Knepley 
3193221ece2SMatthew G. Knepley */
PetscTrReallocDefault(size_t len,int lineno,const char function[],const char filename[],void ** result)32066976f2fSJacob Faibussowitsch static PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
321d71ae5a4SJacob Faibussowitsch {
3223221ece2SMatthew G. Knepley   char     *a = (char *)*result;
3233221ece2SMatthew G. Knepley   TRSPACE  *head;
3243221ece2SMatthew G. Knepley   char     *ahead, *inew;
325835f2295SStefano Zampini   PetscInt *nend;
3263221ece2SMatthew G. Knepley   size_t    nsize;
3273221ece2SMatthew G. Knepley 
3283221ece2SMatthew G. Knepley   PetscFunctionBegin;
32992f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
330c22f1541SToby Isaac   if (!len) {
3319566063dSJacob Faibussowitsch     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
332c22f1541SToby Isaac     *result = NULL;
3333ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
334c22f1541SToby Isaac   }
335da81f932SPierre Jolivet   /* If the original space was NULL just use the regular malloc() */
336f590eff4SLisandro Dalcin   if (!*result) {
3379566063dSJacob Faibussowitsch     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
3383ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
339f590eff4SLisandro Dalcin   }
3403221ece2SMatthew G. Knepley 
34111cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
3423221ece2SMatthew G. Knepley 
3433221ece2SMatthew G. Knepley   ahead = a;
3443221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3453221ece2SMatthew G. Knepley   head  = (TRSPACE *)a;
3463221ece2SMatthew G. Knepley   inew  = a;
3473221ece2SMatthew G. Knepley 
348835f2295SStefano Zampini   if (head->specialcookie != COOKIE_VALUE) {
3492d853995SBarry Smith     TRdebug = PETSC_FALSE;
3503ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3513ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
3523221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
3533221ece2SMatthew G. Knepley   }
354835f2295SStefano Zampini   nend = (PetscInt *)(ahead + head->size);
355835f2295SStefano Zampini   if (*nend != COOKIE_VALUE) {
3562d853995SBarry Smith     TRdebug = PETSC_FALSE;
3573221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3583ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3593ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
3603221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3613ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3623221ece2SMatthew G. Knepley       } else {
3633ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
3643221ece2SMatthew G. Knepley       }
3653221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
3663221ece2SMatthew G. Knepley     } else {
3673221ece2SMatthew G. Knepley       /* Damaged tail */
3683ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3693ba16761SJacob 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));
3703ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3713221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
3723221ece2SMatthew G. Knepley     }
3733221ece2SMatthew G. Knepley   }
3743221ece2SMatthew G. Knepley 
37592f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
376608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
3773221ece2SMatthew G. Knepley   TRfrags--;
3783221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
3793221ece2SMatthew G. Knepley   else TRhead = head->next;
3803221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
3813221ece2SMatthew G. Knepley 
3823221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
383835f2295SStefano Zampini   PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscInt), lineno, function, filename, (void **)&inew));
3843221ece2SMatthew G. Knepley 
3853221ece2SMatthew G. Knepley   head = (TRSPACE *)inew;
3863221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
3873221ece2SMatthew G. Knepley 
3883221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
3893221ece2SMatthew G. Knepley   head->next   = TRhead;
3903221ece2SMatthew G. Knepley   TRhead       = head;
3913221ece2SMatthew G. Knepley   head->prev   = NULL;
3923221ece2SMatthew G. Knepley   head->size   = nsize;
393608c71bfSMatthew G. Knepley   head->rsize  = len;
394e269983cSBarry Smith   head->id     = TRid++;
3953221ece2SMatthew G. Knepley   head->lineno = lineno;
3963221ece2SMatthew G. Knepley 
3973221ece2SMatthew G. Knepley   head->filename              = filename;
3983221ece2SMatthew G. Knepley   head->functionname          = function;
399835f2295SStefano Zampini   head->specialcookie         = COOKIE_VALUE;
400835f2295SStefano Zampini   *(PetscInt *)(inew + nsize) = COOKIE_VALUE;
4013221ece2SMatthew G. Knepley 
402608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4033221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
404e3ed9ee7SBarry Smith   if (PetscLogMemory) {
4052d853995SBarry Smith     for (PetscInt i = 0; i < NumTRMaxMems; i++) {
406e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
407e3ed9ee7SBarry Smith     }
408e3ed9ee7SBarry Smith   }
4093221ece2SMatthew G. Knepley   TRfrags++;
4103221ece2SMatthew G. Knepley 
411dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
4129566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
4133221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
41453dcd878SStefano Zampini   head->stack.line[PetscMax(head->stack.currentsize - 2, 0)] = lineno;
4153221ece2SMatthew G. Knepley #endif
4163221ece2SMatthew G. Knepley 
4173221ece2SMatthew G. Knepley   /*
41892f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
41992f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4203221ece2SMatthew G. Knepley   */
4213221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4223221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4233221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
42428b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4253221ece2SMatthew G. Knepley 
4263221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
42728b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4283221ece2SMatthew G. Knepley 
4293221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
43028b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4313221ece2SMatthew G. Knepley     }
4323221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4333221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4343221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4353221ece2SMatthew G. Knepley   }
4363221ece2SMatthew G. Knepley   *result = (void *)inew;
4373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4383221ece2SMatthew G. Knepley }
4393221ece2SMatthew G. Knepley 
440fe7fb379SMatthew Knepley /*@C
44192f119d6SBarry Smith   PetscMemoryView - Shows the amount of memory currently being used in a communicator.
442e5c89e4eSSatish Balay 
443c3339decSBarry Smith   Collective
444e5c89e4eSSatish Balay 
445d8d19677SJose E. Roman   Input Parameters:
4460ed210f4SBarry Smith + viewer  - the viewer to output the information on
447e5c89e4eSSatish Balay - message - string printed before values
448e5c89e4eSSatish Balay 
449811af0c4SBarry Smith   Options Database Keys:
45092f119d6SBarry Smith + -malloc_debug    - have PETSc track how much memory it has allocated
4510ed210f4SBarry Smith . -log_view_memory - print memory usage per event when `-log_view` is used
4520ed210f4SBarry Smith - -memory_view     - during `PetscFinalize()` have this routine called
4530841954dSBarry Smith 
454e5c89e4eSSatish Balay   Level: intermediate
455e5c89e4eSSatish Balay 
4560ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
457e5c89e4eSSatish Balay  @*/
PetscMemoryView(PetscViewer viewer,const char message[])458d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
459d71ae5a4SJacob Faibussowitsch {
4602d853995SBarry Smith   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax;
4612d853995SBarry Smith   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax;
462e5c89e4eSSatish Balay   MPI_Comm       comm;
463e5c89e4eSSatish Balay 
464e5c89e4eSSatish Balay   PetscFunctionBegin;
465e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4669566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&allocated));
4679566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4689566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&resident));
4699566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
470e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
4719566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
4729566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
473e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4749566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4759566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4779566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
4789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4799566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4809566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4819566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
4829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4839566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4859566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
4869566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4889566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4899566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
490e5c89e4eSSatish Balay   } else if (resident && residentmax) {
4919566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4929566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4939566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
4959566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
499e5c89e4eSSatish Balay   } else if (resident && allocated) {
5009566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5019566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5039566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5079566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
509e5c89e4eSSatish Balay   } else if (allocated) {
5109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5159566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
516e5c89e4eSSatish Balay   } else {
5179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
518e5c89e4eSSatish Balay   }
5199566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
5203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
521e5c89e4eSSatish Balay }
522e5c89e4eSSatish Balay 
52346eb3923SBarry Smith /*@
524811af0c4SBarry Smith   PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
525e5c89e4eSSatish Balay 
526e5c89e4eSSatish Balay   Not Collective
527e5c89e4eSSatish Balay 
5282fe279fdSBarry Smith   Output Parameter:
529e5c89e4eSSatish Balay . space - number of bytes currently allocated
530e5c89e4eSSatish Balay 
531e5c89e4eSSatish Balay   Level: intermediate
532e5c89e4eSSatish Balay 
5332d853995SBarry Smith   Note:
5342d853995SBarry Smith   This only works if `-memory_view` or `-log_view_memory` have been used
5352d853995SBarry Smith 
5360ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
537db781477SPatrick Sanan           `PetscMemoryGetMaximumUsage()`
538e5c89e4eSSatish Balay  @*/
PetscMallocGetCurrentUsage(PetscLogDouble * space)539d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
540d71ae5a4SJacob Faibussowitsch {
541e5c89e4eSSatish Balay   PetscFunctionBegin;
542e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRallocated;
5433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
544e5c89e4eSSatish Balay }
545e5c89e4eSSatish Balay 
546dc37d89fSBarry Smith /*@
547811af0c4SBarry Smith   PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
548811af0c4SBarry Smith   during this run, the high water mark.
549e5c89e4eSSatish Balay 
550e5c89e4eSSatish Balay   Not Collective
551e5c89e4eSSatish Balay 
5522fe279fdSBarry Smith   Output Parameter:
553e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay   Level: intermediate
556e5c89e4eSSatish Balay 
5572d853995SBarry Smith   Note:
5582d853995SBarry Smith   This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
5592d853995SBarry Smith 
5600ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
561db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
562e5c89e4eSSatish Balay  @*/
PetscMallocGetMaximumUsage(PetscLogDouble * space)563d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
564d71ae5a4SJacob Faibussowitsch {
565e5c89e4eSSatish Balay   PetscFunctionBegin;
566e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRMaxMem;
5673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
568e5c89e4eSSatish Balay }
569e5c89e4eSSatish Balay 
570e3ed9ee7SBarry Smith /*@
571e3ed9ee7SBarry Smith   PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
572e3ed9ee7SBarry Smith 
573e3ed9ee7SBarry Smith   Not Collective
574e3ed9ee7SBarry Smith 
575e3ed9ee7SBarry Smith   Input Parameter:
576e3ed9ee7SBarry Smith . event - an event id; this is just for error checking
577e3ed9ee7SBarry Smith 
578e3ed9ee7SBarry Smith   Level: developer
579e3ed9ee7SBarry Smith 
5802d853995SBarry Smith   Note:
5812d853995SBarry Smith   This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
5822d853995SBarry Smith 
5830ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
584db781477SPatrick Sanan           `PetscMallocPopMaximumUsage()`
585e3ed9ee7SBarry Smith  @*/
PetscMallocPushMaximumUsage(int event)586d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event)
587d71ae5a4SJacob Faibussowitsch {
588e3ed9ee7SBarry Smith   PetscFunctionBegin;
5892611ad71SToby Isaac   if (event < 0 || ++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
590e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
591e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
5923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
593e3ed9ee7SBarry Smith }
594e3ed9ee7SBarry Smith 
595e3ed9ee7SBarry Smith /*@
596e3ed9ee7SBarry Smith   PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
597e3ed9ee7SBarry Smith 
598e3ed9ee7SBarry Smith   Not Collective
599e3ed9ee7SBarry Smith 
600e3ed9ee7SBarry Smith   Input Parameter:
601e3ed9ee7SBarry Smith . event - an event id; this is just for error checking
602e3ed9ee7SBarry Smith 
603e3ed9ee7SBarry Smith   Output Parameter:
604e3ed9ee7SBarry Smith . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
605e3ed9ee7SBarry Smith 
606e3ed9ee7SBarry Smith   Level: developer
607e3ed9ee7SBarry Smith 
6082d853995SBarry Smith   Note:
6092d853995SBarry Smith   This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
6102d853995SBarry Smith 
6110ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
612db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
613e3ed9ee7SBarry Smith  @*/
PetscMallocPopMaximumUsage(int event,PetscLogDouble * mu)614d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
615d71ae5a4SJacob Faibussowitsch {
616e3ed9ee7SBarry Smith   PetscFunctionBegin;
617e3ed9ee7SBarry Smith   *mu = 0;
6182611ad71SToby Isaac   if (event < 0 || NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
61908401ef6SPierre Jolivet   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
6206497c311SBarry Smith   *mu = (PetscLogDouble)TRMaxMems[NumTRMaxMems];
6213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
622e3ed9ee7SBarry Smith }
623e3ed9ee7SBarry Smith 
624a64a8e02SBarry Smith /*@C
625811af0c4SBarry Smith   PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
626a64a8e02SBarry Smith 
627cc4c1da9SBarry Smith   Not Collective, No Fortran Support
628a64a8e02SBarry Smith 
629a64a8e02SBarry Smith   Input Parameter:
630a64a8e02SBarry Smith . ptr - the memory location
631a64a8e02SBarry Smith 
632fd292e60Sprj-   Output Parameter:
633a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory
634a64a8e02SBarry Smith 
635a64a8e02SBarry Smith   Level: intermediate
636a64a8e02SBarry Smith 
6372d853995SBarry Smith   Note:
6382d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
6392d853995SBarry Smith 
6400ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
641a64a8e02SBarry Smith @*/
PetscMallocGetStack(void * ptr,PetscStack ** stack)642d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
643d71ae5a4SJacob Faibussowitsch {
644dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
645a64a8e02SBarry Smith   TRSPACE *head;
646a64a8e02SBarry Smith 
647a64a8e02SBarry Smith   PetscFunctionBegin;
64857508eceSPierre Jolivet   head   = (TRSPACE *)((char *)ptr - HEADER_BYTES);
649a64a8e02SBarry Smith   *stack = &head->stack;
6503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65176386721SLisandro Dalcin #else
652f0ba7cfcSLisandro Dalcin   *stack = NULL;
6533ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
654a64a8e02SBarry Smith #endif
655dfb7d7afSStefano Zampini }
656a64a8e02SBarry Smith 
657e5c89e4eSSatish Balay /*@C
65892f119d6SBarry Smith   PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
659e5c89e4eSSatish Balay   printed is: size of space (in bytes), address of space, id of space,
660e5c89e4eSSatish Balay   file in which space was allocated, and line number at which it was
661e5c89e4eSSatish Balay   allocated.
662e5c89e4eSSatish Balay 
66392f119d6SBarry Smith   Not Collective
664e5c89e4eSSatish Balay 
665e5c89e4eSSatish Balay   Input Parameter:
6660ed210f4SBarry Smith . fp - file pointer.  If `fp` is `NULL`, `stdout` is assumed.
667e5c89e4eSSatish Balay 
668e5c89e4eSSatish Balay   Options Database Key:
6690ed210f4SBarry Smith . -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given
670e5c89e4eSSatish Balay 
671e5c89e4eSSatish Balay   Level: intermediate
672e5c89e4eSSatish Balay 
67395452b02SPatrick Sanan   Notes:
674811af0c4SBarry Smith   Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
675e5c89e4eSSatish Balay 
676811af0c4SBarry Smith   When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
67792f119d6SBarry Smith 
678811af0c4SBarry Smith   `PetscMallocView()` prints a list of all memory ever allocated
67992f119d6SBarry Smith 
6802d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
6812d853995SBarry Smith 
682aec76313SJacob Faibussowitsch   Fortran Notes:
6830ed210f4SBarry Smith   The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
68420f4b53cSBarry Smith 
685aec76313SJacob Faibussowitsch   Developer Notes:
6862d853995SBarry Smith   This should be absorbed into `PetscMallocView()`
6872d853995SBarry Smith 
6880ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
689e5c89e4eSSatish Balay @*/
PetscMallocDump(FILE * fp)690d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp)
691d71ae5a4SJacob Faibussowitsch {
692e5c89e4eSSatish Balay   TRSPACE    *head;
693e3ed9ee7SBarry Smith   size_t      libAlloc = 0;
694e5c89e4eSSatish Balay   PetscMPIInt rank;
695e5c89e4eSSatish Balay 
696e5c89e4eSSatish Balay   PetscFunctionBegin;
6979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
698da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
699e5c89e4eSSatish Balay   head = TRhead;
700e5c89e4eSSatish Balay   while (head) {
701608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7025486ca60SMatthew G. Knepley     head = head->next;
7035486ca60SMatthew G. Knepley   }
7045486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7055486ca60SMatthew G. Knepley   head = TRhead;
7065486ca60SMatthew G. Knepley   while (head) {
7075486ca60SMatthew G. Knepley     PetscBool isLib;
7085486ca60SMatthew G. Knepley 
7099566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7105486ca60SMatthew G. Knepley     if (!isLib) {
711dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
7122d853995SBarry Smith       fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size));
7139566063dSJacob Faibussowitsch       PetscCall(PetscStackPrint(&head->stack, fp));
7142d853995SBarry Smith #else
7152d853995SBarry Smith       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
716e5c89e4eSSatish Balay #endif
7175486ca60SMatthew G. Knepley     }
718e5c89e4eSSatish Balay     head = head->next;
719e5c89e4eSSatish Balay   }
7203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
721e5c89e4eSSatish Balay }
722e5c89e4eSSatish Balay 
723dc37d89fSBarry Smith /*@
724811af0c4SBarry Smith   PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
725574034a9SJed Brown 
726574034a9SJed Brown   Not Collective
727574034a9SJed Brown 
7284165533cSJose E. Roman   Input Parameter:
7290ed210f4SBarry Smith . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
730574034a9SJed Brown 
7310ed210f4SBarry Smith   Options Database Keys:
732811af0c4SBarry Smith + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
7332d853995SBarry Smith . -malloc_view_threshold <min>     - Sets a minimum size if `-malloc_view` is used
7348b254c29SBarry Smith - -log_view_memory                 - view the memory usage also with the -log_view option
735574034a9SJed Brown 
736574034a9SJed Brown   Level: advanced
737574034a9SJed Brown 
7380ed210f4SBarry Smith   Note:
739811af0c4SBarry Smith   Must be called after `PetscMallocSetDebug()`
74092f119d6SBarry Smith 
741aec76313SJacob Faibussowitsch   Developer Notes:
742811af0c4SBarry Smith   Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
74392f119d6SBarry Smith 
7440ed210f4SBarry Smith .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
745574034a9SJed Brown @*/
PetscMallocViewSet(PetscLogDouble logmin)746d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
747d71ae5a4SJacob Faibussowitsch {
748574034a9SJed Brown   PetscFunctionBegin;
74992f119d6SBarry Smith   PetscLogMalloc = 0;
7509566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
751574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
752574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
7533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
754574034a9SJed Brown }
755574034a9SJed Brown 
756dc37d89fSBarry Smith /*@
757811af0c4SBarry Smith   PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
75818a2528dSJed Brown 
75918a2528dSJed Brown   Not Collective
76018a2528dSJed Brown 
76110450e9eSJacob Faibussowitsch   Output Parameter:
762811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
76318a2528dSJed Brown 
76418a2528dSJed Brown   Options Database Key:
765811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
76618a2528dSJed Brown 
76718a2528dSJed Brown   Level: advanced
76818a2528dSJed Brown 
7690ed210f4SBarry Smith .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()`
77018a2528dSJed Brown @*/
PetscMallocViewGet(PetscBool * logging)771d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging)
772d71ae5a4SJacob Faibussowitsch {
77318a2528dSJed Brown   PetscFunctionBegin;
77418a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
7753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
77618a2528dSJed Brown }
77718a2528dSJed Brown 
778608c71bfSMatthew G. Knepley /*@
7792d853995SBarry Smith   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer.
780608c71bfSMatthew G. Knepley 
781608c71bfSMatthew G. Knepley   Not Collective
782608c71bfSMatthew G. Knepley 
7834165533cSJose E. Roman   Input Parameters:
7840ed210f4SBarry Smith + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF`
785608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
786608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
787608c71bfSMatthew G. Knepley 
7880ed210f4SBarry Smith   Level: advanced
7890ed210f4SBarry Smith 
790608c71bfSMatthew G. Knepley   Note:
791608c71bfSMatthew G. Knepley   The viewer should not be collective.
792608c71bfSMatthew G. Knepley 
7932d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
7942d853995SBarry Smith 
7950ed210f4SBarry Smith .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
796608c71bfSMatthew G. Knepley @*/
PetscMallocTraceSet(PetscViewer viewer,PetscBool active,PetscLogDouble logmin)797d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
798d71ae5a4SJacob Faibussowitsch {
799608c71bfSMatthew G. Knepley   PetscFunctionBegin;
8009371c9d4SSatish Balay   if (!active) {
8019371c9d4SSatish Balay     PetscLogMallocTrace = -1;
8023ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8039371c9d4SSatish Balay   }
8040ed210f4SBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
8050ed210f4SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8060ed210f4SBarry Smith   PetscLogMallocTraceViewer = viewer;
807608c71bfSMatthew G. Knepley   PetscLogMallocTrace       = 0;
8089566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
809608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
810608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t)logmin;
8113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
812608c71bfSMatthew G. Knepley }
813608c71bfSMatthew G. Knepley 
814608c71bfSMatthew G. Knepley /*@
815811af0c4SBarry Smith   PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
816608c71bfSMatthew G. Knepley 
817608c71bfSMatthew G. Knepley   Not Collective
818608c71bfSMatthew G. Knepley 
8194165533cSJose E. Roman   Output Parameter:
820811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
821608c71bfSMatthew G. Knepley 
822608c71bfSMatthew G. Knepley   Options Database Key:
8230ed210f4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
824608c71bfSMatthew G. Knepley 
825608c71bfSMatthew G. Knepley   Level: advanced
826608c71bfSMatthew G. Knepley 
8272d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
8282d853995SBarry Smith 
8290ed210f4SBarry Smith .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
830608c71bfSMatthew G. Knepley @*/
PetscMallocTraceGet(PetscBool * logging)831d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
832d71ae5a4SJacob Faibussowitsch {
833608c71bfSMatthew G. Knepley   PetscFunctionBegin;
834608c71bfSMatthew G. Knepley   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
8353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
836608c71bfSMatthew G. Knepley }
837608c71bfSMatthew G. Knepley 
838e5c89e4eSSatish Balay /*@C
8392d853995SBarry Smith   PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()`
840e5c89e4eSSatish Balay 
84192f119d6SBarry Smith   Not Collective
842e5c89e4eSSatish Balay 
843e5c89e4eSSatish Balay   Input Parameter:
8440ed210f4SBarry Smith . fp - file pointer; or `NULL`
845e5c89e4eSSatish Balay 
846e5c89e4eSSatish Balay   Options Database Key:
847811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
848e5c89e4eSSatish Balay 
849e5c89e4eSSatish Balay   Level: advanced
850e5c89e4eSSatish Balay 
85192f119d6SBarry Smith   Notes:
852811af0c4SBarry Smith   `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
85392f119d6SBarry Smith 
854811af0c4SBarry Smith   `PetscMemoryView()` gives a brief summary of current memory usage
85592f119d6SBarry Smith 
85620f4b53cSBarry Smith   Fortran Notes:
8570ed210f4SBarry Smith   The calling sequence in Fortran is `PetscMallocView`(integer ierr)
85820f4b53cSBarry Smith 
8590ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
860e5c89e4eSSatish Balay @*/
PetscMallocView(FILE * fp)861d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp)
862d71ae5a4SJacob Faibussowitsch {
8632d853995SBarry Smith   PetscInt       n, *perm;
864e5c89e4eSSatish Balay   size_t        *shortlength;
865c69effb2SJacob Faibussowitsch   int           *shortcount;
86692f119d6SBarry Smith   PetscMPIInt    rank;
867ace3abfcSBarry Smith   PetscBool      match;
868e5c89e4eSSatish Balay   const char   **shortfunction;
869e5c89e4eSSatish Balay   PetscLogDouble rss;
870e5c89e4eSSatish Balay 
871e5c89e4eSSatish Balay   PetscFunctionBegin;
8729566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
873c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
874f56c2debSBarry Smith 
87500045ab3SPierre Jolivet   PetscCheck(PetscLogMalloc >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscMallocView() called without call to PetscMallocViewSet() this is often due to setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
876768aa557SSatish Balay 
877da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
8789566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&rss));
879e5c89e4eSSatish Balay   if (rss) {
88092f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
881e5c89e4eSSatish Balay   } else {
88292f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
883e5c89e4eSSatish Balay   }
884b13f2904SStefano Zampini   if (PetscLogMalloc > 0) {
8859371c9d4SSatish Balay     shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
8869371c9d4SSatish Balay     PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8879371c9d4SSatish Balay     shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
8889371c9d4SSatish Balay     PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8899371c9d4SSatish Balay     shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
8909371c9d4SSatish Balay     PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8912d853995SBarry Smith     n = 0;
8922d853995SBarry Smith     for (PetscInt i = 0; i < PetscLogMalloc; i++) {
8932d853995SBarry Smith       for (PetscInt j = 0; j < n; j++) {
8949566063dSJacob Faibussowitsch         PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
895e5c89e4eSSatish Balay         if (match) {
896e5c89e4eSSatish Balay           shortlength[j] += PetscLogMallocLength[i];
89759ffdab8SBarry Smith           shortcount[j]++;
898e5c89e4eSSatish Balay           goto foundit;
899e5c89e4eSSatish Balay         }
900e5c89e4eSSatish Balay       }
901e5c89e4eSSatish Balay       shortfunction[n] = PetscLogMallocFunction[i];
902e5c89e4eSSatish Balay       shortlength[n]   = PetscLogMallocLength[i];
90359ffdab8SBarry Smith       shortcount[n]    = 1;
904e5c89e4eSSatish Balay       n++;
905e5c89e4eSSatish Balay     foundit:;
906e5c89e4eSSatish Balay     }
907e5c89e4eSSatish Balay 
9089371c9d4SSatish Balay     perm = (PetscInt *)malloc(n * sizeof(PetscInt));
9099371c9d4SSatish Balay     PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
9102d853995SBarry Smith     for (PetscInt i = 0; i < n; i++) perm[i] = i;
911835f2295SStefano Zampini     PetscCall(PetscSortStrWithPermutation(n, shortfunction, perm));
912e5c89e4eSSatish Balay 
91392f119d6SBarry Smith     (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
9142d853995SBarry Smith     for (PetscInt i = 0; i < n; i++) (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]);
915e5c89e4eSSatish Balay     free(perm);
916e5c89e4eSSatish Balay     free(shortlength);
91759ffdab8SBarry Smith     free(shortcount);
918e5c89e4eSSatish Balay     free((char **)shortfunction);
919b13f2904SStefano Zampini   }
920c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
9213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
922e5c89e4eSSatish Balay }
923e5c89e4eSSatish Balay 
924dc37d89fSBarry Smith /*@
92592f119d6SBarry Smith   PetscMallocSetDebug - Set's PETSc memory debugging
926e5c89e4eSSatish Balay 
927e5c89e4eSSatish Balay   Not Collective
928e5c89e4eSSatish Balay 
929d8d19677SJose E. Roman   Input Parameters:
930811af0c4SBarry Smith + eachcall      - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
9310ed210f4SBarry Smith - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
932e5c89e4eSSatish Balay 
933811af0c4SBarry Smith   Options Database Keys:
93479dccf82SBarry Smith + -malloc_debug <true or false> - turns on or off debugging
9350ed210f4SBarry Smith . -malloc_test                  - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
93679dccf82SBarry Smith . -malloc_view_threshold t      - log only allocations larger than t
93710450e9eSJacob Faibussowitsch - -malloc_dump <filename>       - print a list of all memory that has not been freed, in `PetscFinalize()`
938e5c89e4eSSatish Balay 
93992f119d6SBarry Smith   Level: developer
94092f119d6SBarry Smith 
941811af0c4SBarry Smith   Note:
942811af0c4SBarry Smith   This is called in `PetscInitialize()` and should not be called elsewhere
94392f119d6SBarry Smith 
9442d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
945e5c89e4eSSatish Balay @*/
PetscMallocSetDebug(PetscBool eachcall,PetscBool initializenan)946d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
947d71ae5a4SJacob Faibussowitsch {
948e5c89e4eSSatish Balay   PetscFunctionBegin;
94908401ef6SPierre 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()");
9509566063dSJacob Faibussowitsch   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
95192f119d6SBarry Smith 
95292f119d6SBarry Smith   TRallocated           = 0;
95392f119d6SBarry Smith   TRfrags               = 0;
95492f119d6SBarry Smith   TRhead                = NULL;
95592f119d6SBarry Smith   TRid                  = 0;
9562d853995SBarry Smith   TRdebug               = eachcall;
95792f119d6SBarry Smith   TRMaxMem              = 0;
95892f119d6SBarry Smith   PetscLogMallocMax     = 10000;
95992f119d6SBarry Smith   PetscLogMalloc        = -1;
9602d4ee042Sprj-   TRdebugIinitializenan = initializenan;
9613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
962e5c89e4eSSatish Balay }
9630acecf5bSBarry Smith 
964dc37d89fSBarry Smith /*@
96592f119d6SBarry Smith   PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9660acecf5bSBarry Smith 
9670acecf5bSBarry Smith   Not Collective
9680acecf5bSBarry Smith 
96992f119d6SBarry Smith   Output Parameters:
97092f119d6SBarry Smith + basic         - doing basic debugging
971811af0c4SBarry Smith . eachcall      - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
9720ed210f4SBarry Smith - initializenan - initializes memory with `NaN`
9730acecf5bSBarry Smith 
9740acecf5bSBarry Smith   Level: intermediate
9750acecf5bSBarry Smith 
976811af0c4SBarry Smith   Note:
9772d853995SBarry Smith   By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no`
9780acecf5bSBarry Smith 
9792d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
9800acecf5bSBarry Smith @*/
PetscMallocGetDebug(PetscBool * basic,PetscBool * eachcall,PetscBool * initializenan)981d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
982d71ae5a4SJacob Faibussowitsch {
9830acecf5bSBarry Smith   PetscFunctionBegin;
98479dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
9852d853995SBarry Smith   if (eachcall) *eachcall = TRdebug;
9862d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9880acecf5bSBarry Smith }
989608c71bfSMatthew G. Knepley 
990608c71bfSMatthew G. Knepley /*@
991608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
992608c71bfSMatthew G. Knepley 
993608c71bfSMatthew G. Knepley   Not Collective
994608c71bfSMatthew G. Knepley 
995608c71bfSMatthew G. Knepley   Input Parameter:
996811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size
997608c71bfSMatthew G. Knepley 
998811af0c4SBarry Smith   Options Database Key:
999608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1000608c71bfSMatthew G. Knepley 
1001608c71bfSMatthew G. Knepley   Level: developer
1002608c71bfSMatthew G. Knepley 
10030ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1004608c71bfSMatthew G. Knepley @*/
PetscMallocLogRequestedSizeSet(PetscBool flg)1005d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1006d71ae5a4SJacob Faibussowitsch {
1007608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1008608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
10093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1010608c71bfSMatthew G. Knepley }
1011608c71bfSMatthew G. Knepley 
1012608c71bfSMatthew G. Knepley /*@
1013608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1014608c71bfSMatthew G. Knepley 
1015608c71bfSMatthew G. Knepley   Not Collective
1016608c71bfSMatthew G. Knepley 
1017608c71bfSMatthew G. Knepley   Output Parameter:
1018811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size
1019608c71bfSMatthew G. Knepley 
1020608c71bfSMatthew G. Knepley   Level: developer
1021608c71bfSMatthew G. Knepley 
10220ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1023608c71bfSMatthew G. Knepley @*/
PetscMallocLogRequestedSizeGet(PetscBool * flg)1024d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1025d71ae5a4SJacob Faibussowitsch {
1026608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1027608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
10283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1029608c71bfSMatthew G. Knepley }
1030