xref: /petsc/src/sys/memory/mtr.c (revision aec76313382a76d73a95f2051cbe4b1eab55c1c7)
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 
170700a824SBarry Smith #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9)
180700a824SBarry Smith #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c)
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;
270700a824SBarry Smith   PetscClassId classid;
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 
80e5c89e4eSSatish Balay   Return value:
81e5c89e4eSSatish Balay   The number of errors detected.
82e5c89e4eSSatish Balay 
83811af0c4SBarry Smith   Options Database Keys:.
840ed210f4SBarry Smith + -malloc_test  - turns this feature on when PETSc was not configured with `--with-debugging=0`
8592f119d6SBarry Smith - -malloc_debug - turns this feature on anytime
8692f119d6SBarry Smith 
87e5c89e4eSSatish Balay   Level: advanced
88e5c89e4eSSatish Balay 
89e5c89e4eSSatish Balay   Notes:
902d853995SBarry Smith   You should generally use `CHKMEMQ` as a short cut for calling this routine.
912d853995SBarry Smith 
920ed210f4SBarry Smith   Error messages are written to `stdout`.
930ed210f4SBarry Smith 
940ed210f4SBarry 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)
9538548759SBarry Smith 
96e5c89e4eSSatish Balay   No output is generated if there are no problems detected.
97e5c89e4eSSatish Balay 
98*aec76313SJacob Faibussowitsch   Fortran Notes:
9920f4b53cSBarry Smith   The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
10020f4b53cSBarry Smith 
1010ed210f4SBarry Smith .seealso: `CHKMEMQ`, `PetscMalloc()`, `PetscFree()`, `PetscMallocSetDebug()`
102e5c89e4eSSatish Balay @*/
103d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
104d71ae5a4SJacob Faibussowitsch {
1056c093d5bSvictor   TRSPACE      *head, *lasthead;
106e5c89e4eSSatish Balay   char         *a;
1070700a824SBarry Smith   PetscClassId *nend;
108e5c89e4eSSatish Balay 
1092d853995SBarry Smith   if (!TRdebug) return PETSC_SUCCESS;
1109371c9d4SSatish Balay   head     = TRhead;
1119371c9d4SSatish Balay   lasthead = NULL;
1122cba8197SMatthew G. Knepley   if (head && head->prev) {
1132d853995SBarry Smith     TRdebug = PETSC_FALSE;
1143ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1153ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
1164ed0ab5bSBarry Smith     return PETSC_ERR_MEMC;
1172cba8197SMatthew G. Knepley   }
118e5c89e4eSSatish Balay   while (head) {
1190700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
1202d853995SBarry Smith       TRdebug = PETSC_FALSE;
1213ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1223ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
1233ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
124e269983cSBarry Smith       if (lasthead) {
125e269983cSBarry Smith         a = (char *)(((TrSPACE *)head) + 1);
1263ba16761SJacob 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));
127e269983cSBarry Smith       }
128e269983cSBarry Smith       abort();
1294ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
130e5c89e4eSSatish Balay     }
131e5c89e4eSSatish Balay     a    = (char *)(((TrSPACE *)head) + 1);
1320700a824SBarry Smith     nend = (PetscClassId *)(a + head->size);
1330700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
1342d853995SBarry Smith       TRdebug = PETSC_FALSE;
1353ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
136e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
1373ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
1384ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
139e5c89e4eSSatish Balay       } else {
1403ba16761SJacob 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));
1413ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1424ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
143e5c89e4eSSatish Balay       }
144e5c89e4eSSatish Balay     }
1452cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
1462d853995SBarry Smith       TRdebug = PETSC_FALSE;
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 /*
1602d853995SBarry Smith     PetscTrMallocDefault - Malloc with logging and error checking
161e5c89e4eSSatish Balay 
162e5c89e4eSSatish Balay */
163d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
164d71ae5a4SJacob Faibussowitsch {
165e5c89e4eSSatish Balay   TRSPACE *head;
166e5c89e4eSSatish Balay   char    *inew;
167e5c89e4eSSatish Balay   size_t   nsize;
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay   PetscFunctionBegin;
1709371c9d4SSatish Balay   if (!a) {
1719371c9d4SSatish Balay     *result = NULL;
1723ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1739371c9d4SSatish Balay   }
174f0ba7cfcSLisandro Dalcin 
17511cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
176e5c89e4eSSatish Balay 
17725b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
1789566063dSJacob Faibussowitsch   PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
179e3ed9ee7SBarry Smith 
180e5c89e4eSSatish Balay   head = (TRSPACE *)inew;
181e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
182e5c89e4eSSatish Balay 
183e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
184e5c89e4eSSatish Balay   head->next   = TRhead;
185e5c89e4eSSatish Balay   TRhead       = head;
186f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
187e5c89e4eSSatish Balay   head->size   = nsize;
188608c71bfSMatthew G. Knepley   head->rsize  = a;
189e269983cSBarry Smith   head->id     = TRid++;
190e5c89e4eSSatish Balay   head->lineno = lineno;
191e5c89e4eSSatish Balay 
192e5c89e4eSSatish Balay   head->filename                  = filename;
193e5c89e4eSSatish Balay   head->functionname              = function;
1940700a824SBarry Smith   head->classid                   = CLASSID_VALUE;
1950700a824SBarry Smith   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
196e5c89e4eSSatish Balay 
197608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
198a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
199e3ed9ee7SBarry Smith   if (PetscLogMemory) {
2002d853995SBarry Smith     for (PetscInt i = 0; i < NumTRMaxMems; i++) {
201e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
202e3ed9ee7SBarry Smith     }
203e3ed9ee7SBarry Smith   }
204e5c89e4eSSatish Balay   TRfrags++;
205e5c89e4eSSatish Balay 
206dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
2079566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
2082d853995SBarry Smith   /* fix the line number to where PetscTrMallocDefault() was called, not the PetscFunctionBegin; */
2092c9581d2SBarry Smith   head->stack.line[head->stack.currentsize - 2] = lineno;
2102d853995SBarry Smith   head->stack.currentsize--;
21192f119d6SBarry Smith   #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2122d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
2132d853995SBarry Smith     size_t     n = a / sizeof(PetscReal);
21492f119d6SBarry Smith     PetscReal *s = (PetscReal *)inew;
21592f119d6SBarry Smith       /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
21692f119d6SBarry Smith     #if defined(PETSC_USE_REAL_SINGLE)
217df282883SBarry Smith     int nas = 0x7F800002;
21892f119d6SBarry Smith     #else
21992f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22092f119d6SBarry Smith     #endif
2212d853995SBarry Smith     for (size_t i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
22292f119d6SBarry Smith   }
22392f119d6SBarry Smith   #endif
224e5c89e4eSSatish Balay #endif
225e5c89e4eSSatish Balay 
226e5c89e4eSSatish Balay   /*
22792f119d6SBarry Smith          Allow logging of all mallocs made.
22892f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
229e5c89e4eSSatish Balay   */
230574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
231e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
232e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
23328b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
234a297a907SKarl Rupp 
235a2ea699eSBarry Smith       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
23628b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
237a297a907SKarl Rupp 
238a2ea699eSBarry Smith       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
23928b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
240e5c89e4eSSatish Balay     }
241e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
242e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
243e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
244e5c89e4eSSatish Balay   }
24548a46eb9SPierre Jolivet   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
246e5c89e4eSSatish Balay   *result = (void *)inew;
2473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
248e5c89e4eSSatish Balay }
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay /*
2512d853995SBarry Smith    PetscTrFreeDefault - Free with logging and error checking
252e5c89e4eSSatish Balay 
253e5c89e4eSSatish Balay */
254d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
255d71ae5a4SJacob Faibussowitsch {
256e5c89e4eSSatish Balay   char         *a = (char *)aa;
257e5c89e4eSSatish Balay   TRSPACE      *head;
258e5c89e4eSSatish Balay   char         *ahead;
259608c71bfSMatthew G. Knepley   size_t        asize;
2600700a824SBarry Smith   PetscClassId *nend;
261e5c89e4eSSatish Balay 
262e5c89e4eSSatish Balay   PetscFunctionBegin;
2633ba16761SJacob Faibussowitsch   if (!a) PetscFunctionReturn(PETSC_SUCCESS);
264e5c89e4eSSatish Balay 
2659566063dSJacob Faibussowitsch   PetscCall(PetscMallocValidate(lineno, function, filename));
266e5c89e4eSSatish Balay 
267e5c89e4eSSatish Balay   ahead = a;
268e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
269e5c89e4eSSatish Balay   head  = (TRSPACE *)a;
270e5c89e4eSSatish Balay 
2710700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
2722d853995SBarry Smith     TRdebug = PETSC_FALSE;
2733ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2743ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
275e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
276e5c89e4eSSatish Balay   }
2770700a824SBarry Smith   nend = (PetscClassId *)(ahead + head->size);
2780700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
2792d853995SBarry Smith     TRdebug = PETSC_FALSE;
280e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
2813ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2823ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
283e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
2843ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
285e5c89e4eSSatish Balay       } else {
2863ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
287e5c89e4eSSatish Balay       }
288e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
289e5c89e4eSSatish Balay     } else {
290e5c89e4eSSatish Balay       /* Damaged tail */
2913ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2923ba16761SJacob 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));
2933ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
294e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
295e5c89e4eSSatish Balay     }
296e5c89e4eSSatish Balay   }
297608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
2989566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
299608c71bfSMatthew G. Knepley   }
300e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
301e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as allocated location */
302608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
303608c71bfSMatthew G. Knepley     head->lineno       = lineno;
304608c71bfSMatthew G. Knepley     head->filename     = filename;
305e5c89e4eSSatish Balay     head->functionname = function;
306e5c89e4eSSatish Balay   } else {
307e5c89e4eSSatish Balay     head->lineno = -head->lineno;
308e5c89e4eSSatish Balay   }
309608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
31008401ef6SPierre Jolivet   PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
311608c71bfSMatthew G. Knepley   TRallocated -= asize;
312e5c89e4eSSatish Balay   TRfrags--;
313e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
314e5c89e4eSSatish Balay   else TRhead = head->next;
315e5c89e4eSSatish Balay 
316e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
3179566063dSJacob Faibussowitsch   PetscCall(PetscFreeAlign(a, lineno, function, filename));
3183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
319e5c89e4eSSatish Balay }
320e5c89e4eSSatish Balay 
3213221ece2SMatthew G. Knepley /*
3222d853995SBarry Smith   PetscTrReallocDefault - Realloc with logging and error checking
3233221ece2SMatthew G. Knepley 
3243221ece2SMatthew G. Knepley */
325d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
326d71ae5a4SJacob Faibussowitsch {
3273221ece2SMatthew G. Knepley   char         *a = (char *)*result;
3283221ece2SMatthew G. Knepley   TRSPACE      *head;
3293221ece2SMatthew G. Knepley   char         *ahead, *inew;
3303221ece2SMatthew G. Knepley   PetscClassId *nend;
3313221ece2SMatthew G. Knepley   size_t        nsize;
3323221ece2SMatthew G. Knepley 
3333221ece2SMatthew G. Knepley   PetscFunctionBegin;
33492f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
335c22f1541SToby Isaac   if (!len) {
3369566063dSJacob Faibussowitsch     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
337c22f1541SToby Isaac     *result = NULL;
3383ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
339c22f1541SToby Isaac   }
340da81f932SPierre Jolivet   /* If the original space was NULL just use the regular malloc() */
341f590eff4SLisandro Dalcin   if (!*result) {
3429566063dSJacob Faibussowitsch     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
3433ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
344f590eff4SLisandro Dalcin   }
3453221ece2SMatthew G. Knepley 
34611cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
3473221ece2SMatthew G. Knepley 
3483221ece2SMatthew G. Knepley   ahead = a;
3493221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3503221ece2SMatthew G. Knepley   head  = (TRSPACE *)a;
3513221ece2SMatthew G. Knepley   inew  = a;
3523221ece2SMatthew G. Knepley 
3533221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3542d853995SBarry Smith     TRdebug = PETSC_FALSE;
3553ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3563ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
3573221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
3583221ece2SMatthew G. Knepley   }
3593221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3603221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3612d853995SBarry Smith     TRdebug = PETSC_FALSE;
3623221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3633ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3643ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
3653221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3663ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3673221ece2SMatthew G. Knepley       } else {
3683ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
3693221ece2SMatthew G. Knepley       }
3703221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
3713221ece2SMatthew G. Knepley     } else {
3723221ece2SMatthew G. Knepley       /* Damaged tail */
3733ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3743ba16761SJacob 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));
3753ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3763221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
3773221ece2SMatthew G. Knepley     }
3783221ece2SMatthew G. Knepley   }
3793221ece2SMatthew G. Knepley 
38092f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
381608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
3823221ece2SMatthew G. Knepley   TRfrags--;
3833221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
3843221ece2SMatthew G. Knepley   else TRhead = head->next;
3853221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
3863221ece2SMatthew G. Knepley 
3873221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
3889566063dSJacob Faibussowitsch   PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
3893221ece2SMatthew G. Knepley 
3903221ece2SMatthew G. Knepley   head = (TRSPACE *)inew;
3913221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
3923221ece2SMatthew G. Knepley 
3933221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
3943221ece2SMatthew G. Knepley   head->next   = TRhead;
3953221ece2SMatthew G. Knepley   TRhead       = head;
3963221ece2SMatthew G. Knepley   head->prev   = NULL;
3973221ece2SMatthew G. Knepley   head->size   = nsize;
398608c71bfSMatthew G. Knepley   head->rsize  = len;
399e269983cSBarry Smith   head->id     = TRid++;
4003221ece2SMatthew G. Knepley   head->lineno = lineno;
4013221ece2SMatthew G. Knepley 
4023221ece2SMatthew G. Knepley   head->filename                  = filename;
4033221ece2SMatthew G. Knepley   head->functionname              = function;
4043221ece2SMatthew G. Knepley   head->classid                   = CLASSID_VALUE;
4053221ece2SMatthew G. Knepley   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
4063221ece2SMatthew G. Knepley 
407608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4083221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
409e3ed9ee7SBarry Smith   if (PetscLogMemory) {
4102d853995SBarry Smith     for (PetscInt i = 0; i < NumTRMaxMems; i++) {
411e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
412e3ed9ee7SBarry Smith     }
413e3ed9ee7SBarry Smith   }
4143221ece2SMatthew G. Knepley   TRfrags++;
4153221ece2SMatthew G. Knepley 
416dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
4179566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
4183221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4193221ece2SMatthew G. Knepley   head->stack.line[head->stack.currentsize - 2] = lineno;
4203221ece2SMatthew G. Knepley #endif
4213221ece2SMatthew G. Knepley 
4223221ece2SMatthew G. Knepley   /*
42392f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
42492f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4253221ece2SMatthew G. Knepley   */
4263221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4273221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4283221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
42928b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4303221ece2SMatthew G. Knepley 
4313221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
43228b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4333221ece2SMatthew G. Knepley 
4343221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
43528b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4363221ece2SMatthew G. Knepley     }
4373221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4383221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4393221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4403221ece2SMatthew G. Knepley   }
4413221ece2SMatthew G. Knepley   *result = (void *)inew;
4423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4433221ece2SMatthew G. Knepley }
4443221ece2SMatthew G. Knepley 
445fe7fb379SMatthew Knepley /*@C
44692f119d6SBarry Smith   PetscMemoryView - Shows the amount of memory currently being used in a communicator.
447e5c89e4eSSatish Balay 
448c3339decSBarry Smith   Collective
449e5c89e4eSSatish Balay 
450d8d19677SJose E. Roman   Input Parameters:
4510ed210f4SBarry Smith + viewer  - the viewer to output the information on
452e5c89e4eSSatish Balay - message - string printed before values
453e5c89e4eSSatish Balay 
454811af0c4SBarry Smith   Options Database Keys:
45592f119d6SBarry Smith + -malloc_debug    - have PETSc track how much memory it has allocated
4560ed210f4SBarry Smith . -log_view_memory - print memory usage per event when `-log_view` is used
4570ed210f4SBarry Smith - -memory_view     - during `PetscFinalize()` have this routine called
4580841954dSBarry Smith 
459e5c89e4eSSatish Balay   Level: intermediate
460e5c89e4eSSatish Balay 
4610ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
462e5c89e4eSSatish Balay  @*/
463d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
464d71ae5a4SJacob Faibussowitsch {
4652d853995SBarry Smith   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax;
4662d853995SBarry Smith   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax, maxgresident, maxgresidentmax;
467e5c89e4eSSatish Balay   MPI_Comm       comm;
468e5c89e4eSSatish Balay 
469e5c89e4eSSatish Balay   PetscFunctionBegin;
470e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4719566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&allocated));
4729566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4739566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&resident));
4749566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
475e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
4769566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
4779566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
478e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4799566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4809566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4819566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4829566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
4839566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4859566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
4879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4889566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4899566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
4919566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4929566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4939566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4949566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
495e5c89e4eSSatish Balay   } else if (resident && residentmax) {
4969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
4979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
4989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
4999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
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));
504e5c89e4eSSatish Balay   } else if (resident && allocated) {
5059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
514e5c89e4eSSatish Balay   } else if (allocated) {
5159566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5179566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5189566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
521e5c89e4eSSatish Balay   } else {
5229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
523e5c89e4eSSatish Balay   }
5249566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
5253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
526e5c89e4eSSatish Balay }
527e5c89e4eSSatish Balay 
52846eb3923SBarry Smith /*@
529811af0c4SBarry Smith   PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
530e5c89e4eSSatish Balay 
531e5c89e4eSSatish Balay   Not Collective
532e5c89e4eSSatish Balay 
5332fe279fdSBarry Smith   Output Parameter:
534e5c89e4eSSatish Balay . space - number of bytes currently allocated
535e5c89e4eSSatish Balay 
536e5c89e4eSSatish Balay   Level: intermediate
537e5c89e4eSSatish Balay 
5382d853995SBarry Smith   Note:
5392d853995SBarry Smith   This only works if `-memory_view` or `-log_view_memory` have been used
5402d853995SBarry Smith 
5410ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
542db781477SPatrick Sanan           `PetscMemoryGetMaximumUsage()`
543e5c89e4eSSatish Balay  @*/
544d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
545d71ae5a4SJacob Faibussowitsch {
546e5c89e4eSSatish Balay   PetscFunctionBegin;
547e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRallocated;
5483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
549e5c89e4eSSatish Balay }
550e5c89e4eSSatish Balay 
551dc37d89fSBarry Smith /*@
552811af0c4SBarry Smith   PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
553811af0c4SBarry Smith   during this run, the high water mark.
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay   Not Collective
556e5c89e4eSSatish Balay 
5572fe279fdSBarry Smith   Output Parameter:
558e5c89e4eSSatish Balay . space - maximum number of bytes ever allocated at one time
559e5c89e4eSSatish Balay 
560e5c89e4eSSatish Balay   Level: intermediate
561e5c89e4eSSatish Balay 
5622d853995SBarry Smith   Note:
5632d853995SBarry Smith   This only works if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
5642d853995SBarry Smith 
5650ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
566db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
567e5c89e4eSSatish Balay  @*/
568d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
569d71ae5a4SJacob Faibussowitsch {
570e5c89e4eSSatish Balay   PetscFunctionBegin;
571e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRMaxMem;
5723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
573e5c89e4eSSatish Balay }
574e5c89e4eSSatish Balay 
575e3ed9ee7SBarry Smith /*@
576e3ed9ee7SBarry Smith   PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
577e3ed9ee7SBarry Smith 
578e3ed9ee7SBarry Smith   Not Collective
579e3ed9ee7SBarry Smith 
580e3ed9ee7SBarry Smith   Input Parameter:
581e3ed9ee7SBarry Smith . event - an event id; this is just for error checking
582e3ed9ee7SBarry Smith 
583e3ed9ee7SBarry Smith   Level: developer
584e3ed9ee7SBarry Smith 
5852d853995SBarry Smith   Note:
5862d853995SBarry Smith   This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
5872d853995SBarry Smith 
5880ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
589db781477SPatrick Sanan           `PetscMallocPopMaximumUsage()`
590e3ed9ee7SBarry Smith  @*/
591d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event)
592d71ae5a4SJacob Faibussowitsch {
593e3ed9ee7SBarry Smith   PetscFunctionBegin;
5943ba16761SJacob Faibussowitsch   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
595e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
596e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
5973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
598e3ed9ee7SBarry Smith }
599e3ed9ee7SBarry Smith 
600e3ed9ee7SBarry Smith /*@
601e3ed9ee7SBarry Smith   PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
602e3ed9ee7SBarry Smith 
603e3ed9ee7SBarry Smith   Not Collective
604e3ed9ee7SBarry Smith 
605e3ed9ee7SBarry Smith   Input Parameter:
606e3ed9ee7SBarry Smith . event - an event id; this is just for error checking
607e3ed9ee7SBarry Smith 
608e3ed9ee7SBarry Smith   Output Parameter:
609e3ed9ee7SBarry Smith . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
610e3ed9ee7SBarry Smith 
611e3ed9ee7SBarry Smith   Level: developer
612e3ed9ee7SBarry Smith 
6132d853995SBarry Smith   Note:
6142d853995SBarry Smith   This only does anything if `PetscMemorySetGetMaximumUsage()`, `-memory_view`, or `-log_view_memory` have been used
6152d853995SBarry Smith 
6160ed210f4SBarry Smith .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, `PetscMalloc()`, `PetscFree()`,
617db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
618e3ed9ee7SBarry Smith  @*/
619d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
620d71ae5a4SJacob Faibussowitsch {
621e3ed9ee7SBarry Smith   PetscFunctionBegin;
622e3ed9ee7SBarry Smith   *mu = 0;
6233ba16761SJacob Faibussowitsch   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
62408401ef6SPierre Jolivet   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
625e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
6263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
627e3ed9ee7SBarry Smith }
628e3ed9ee7SBarry Smith 
629a64a8e02SBarry Smith /*@C
630811af0c4SBarry Smith   PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
631a64a8e02SBarry Smith 
6320ed210f4SBarry Smith   Not Collective
633a64a8e02SBarry Smith 
634a64a8e02SBarry Smith   Input Parameter:
635a64a8e02SBarry Smith . ptr - the memory location
636a64a8e02SBarry Smith 
637fd292e60Sprj-   Output Parameter:
638a64a8e02SBarry Smith . stack - the stack indicating where the program allocated this memory
639a64a8e02SBarry Smith 
640a64a8e02SBarry Smith   Level: intermediate
641a64a8e02SBarry Smith 
6422d853995SBarry Smith   Note:
6432d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
6442d853995SBarry Smith 
6450ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
646a64a8e02SBarry Smith @*/
647d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
648d71ae5a4SJacob Faibussowitsch {
649dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
650a64a8e02SBarry Smith   TRSPACE *head;
651a64a8e02SBarry Smith 
652a64a8e02SBarry Smith   PetscFunctionBegin;
653a64a8e02SBarry Smith   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
654a64a8e02SBarry Smith   *stack = &head->stack;
6553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65676386721SLisandro Dalcin #else
657f0ba7cfcSLisandro Dalcin   *stack = NULL;
6583ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
659a64a8e02SBarry Smith #endif
660dfb7d7afSStefano Zampini }
661a64a8e02SBarry Smith 
662e5c89e4eSSatish Balay /*@C
66392f119d6SBarry Smith   PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
664e5c89e4eSSatish Balay   printed is: size of space (in bytes), address of space, id of space,
665e5c89e4eSSatish Balay   file in which space was allocated, and line number at which it was
666e5c89e4eSSatish Balay   allocated.
667e5c89e4eSSatish Balay 
66892f119d6SBarry Smith   Not Collective
669e5c89e4eSSatish Balay 
670e5c89e4eSSatish Balay   Input Parameter:
6710ed210f4SBarry Smith . fp - file pointer.  If `fp` is `NULL`, `stdout` is assumed.
672e5c89e4eSSatish Balay 
673e5c89e4eSSatish Balay   Options Database Key:
6740ed210f4SBarry Smith . -malloc_dump <optional filename> - Print summary of unfreed memory during call to `PetscFinalize()`, writing to filename if given
675e5c89e4eSSatish Balay 
676e5c89e4eSSatish Balay   Level: intermediate
677e5c89e4eSSatish Balay 
67895452b02SPatrick Sanan   Notes:
679811af0c4SBarry Smith   Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
680e5c89e4eSSatish Balay 
681811af0c4SBarry Smith   When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
68292f119d6SBarry Smith 
683811af0c4SBarry Smith   `PetscMallocView()` prints a list of all memory ever allocated
68492f119d6SBarry Smith 
6852d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
6862d853995SBarry Smith 
687*aec76313SJacob Faibussowitsch   Fortran Notes:
6880ed210f4SBarry Smith   The calling sequence is `PetscMallocDump`(PetscErrorCode ierr). A `fp` parameter is not supported.
68920f4b53cSBarry Smith 
690*aec76313SJacob Faibussowitsch   Developer Notes:
6912d853995SBarry Smith   This should be absorbed into `PetscMallocView()`
6922d853995SBarry Smith 
6930ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
694e5c89e4eSSatish Balay @*/
695d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp)
696d71ae5a4SJacob Faibussowitsch {
697e5c89e4eSSatish Balay   TRSPACE    *head;
698e3ed9ee7SBarry Smith   size_t      libAlloc = 0;
699e5c89e4eSSatish Balay   PetscMPIInt rank;
700e5c89e4eSSatish Balay 
701e5c89e4eSSatish Balay   PetscFunctionBegin;
7029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
703da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
704e5c89e4eSSatish Balay   head = TRhead;
705e5c89e4eSSatish Balay   while (head) {
706608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7075486ca60SMatthew G. Knepley     head = head->next;
7085486ca60SMatthew G. Knepley   }
7095486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7105486ca60SMatthew G. Knepley   head = TRhead;
7115486ca60SMatthew G. Knepley   while (head) {
7125486ca60SMatthew G. Knepley     PetscBool isLib;
7135486ca60SMatthew G. Knepley 
7149566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7155486ca60SMatthew G. Knepley     if (!isLib) {
716dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
7172d853995SBarry Smith       fprintf(fp, "[%2d] %.0f bytes\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size));
7189566063dSJacob Faibussowitsch       PetscCall(PetscStackPrint(&head->stack, fp));
7192d853995SBarry Smith #else
7202d853995SBarry Smith       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
721e5c89e4eSSatish Balay #endif
7225486ca60SMatthew G. Knepley     }
723e5c89e4eSSatish Balay     head = head->next;
724e5c89e4eSSatish Balay   }
7253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
726e5c89e4eSSatish Balay }
727e5c89e4eSSatish Balay 
728dc37d89fSBarry Smith /*@
729811af0c4SBarry Smith   PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
730574034a9SJed Brown 
731574034a9SJed Brown   Not Collective
732574034a9SJed Brown 
7334165533cSJose E. Roman   Input Parameter:
7340ed210f4SBarry Smith . logmin - minimum allocation size to log, or `PETSC_DEFAULT` to log all memory allocations
735574034a9SJed Brown 
7360ed210f4SBarry Smith   Options Database Keys:
737811af0c4SBarry Smith + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
7382d853995SBarry Smith . -malloc_view_threshold <min>     - Sets a minimum size if `-malloc_view` is used
7398b254c29SBarry Smith - -log_view_memory                 - view the memory usage also with the -log_view option
740574034a9SJed Brown 
741574034a9SJed Brown   Level: advanced
742574034a9SJed Brown 
7430ed210f4SBarry Smith   Note:
744811af0c4SBarry Smith   Must be called after `PetscMallocSetDebug()`
74592f119d6SBarry Smith 
746*aec76313SJacob Faibussowitsch   Developer Notes:
747811af0c4SBarry Smith   Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
74892f119d6SBarry Smith 
7490ed210f4SBarry Smith .seealso: `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`, `PetscMalloc()`, `PetscFree()`
750574034a9SJed Brown @*/
751d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
752d71ae5a4SJacob Faibussowitsch {
753574034a9SJed Brown   PetscFunctionBegin;
75492f119d6SBarry Smith   PetscLogMalloc = 0;
7559566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
756574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
757574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
7583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
759574034a9SJed Brown }
760574034a9SJed Brown 
761dc37d89fSBarry Smith /*@
762811af0c4SBarry Smith   PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
76318a2528dSJed Brown 
76418a2528dSJed Brown   Not Collective
76518a2528dSJed Brown 
7664165533cSJose E. Roman   Output Parameter
767811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
76818a2528dSJed Brown 
76918a2528dSJed Brown   Options Database Key:
770811af0c4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
77118a2528dSJed Brown 
77218a2528dSJed Brown   Level: advanced
77318a2528dSJed Brown 
7740ed210f4SBarry Smith .seealso: `PetscMallocViewSet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`, `PetscMalloc()`, `PetscFree()`
77518a2528dSJed Brown @*/
776d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging)
777d71ae5a4SJacob Faibussowitsch {
77818a2528dSJed Brown   PetscFunctionBegin;
77918a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
7803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78118a2528dSJed Brown }
78218a2528dSJed Brown 
783608c71bfSMatthew G. Knepley /*@
7842d853995SBarry Smith   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`. That is print each `PetscMalloc()` and `PetscFree()` call to a viewer.
785608c71bfSMatthew G. Knepley 
786608c71bfSMatthew G. Knepley   Not Collective
787608c71bfSMatthew G. Knepley 
7884165533cSJose E. Roman   Input Parameters:
7890ed210f4SBarry Smith + viewer - The viewer to use for tracing, or `NULL` to use `PETSC_VIEWER_STDOUT_SELF`
790608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
791608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
792608c71bfSMatthew G. Knepley 
7930ed210f4SBarry Smith   Level: advanced
7940ed210f4SBarry Smith 
795608c71bfSMatthew G. Knepley   Note:
796608c71bfSMatthew G. Knepley   The viewer should not be collective.
797608c71bfSMatthew G. Knepley 
7982d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
7992d853995SBarry Smith 
8000ed210f4SBarry Smith .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
801608c71bfSMatthew G. Knepley @*/
802d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
803d71ae5a4SJacob Faibussowitsch {
804608c71bfSMatthew G. Knepley   PetscFunctionBegin;
8059371c9d4SSatish Balay   if (!active) {
8069371c9d4SSatish Balay     PetscLogMallocTrace = -1;
8073ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8089371c9d4SSatish Balay   }
8090ed210f4SBarry Smith   if (!viewer) viewer = PETSC_VIEWER_STDOUT_SELF;
8100ed210f4SBarry Smith   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
8110ed210f4SBarry Smith   PetscLogMallocTraceViewer = viewer;
812608c71bfSMatthew G. Knepley   PetscLogMallocTrace       = 0;
8139566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
814608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
815608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t)logmin;
8163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
817608c71bfSMatthew G. Knepley }
818608c71bfSMatthew G. Knepley 
819608c71bfSMatthew G. Knepley /*@
820811af0c4SBarry Smith   PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
821608c71bfSMatthew G. Knepley 
822608c71bfSMatthew G. Knepley   Not Collective
823608c71bfSMatthew G. Knepley 
8244165533cSJose E. Roman   Output Parameter:
825811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
826608c71bfSMatthew G. Knepley 
827608c71bfSMatthew G. Knepley   Options Database Key:
8280ed210f4SBarry Smith . -malloc_view <optional filename> - Activates `PetscMallocView()`
829608c71bfSMatthew G. Knepley 
830608c71bfSMatthew G. Knepley   Level: advanced
831608c71bfSMatthew G. Knepley 
8322d853995SBarry Smith   This only does anything if `-malloc_debug` (or `-malloc_test` if PETSc was configured with debugging) has been used
8332d853995SBarry Smith 
8340ed210f4SBarry Smith .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`, `PetscMalloc()`, `PetscFree()`
835608c71bfSMatthew G. Knepley @*/
836d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
837d71ae5a4SJacob Faibussowitsch {
838608c71bfSMatthew G. Knepley   PetscFunctionBegin;
839608c71bfSMatthew G. Knepley   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
8403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
841608c71bfSMatthew G. Knepley }
842608c71bfSMatthew G. Knepley 
843e5c89e4eSSatish Balay /*@C
8442d853995SBarry Smith   PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls `PetscMemoryGetMaximumUsage()`
845e5c89e4eSSatish Balay 
84692f119d6SBarry Smith   Not Collective
847e5c89e4eSSatish Balay 
848e5c89e4eSSatish Balay   Input Parameter:
8490ed210f4SBarry 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:
8620ed210f4SBarry Smith   The calling sequence in Fortran is `PetscMallocView`(integer ierr)
86320f4b53cSBarry Smith 
8640ed210f4SBarry Smith .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`, `PetscMalloc()`, `PetscFree()`
865e5c89e4eSSatish Balay @*/
866d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp)
867d71ae5a4SJacob Faibussowitsch {
8682d853995SBarry Smith   PetscInt       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");
8962d853995SBarry Smith     n = 0;
8972d853995SBarry Smith     for (PetscInt i = 0; i < PetscLogMalloc; i++) {
8982d853995SBarry Smith       for (PetscInt j = 0; j < n; j++) {
8999566063dSJacob Faibussowitsch         PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
900e5c89e4eSSatish Balay         if (match) {
901e5c89e4eSSatish Balay           shortlength[j] += PetscLogMallocLength[i];
90259ffdab8SBarry Smith           shortcount[j]++;
903e5c89e4eSSatish Balay           goto foundit;
904e5c89e4eSSatish Balay         }
905e5c89e4eSSatish Balay       }
906e5c89e4eSSatish Balay       shortfunction[n] = PetscLogMallocFunction[i];
907e5c89e4eSSatish Balay       shortlength[n]   = PetscLogMallocLength[i];
90859ffdab8SBarry Smith       shortcount[n]    = 1;
909e5c89e4eSSatish Balay       n++;
910e5c89e4eSSatish Balay     foundit:;
911e5c89e4eSSatish Balay     }
912e5c89e4eSSatish Balay 
9139371c9d4SSatish Balay     perm = (PetscInt *)malloc(n * sizeof(PetscInt));
9149371c9d4SSatish Balay     PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
9152d853995SBarry Smith     for (PetscInt i = 0; i < n; i++) perm[i] = i;
9169566063dSJacob Faibussowitsch     PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
917e5c89e4eSSatish Balay 
91892f119d6SBarry Smith     (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
9192d853995SBarry 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]]);
920e5c89e4eSSatish Balay     free(perm);
921e5c89e4eSSatish Balay     free(shortlength);
92259ffdab8SBarry Smith     free(shortcount);
923e5c89e4eSSatish Balay     free((char **)shortfunction);
924b13f2904SStefano Zampini   }
925c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
9263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
927e5c89e4eSSatish Balay }
928e5c89e4eSSatish Balay 
929dc37d89fSBarry Smith /*@
93092f119d6SBarry Smith   PetscMallocSetDebug - Set's PETSc memory debugging
931e5c89e4eSSatish Balay 
932e5c89e4eSSatish Balay   Not Collective
933e5c89e4eSSatish Balay 
934d8d19677SJose E. Roman   Input Parameters:
935811af0c4SBarry Smith + eachcall      - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
9360ed210f4SBarry Smith - initializenan - initializes all memory with `NaN` to catch use of uninitialized floating point arrays
937e5c89e4eSSatish Balay 
938811af0c4SBarry Smith   Options Database Keys:
93979dccf82SBarry Smith + -malloc_debug <true or false> - turns on or off debugging
9400ed210f4SBarry Smith . -malloc_test                  - turns on all debugging if PETSc was configured with debugging including `-malloc_dump`, otherwise ignored
94179dccf82SBarry Smith . -malloc_view_threshold t      - log only allocations larger than t
9422d853995SBarry Smith . -malloc_dump <filename>       - print a list of all memory that has not been freed, in `PetscFinalize()`
943e5c89e4eSSatish Balay 
94492f119d6SBarry Smith   Level: developer
94592f119d6SBarry Smith 
946811af0c4SBarry Smith   Note:
947811af0c4SBarry Smith   This is called in `PetscInitialize()` and should not be called elsewhere
94892f119d6SBarry Smith 
9492d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocGetDebug()`, `PetscMalloc()`, `PetscFree()`
950e5c89e4eSSatish Balay @*/
951d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
952d71ae5a4SJacob Faibussowitsch {
953e5c89e4eSSatish Balay   PetscFunctionBegin;
95408401ef6SPierre 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()");
9559566063dSJacob Faibussowitsch   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
95692f119d6SBarry Smith 
95792f119d6SBarry Smith   TRallocated           = 0;
95892f119d6SBarry Smith   TRfrags               = 0;
95992f119d6SBarry Smith   TRhead                = NULL;
96092f119d6SBarry Smith   TRid                  = 0;
9612d853995SBarry Smith   TRdebug               = eachcall;
96292f119d6SBarry Smith   TRMaxMem              = 0;
96392f119d6SBarry Smith   PetscLogMallocMax     = 10000;
96492f119d6SBarry Smith   PetscLogMalloc        = -1;
9652d4ee042Sprj-   TRdebugIinitializenan = initializenan;
9663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
967e5c89e4eSSatish Balay }
9680acecf5bSBarry Smith 
969dc37d89fSBarry Smith /*@
97092f119d6SBarry Smith   PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9710acecf5bSBarry Smith 
9720acecf5bSBarry Smith   Not Collective
9730acecf5bSBarry Smith 
97492f119d6SBarry Smith   Output Parameters:
97592f119d6SBarry Smith + basic         - doing basic debugging
976811af0c4SBarry Smith . eachcall      - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
9770ed210f4SBarry Smith - initializenan - initializes memory with `NaN`
9780acecf5bSBarry Smith 
9790acecf5bSBarry Smith   Level: intermediate
9800acecf5bSBarry Smith 
981811af0c4SBarry Smith   Note:
9822d853995SBarry Smith   By default, the debug configuration of PETSc always does some debugging unless you run with `-malloc_debug no`
9830acecf5bSBarry Smith 
9842d853995SBarry Smith .seealso: `CHKMEMQ`, `PetscMallocValidate()`, `PetscMallocSetDebug()`, `PetscMalloc()`, `PetscFree()`
9850acecf5bSBarry Smith @*/
986d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
987d71ae5a4SJacob Faibussowitsch {
9880acecf5bSBarry Smith   PetscFunctionBegin;
98979dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
9902d853995SBarry Smith   if (eachcall) *eachcall = TRdebug;
9912d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9930acecf5bSBarry Smith }
994608c71bfSMatthew G. Knepley 
995608c71bfSMatthew G. Knepley /*@
996608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
997608c71bfSMatthew G. Knepley 
998608c71bfSMatthew G. Knepley   Not Collective
999608c71bfSMatthew G. Knepley 
1000608c71bfSMatthew G. Knepley   Input Parameter:
1001811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size
1002608c71bfSMatthew G. Knepley 
1003811af0c4SBarry Smith   Options Database Key:
1004608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1005608c71bfSMatthew G. Knepley 
1006608c71bfSMatthew G. Knepley   Level: developer
1007608c71bfSMatthew G. Knepley 
10080ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1009608c71bfSMatthew G. Knepley @*/
1010d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1011d71ae5a4SJacob Faibussowitsch {
1012608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1013608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
10143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1015608c71bfSMatthew G. Knepley }
1016608c71bfSMatthew G. Knepley 
1017608c71bfSMatthew G. Knepley /*@
1018608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1019608c71bfSMatthew G. Knepley 
1020608c71bfSMatthew G. Knepley   Not Collective
1021608c71bfSMatthew G. Knepley 
1022608c71bfSMatthew G. Knepley   Output Parameter:
1023811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size
1024608c71bfSMatthew G. Knepley 
1025608c71bfSMatthew G. Knepley   Level: developer
1026608c71bfSMatthew G. Knepley 
10270ed210f4SBarry Smith .seealso: `PetscMallocLogRequestedSizeSet()`, `PetscMallocViewSet()`, `PetscMalloc()`, `PetscFree()`
1028608c71bfSMatthew G. Knepley @*/
1029d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1030d71ae5a4SJacob Faibussowitsch {
1031608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1032608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
10333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1034608c71bfSMatthew G. Knepley }
1035