xref: /petsc/src/sys/memory/mtr.c (revision 20f4b53cbb5e9bd9ef12b76a8697d60d197cda17)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
392f119d6SBarry Smith      Interface to malloc() and free(). This code allows for logging of memory usage and some error checking
4e5c89e4eSSatish Balay */
527104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/
6665c2dedSJed Brown #include <petscviewer.h>
7e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
8e5c89e4eSSatish Balay   #include <malloc.h>
9e5c89e4eSSatish Balay #endif
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay /*
12e5c89e4eSSatish Balay      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
13e5c89e4eSSatish Balay */
14071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **);
1595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]);
1695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **);
17e5c89e4eSSatish Balay 
180700a824SBarry Smith #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9)
190700a824SBarry Smith #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c)
20e5c89e4eSSatish Balay 
2192f119d6SBarry Smith /*  this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */
22e5c89e4eSSatish Balay typedef struct _trSPACE {
23608c71bfSMatthew G. Knepley   size_t       size, rsize; /* Aligned size and requested size */
24e5c89e4eSSatish Balay   int          id;
25e5c89e4eSSatish Balay   int          lineno;
26e5c89e4eSSatish Balay   const char  *filename;
27e5c89e4eSSatish Balay   const char  *functionname;
280700a824SBarry Smith   PetscClassId classid;
29dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
30e5c89e4eSSatish Balay   PetscStack stack;
31e5c89e4eSSatish Balay #endif
32e5c89e4eSSatish Balay   struct _trSPACE *next, *prev;
33e5c89e4eSSatish Balay } TRSPACE;
34e5c89e4eSSatish Balay 
3525b53cc9SJed Brown /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
3692f119d6SBarry Smith    It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
3725b53cc9SJed Brown */
38a64a8e02SBarry Smith #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1))
39e5c89e4eSSatish Balay 
4025b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains
4125b53cc9SJed Brown    a minimum alignment of PETSC_MEMALIGN.
4225b53cc9SJed Brown */
439371c9d4SSatish Balay typedef union
449371c9d4SSatish Balay {
45e5c89e4eSSatish Balay   TRSPACE sp;
4625b53cc9SJed Brown   char    v[HEADER_BYTES];
47e5c89e4eSSatish Balay } TrSPACE;
48e5c89e4eSSatish Balay 
49e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50
50e5c89e4eSSatish Balay static size_t    TRallocated           = 0;
51e5c89e4eSSatish Balay static int       TRfrags               = 0;
52f0ba7cfcSLisandro Dalcin static TRSPACE  *TRhead                = NULL;
53e5c89e4eSSatish Balay static int       TRid                  = 0;
54ace3abfcSBarry Smith static PetscBool TRdebugLevel          = PETSC_FALSE;
552d4ee042Sprj- static PetscBool TRdebugIinitializenan = PETSC_FALSE;
56608c71bfSMatthew G. Knepley static PetscBool TRrequestedSize       = PETSC_FALSE;
57e5c89e4eSSatish Balay static size_t    TRMaxMem              = 0;
58e3ed9ee7SBarry Smith static int       NumTRMaxMems          = 0;
59e3ed9ee7SBarry Smith static size_t    TRMaxMems[MAXTRMAXMEMS];
60e3ed9ee7SBarry Smith static int       TRMaxMemsEvents[MAXTRMAXMEMS];
61e5c89e4eSSatish Balay /*
6292f119d6SBarry Smith       Arrays to log information on mallocs for PetscMallocView()
63e5c89e4eSSatish Balay */
64f0ba7cfcSLisandro Dalcin static int          PetscLogMallocMax       = 10000;
65f0ba7cfcSLisandro Dalcin static int          PetscLogMalloc          = -1;
66574034a9SJed Brown static size_t       PetscLogMallocThreshold = 0;
67e5c89e4eSSatish Balay static size_t      *PetscLogMallocLength;
68efca3c55SSatish Balay static const char **PetscLogMallocFile, **PetscLogMallocFunction;
69608c71bfSMatthew G. Knepley static int          PetscLogMallocTrace          = -1;
70608c71bfSMatthew G. Knepley static size_t       PetscLogMallocTraceThreshold = 0;
71608c71bfSMatthew G. Knepley static PetscViewer  PetscLogMallocTraceViewer    = NULL;
72b022a5c1SBarry Smith 
73e5c89e4eSSatish Balay /*@C
74811af0c4SBarry Smith    PetscMallocValidate - Test the memory for corruption.  This can be called at any time between `PetscInitialize()` and `PetscFinalize()`
75e5c89e4eSSatish Balay 
7692f119d6SBarry Smith    Input Parameters:
77e5c89e4eSSatish Balay +  line - line number where call originated.
78e5c89e4eSSatish Balay .  function - name of function calling
79efca3c55SSatish Balay -  file - file where function is
80e5c89e4eSSatish Balay 
81e5c89e4eSSatish Balay    Return value:
82e5c89e4eSSatish Balay    The number of errors detected.
83e5c89e4eSSatish Balay 
84811af0c4SBarry Smith    Options Database Keys:.
8592f119d6SBarry Smith +  -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0
8692f119d6SBarry Smith -  -malloc_debug - turns this feature on anytime
8792f119d6SBarry Smith 
88e5c89e4eSSatish Balay    Output Effect:
89e5c89e4eSSatish Balay    Error messages are written to stdout.
90e5c89e4eSSatish Balay 
91e5c89e4eSSatish Balay    Level: advanced
92e5c89e4eSSatish Balay 
93e5c89e4eSSatish Balay    Notes:
94811af0c4SBarry 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 
96811af0c4SBarry Smith     You should generally use `CHKMEMQ` as a short cut for calling this  routine.
97e5c89e4eSSatish Balay 
98e5c89e4eSSatish Balay    No output is generated if there are no problems detected.
99e5c89e4eSSatish Balay 
100*20f4b53cSBarry Smith    Fortran Note:
101*20f4b53cSBarry Smith     The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
102*20f4b53cSBarry Smith 
10392f119d6SBarry Smith    Developers Note:
104*20f4b53cSBarry Smith      Uses the flg `TRdebugLevel` (set as the first argument to `PetscMallocSetDebug()`) to determine if it should run
10592f119d6SBarry Smith 
106db781477SPatrick Sanan .seealso: `CHKMEMQ`
107e5c89e4eSSatish Balay @*/
108d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
109d71ae5a4SJacob Faibussowitsch {
1106c093d5bSvictor   TRSPACE      *head, *lasthead;
111e5c89e4eSSatish Balay   char         *a;
1120700a824SBarry Smith   PetscClassId *nend;
113e5c89e4eSSatish Balay 
1143ba16761SJacob Faibussowitsch   if (!TRdebugLevel) return PETSC_SUCCESS;
1159371c9d4SSatish Balay   head     = TRhead;
1169371c9d4SSatish Balay   lasthead = NULL;
1172cba8197SMatthew G. Knepley   if (head && head->prev) {
1183ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1193ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev));
1204ed0ab5bSBarry Smith     return PETSC_ERR_MEMC;
1212cba8197SMatthew G. Knepley   }
122e5c89e4eSSatish Balay   while (head) {
1230700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
1243ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1253ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head));
1263ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"));
127e269983cSBarry Smith       if (lasthead) {
128e269983cSBarry Smith         a = (char *)(((TrSPACE *)head) + 1);
1293ba16761SJacob 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));
130e269983cSBarry Smith       }
131e269983cSBarry Smith       abort();
1324ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
133e5c89e4eSSatish Balay     }
134e5c89e4eSSatish Balay     a    = (char *)(((TrSPACE *)head) + 1);
1350700a824SBarry Smith     nend = (PetscClassId *)(a + head->size);
1360700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
1373ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
138e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
1393ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a));
1404ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
141e5c89e4eSSatish Balay       } else {
1423ba16761SJacob 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));
1433ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1444ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
145e5c89e4eSSatish Balay       }
146e5c89e4eSSatish Balay     }
1472cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
1483ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line));
1493ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead));
1503ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno));
1513ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
1524ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
1532cba8197SMatthew G. Knepley     }
1546c093d5bSvictor     lasthead = head;
155e5c89e4eSSatish Balay     head     = head->next;
156e5c89e4eSSatish Balay   }
1573ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
158e5c89e4eSSatish Balay }
159e5c89e4eSSatish Balay 
160e5c89e4eSSatish Balay /*
161e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
162e5c89e4eSSatish Balay 
163e5c89e4eSSatish Balay     Input Parameters:
164e5c89e4eSSatish Balay +   a   - number of bytes to allocate
165e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
166efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
167e5c89e4eSSatish Balay 
168e5c89e4eSSatish Balay     Returns:
16992f119d6SBarry Smith     double aligned pointer to requested storage, or null if not  available.
170e5c89e4eSSatish Balay  */
171d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
172d71ae5a4SJacob Faibussowitsch {
173e5c89e4eSSatish Balay   TRSPACE *head;
174e5c89e4eSSatish Balay   char    *inew;
175e5c89e4eSSatish Balay   size_t   nsize;
176e5c89e4eSSatish Balay 
177e5c89e4eSSatish Balay   PetscFunctionBegin;
178f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
1799371c9d4SSatish Balay   if (!a) {
1809371c9d4SSatish Balay     *result = NULL;
1813ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1829371c9d4SSatish Balay   }
183f0ba7cfcSLisandro Dalcin 
18411cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
185e5c89e4eSSatish Balay 
18625b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
1879566063dSJacob Faibussowitsch   PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
188e3ed9ee7SBarry Smith 
189e5c89e4eSSatish Balay   head = (TRSPACE *)inew;
190e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
191e5c89e4eSSatish Balay 
192e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
193e5c89e4eSSatish Balay   head->next   = TRhead;
194e5c89e4eSSatish Balay   TRhead       = head;
195f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
196e5c89e4eSSatish Balay   head->size   = nsize;
197608c71bfSMatthew G. Knepley   head->rsize  = a;
198e269983cSBarry Smith   head->id     = TRid++;
199e5c89e4eSSatish Balay   head->lineno = lineno;
200e5c89e4eSSatish Balay 
201e5c89e4eSSatish Balay   head->filename                  = filename;
202e5c89e4eSSatish Balay   head->functionname              = function;
2030700a824SBarry Smith   head->classid                   = CLASSID_VALUE;
2040700a824SBarry Smith   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
205e5c89e4eSSatish Balay 
206608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
207a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
208e3ed9ee7SBarry Smith   if (PetscLogMemory) {
209e3ed9ee7SBarry Smith     PetscInt i;
210e3ed9ee7SBarry Smith     for (i = 0; i < NumTRMaxMems; i++) {
211e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
212e3ed9ee7SBarry Smith     }
213e3ed9ee7SBarry Smith   }
214e5c89e4eSSatish Balay   TRfrags++;
215e5c89e4eSSatish Balay 
216dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
2179566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
2182c9581d2SBarry Smith   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2192c9581d2SBarry Smith   head->stack.line[head->stack.currentsize - 2] = lineno;
22092f119d6SBarry Smith   #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2212d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
22292f119d6SBarry Smith     size_t     i, n = a / sizeof(PetscReal);
22392f119d6SBarry Smith     PetscReal *s = (PetscReal *)inew;
22492f119d6SBarry Smith       /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
22592f119d6SBarry Smith     #if defined(PETSC_USE_REAL_SINGLE)
226df282883SBarry Smith     int nas = 0x7F800002;
22792f119d6SBarry Smith     #else
22892f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22992f119d6SBarry Smith     #endif
230ad540459SPierre Jolivet     for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
23192f119d6SBarry Smith   }
23292f119d6SBarry Smith   #endif
233e5c89e4eSSatish Balay #endif
234e5c89e4eSSatish Balay 
235e5c89e4eSSatish Balay   /*
23692f119d6SBarry Smith          Allow logging of all mallocs made.
23792f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
238e5c89e4eSSatish Balay   */
239574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
240e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
241e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
24228b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
243a297a907SKarl Rupp 
244a2ea699eSBarry Smith       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
24528b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
246a297a907SKarl Rupp 
247a2ea699eSBarry Smith       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
24828b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
249e5c89e4eSSatish Balay     }
250e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
251e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
252e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
253e5c89e4eSSatish Balay   }
25448a46eb9SPierre Jolivet   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
255e5c89e4eSSatish Balay   *result = (void *)inew;
2563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
257e5c89e4eSSatish Balay }
258e5c89e4eSSatish Balay 
259e5c89e4eSSatish Balay /*
260e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
261e5c89e4eSSatish Balay 
262e5c89e4eSSatish Balay    Input Parameters:
263e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
264e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
265608c71bfSMatthew G. Knepley .   filename  - file name where used.  Use __FILE__ for this
266e5c89e4eSSatish Balay  */
267d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
268d71ae5a4SJacob Faibussowitsch {
269e5c89e4eSSatish Balay   char         *a = (char *)aa;
270e5c89e4eSSatish Balay   TRSPACE      *head;
271e5c89e4eSSatish Balay   char         *ahead;
272608c71bfSMatthew G. Knepley   size_t        asize;
2730700a824SBarry Smith   PetscClassId *nend;
274e5c89e4eSSatish Balay 
275e5c89e4eSSatish Balay   PetscFunctionBegin;
276e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
2773ba16761SJacob Faibussowitsch   if (!a) PetscFunctionReturn(PETSC_SUCCESS);
278e5c89e4eSSatish Balay 
2799566063dSJacob Faibussowitsch   PetscCall(PetscMallocValidate(lineno, function, filename));
280e5c89e4eSSatish Balay 
281e5c89e4eSSatish Balay   ahead = a;
282e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
283e5c89e4eSSatish Balay   head  = (TRSPACE *)a;
284e5c89e4eSSatish Balay 
2850700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
2863ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2873ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
288e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
289e5c89e4eSSatish Balay   }
2900700a824SBarry Smith   nend = (PetscClassId *)(ahead + head->size);
2910700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
292e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
2933ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
2943ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
295e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
2963ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
297e5c89e4eSSatish Balay       } else {
2983ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
299e5c89e4eSSatish Balay       }
300e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
301e5c89e4eSSatish Balay     } else {
302e5c89e4eSSatish Balay       /* Damaged tail */
3033ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno));
3043ba16761SJacob 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));
3053ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
306e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
307e5c89e4eSSatish Balay     }
308e5c89e4eSSatish Balay   }
309608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
3109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
311608c71bfSMatthew G. Knepley   }
312e5c89e4eSSatish Balay   /* Mark the location freed */
313e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
314e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
315608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
316608c71bfSMatthew G. Knepley     head->lineno       = lineno;
317608c71bfSMatthew G. Knepley     head->filename     = filename;
318e5c89e4eSSatish Balay     head->functionname = function;
319e5c89e4eSSatish Balay   } else {
320e5c89e4eSSatish Balay     head->lineno = -head->lineno;
321e5c89e4eSSatish Balay   }
322608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
32308401ef6SPierre Jolivet   PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
324608c71bfSMatthew G. Knepley   TRallocated -= asize;
325e5c89e4eSSatish Balay   TRfrags--;
326e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
327e5c89e4eSSatish Balay   else TRhead = head->next;
328e5c89e4eSSatish Balay 
329e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
3309566063dSJacob Faibussowitsch   PetscCall(PetscFreeAlign(a, lineno, function, filename));
3313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
332e5c89e4eSSatish Balay }
333e5c89e4eSSatish Balay 
3343221ece2SMatthew G. Knepley /*
3353221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3363221ece2SMatthew G. Knepley 
3373221ece2SMatthew G. Knepley   Input Parameters:
3383221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3393221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3403221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
34192f119d6SBarry Smith - result - original memory
3423221ece2SMatthew G. Knepley 
3433221ece2SMatthew G. Knepley   Output Parameter:
3443221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3453221ece2SMatthew G. Knepley 
3463221ece2SMatthew G. Knepley   Level: developer
3473221ece2SMatthew G. Knepley 
348db781477SPatrick Sanan .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()`
3493221ece2SMatthew G. Knepley */
350d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
351d71ae5a4SJacob Faibussowitsch {
3523221ece2SMatthew G. Knepley   char         *a = (char *)*result;
3533221ece2SMatthew G. Knepley   TRSPACE      *head;
3543221ece2SMatthew G. Knepley   char         *ahead, *inew;
3553221ece2SMatthew G. Knepley   PetscClassId *nend;
3563221ece2SMatthew G. Knepley   size_t        nsize;
3573221ece2SMatthew G. Knepley 
3583221ece2SMatthew G. Knepley   PetscFunctionBegin;
35992f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
360c22f1541SToby Isaac   if (!len) {
3619566063dSJacob Faibussowitsch     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
362c22f1541SToby Isaac     *result = NULL;
3633ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
364c22f1541SToby Isaac   }
365da81f932SPierre Jolivet   /* If the original space was NULL just use the regular malloc() */
366f590eff4SLisandro Dalcin   if (!*result) {
3679566063dSJacob Faibussowitsch     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
3683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
369f590eff4SLisandro Dalcin   }
3703221ece2SMatthew G. Knepley 
37111cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
3723221ece2SMatthew G. Knepley 
3733221ece2SMatthew G. Knepley   ahead = a;
3743221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3753221ece2SMatthew G. Knepley   head  = (TRSPACE *)a;
3763221ece2SMatthew G. Knepley   inew  = a;
3773221ece2SMatthew G. Knepley 
3783221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3793ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3803ba16761SJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a));
3813221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
3823221ece2SMatthew G. Knepley   }
3833221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3843221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3853221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3863ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3873ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)));
3883221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3893ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3903221ece2SMatthew G. Knepley       } else {
3913ba16761SJacob Faibussowitsch         PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno));
3923221ece2SMatthew G. Knepley       }
3933221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
3943221ece2SMatthew G. Knepley     } else {
3953221ece2SMatthew G. Knepley       /* Damaged tail */
3963ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno));
3973ba16761SJacob 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));
3983ba16761SJacob Faibussowitsch       PetscCall((*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno));
3993221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
4003221ece2SMatthew G. Knepley     }
4013221ece2SMatthew G. Knepley   }
4023221ece2SMatthew G. Knepley 
40392f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
404608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
4053221ece2SMatthew G. Knepley   TRfrags--;
4063221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4073221ece2SMatthew G. Knepley   else TRhead = head->next;
4083221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4093221ece2SMatthew G. Knepley 
4103221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
4119566063dSJacob Faibussowitsch   PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
4123221ece2SMatthew G. Knepley 
4133221ece2SMatthew G. Knepley   head = (TRSPACE *)inew;
4143221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4153221ece2SMatthew G. Knepley 
4163221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4173221ece2SMatthew G. Knepley   head->next   = TRhead;
4183221ece2SMatthew G. Knepley   TRhead       = head;
4193221ece2SMatthew G. Knepley   head->prev   = NULL;
4203221ece2SMatthew G. Knepley   head->size   = nsize;
421608c71bfSMatthew G. Knepley   head->rsize  = len;
422e269983cSBarry Smith   head->id     = TRid++;
4233221ece2SMatthew G. Knepley   head->lineno = lineno;
4243221ece2SMatthew G. Knepley 
4253221ece2SMatthew G. Knepley   head->filename                  = filename;
4263221ece2SMatthew G. Knepley   head->functionname              = function;
4273221ece2SMatthew G. Knepley   head->classid                   = CLASSID_VALUE;
4283221ece2SMatthew G. Knepley   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
4293221ece2SMatthew G. Knepley 
430608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4313221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
432e3ed9ee7SBarry Smith   if (PetscLogMemory) {
433e3ed9ee7SBarry Smith     PetscInt i;
434e3ed9ee7SBarry Smith     for (i = 0; i < NumTRMaxMems; i++) {
435e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
436e3ed9ee7SBarry Smith     }
437e3ed9ee7SBarry Smith   }
4383221ece2SMatthew G. Knepley   TRfrags++;
4393221ece2SMatthew G. Knepley 
440dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
4419566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
4423221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4433221ece2SMatthew G. Knepley   head->stack.line[head->stack.currentsize - 2] = lineno;
4443221ece2SMatthew G. Knepley #endif
4453221ece2SMatthew G. Knepley 
4463221ece2SMatthew G. Knepley   /*
44792f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
44892f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4493221ece2SMatthew G. Knepley   */
4503221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4513221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4523221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
45328b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4543221ece2SMatthew G. Knepley 
4553221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
45628b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4573221ece2SMatthew G. Knepley 
4583221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
45928b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4603221ece2SMatthew G. Knepley     }
4613221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4623221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4633221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4643221ece2SMatthew G. Knepley   }
4653221ece2SMatthew G. Knepley   *result = (void *)inew;
4663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4673221ece2SMatthew G. Knepley }
4683221ece2SMatthew G. Knepley 
469fe7fb379SMatthew Knepley /*@C
47092f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
471e5c89e4eSSatish Balay 
472c3339decSBarry Smith     Collective
473e5c89e4eSSatish Balay 
474d8d19677SJose E. Roman     Input Parameters:
475e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
476e5c89e4eSSatish Balay -    message - string printed before values
477e5c89e4eSSatish Balay 
478811af0c4SBarry Smith     Options Database Keys:
47992f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
480811af0c4SBarry Smith .    -log_view_memory - print memory usage per event
4810841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4820841954dSBarry Smith 
483e5c89e4eSSatish Balay     Level: intermediate
484e5c89e4eSSatish Balay 
485db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`
486e5c89e4eSSatish Balay  @*/
487d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
488d71ae5a4SJacob Faibussowitsch {
4890841954dSBarry Smith   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax;
4900841954dSBarry Smith   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax;
491e5c89e4eSSatish Balay   MPI_Comm       comm;
492e5c89e4eSSatish Balay 
493e5c89e4eSSatish Balay   PetscFunctionBegin;
494e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4959566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&allocated));
4969566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4979566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&resident));
4989566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
499e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
5019566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
502e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
5039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5069566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5149566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
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));
519e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5249566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5259566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5269566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
528e5c89e4eSSatish Balay   } else if (resident && allocated) {
5299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5379566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
538e5c89e4eSSatish Balay   } else if (allocated) {
5399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5419566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
545e5c89e4eSSatish Balay   } else {
5469566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
547e5c89e4eSSatish Balay   }
5489566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
5493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
550e5c89e4eSSatish Balay }
551e5c89e4eSSatish Balay 
55246eb3923SBarry Smith /*@
553811af0c4SBarry Smith     PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay     Not Collective
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay     Output Parameters:
558e5c89e4eSSatish Balay .   space - number of bytes currently allocated
559e5c89e4eSSatish Balay 
560e5c89e4eSSatish Balay     Level: intermediate
561e5c89e4eSSatish Balay 
562db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
563db781477SPatrick Sanan           `PetscMemoryGetMaximumUsage()`
564e5c89e4eSSatish Balay  @*/
565d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
566d71ae5a4SJacob Faibussowitsch {
567e5c89e4eSSatish Balay   PetscFunctionBegin;
568e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRallocated;
5693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
570e5c89e4eSSatish Balay }
571e5c89e4eSSatish Balay 
572dc37d89fSBarry Smith /*@
573811af0c4SBarry Smith     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
574811af0c4SBarry Smith         during this run, the high water mark.
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay     Not Collective
577e5c89e4eSSatish Balay 
578e5c89e4eSSatish Balay     Output Parameters:
579e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
580e5c89e4eSSatish Balay 
581e5c89e4eSSatish Balay     Level: intermediate
582e5c89e4eSSatish Balay 
583db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
584db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
585e5c89e4eSSatish Balay  @*/
586d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
587d71ae5a4SJacob Faibussowitsch {
588e5c89e4eSSatish Balay   PetscFunctionBegin;
589e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRMaxMem;
5903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
591e5c89e4eSSatish Balay }
592e5c89e4eSSatish Balay 
593e3ed9ee7SBarry Smith /*@
594e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
595e3ed9ee7SBarry Smith 
596e3ed9ee7SBarry Smith     Not Collective
597e3ed9ee7SBarry Smith 
598e3ed9ee7SBarry Smith     Input Parameter:
599e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
600e3ed9ee7SBarry Smith 
601e3ed9ee7SBarry Smith     Level: developer
602e3ed9ee7SBarry Smith 
603db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
604db781477SPatrick Sanan           `PetscMallocPopMaximumUsage()`
605e3ed9ee7SBarry Smith  @*/
606d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event)
607d71ae5a4SJacob Faibussowitsch {
608e3ed9ee7SBarry Smith   PetscFunctionBegin;
6093ba16761SJacob Faibussowitsch   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
610e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
611e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
6123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
613e3ed9ee7SBarry Smith }
614e3ed9ee7SBarry Smith 
615e3ed9ee7SBarry Smith /*@
616e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
617e3ed9ee7SBarry Smith 
618e3ed9ee7SBarry Smith     Not Collective
619e3ed9ee7SBarry Smith 
620e3ed9ee7SBarry Smith     Input Parameter:
621e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
622e3ed9ee7SBarry Smith 
623e3ed9ee7SBarry Smith     Output Parameter:
624e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
625e3ed9ee7SBarry Smith 
626e3ed9ee7SBarry Smith     Level: developer
627e3ed9ee7SBarry Smith 
628db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
629db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
630e3ed9ee7SBarry Smith  @*/
631d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
632d71ae5a4SJacob Faibussowitsch {
633e3ed9ee7SBarry Smith   PetscFunctionBegin;
634e3ed9ee7SBarry Smith   *mu = 0;
6353ba16761SJacob Faibussowitsch   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(PETSC_SUCCESS);
63608401ef6SPierre Jolivet   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
637e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
6383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
639e3ed9ee7SBarry Smith }
640e3ed9ee7SBarry Smith 
641a64a8e02SBarry Smith /*@C
642811af0c4SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
643a64a8e02SBarry Smith 
644811af0c4SBarry Smith    Collective on `PETSC_COMM_WORLD`
645a64a8e02SBarry Smith 
646a64a8e02SBarry Smith    Input Parameter:
647a64a8e02SBarry Smith .    ptr - the memory location
648a64a8e02SBarry Smith 
649fd292e60Sprj-    Output Parameter:
650a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
651a64a8e02SBarry Smith 
652a64a8e02SBarry Smith    Level: intermediate
653a64a8e02SBarry Smith 
654db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`
655a64a8e02SBarry Smith @*/
656d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
657d71ae5a4SJacob Faibussowitsch {
658dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
659a64a8e02SBarry Smith   TRSPACE *head;
660a64a8e02SBarry Smith 
661a64a8e02SBarry Smith   PetscFunctionBegin;
662a64a8e02SBarry Smith   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
663a64a8e02SBarry Smith   *stack = &head->stack;
6643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66576386721SLisandro Dalcin #else
666f0ba7cfcSLisandro Dalcin   *stack = NULL;
6673ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
668a64a8e02SBarry Smith #endif
669dfb7d7afSStefano Zampini }
670a64a8e02SBarry Smith 
671e5c89e4eSSatish Balay /*@C
67292f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
673e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
674e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
675e5c89e4eSSatish Balay    allocated.
676e5c89e4eSSatish Balay 
67792f119d6SBarry Smith    Not Collective
678e5c89e4eSSatish Balay 
679e5c89e4eSSatish Balay    Input Parameter:
680e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
681e5c89e4eSSatish Balay 
682e5c89e4eSSatish Balay    Options Database Key:
683811af0c4SBarry Smith .  -malloc_dump <optional filename> - Dumps unfreed memory during call to `PetscFinalize()`
684e5c89e4eSSatish Balay 
685e5c89e4eSSatish Balay    Level: intermediate
686e5c89e4eSSatish Balay 
68795452b02SPatrick Sanan    Notes:
688811af0c4SBarry Smith      Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
689e5c89e4eSSatish Balay 
690811af0c4SBarry Smith      When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
69192f119d6SBarry Smith 
692811af0c4SBarry Smith      `PetscMallocView()` prints a list of all memory ever allocated
69392f119d6SBarry Smith 
694*20f4b53cSBarry Smith    Fortran Notes:
695*20f4b53cSBarry Smith    The calling sequence in Fortran is PetscMallocDump(integer ierr)
696*20f4b53cSBarry Smith 
697*20f4b53cSBarry Smith    The `fp` defaults to stdout.
698*20f4b53cSBarry Smith 
699db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`
700e5c89e4eSSatish Balay @*/
701d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp)
702d71ae5a4SJacob Faibussowitsch {
703e5c89e4eSSatish Balay   TRSPACE    *head;
704e3ed9ee7SBarry Smith   size_t      libAlloc = 0;
705e5c89e4eSSatish Balay   PetscMPIInt rank;
706e5c89e4eSSatish Balay 
707e5c89e4eSSatish Balay   PetscFunctionBegin;
7089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
709da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
710e5c89e4eSSatish Balay   head = TRhead;
711e5c89e4eSSatish Balay   while (head) {
712608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7135486ca60SMatthew G. Knepley     head = head->next;
7145486ca60SMatthew G. Knepley   }
7155486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7165486ca60SMatthew G. Knepley   head = TRhead;
7175486ca60SMatthew G. Knepley   while (head) {
7185486ca60SMatthew G. Knepley     PetscBool isLib;
7195486ca60SMatthew G. Knepley 
7209566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7215486ca60SMatthew G. Knepley     if (!isLib) {
722ccd65f63SJunchao Zhang       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
723dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
7249566063dSJacob Faibussowitsch       PetscCall(PetscStackPrint(&head->stack, fp));
725e5c89e4eSSatish Balay #endif
7265486ca60SMatthew G. Knepley     }
727e5c89e4eSSatish Balay     head = head->next;
728e5c89e4eSSatish Balay   }
7293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
730e5c89e4eSSatish Balay }
731e5c89e4eSSatish Balay 
732dc37d89fSBarry Smith /*@
733811af0c4SBarry Smith     PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
734574034a9SJed Brown 
735574034a9SJed Brown     Not Collective
736574034a9SJed Brown 
7374165533cSJose E. Roman     Input Parameter:
738811af0c4SBarry Smith .   logmin - minimum allocation size to log, or `PETSC_DEFAULT`
739574034a9SJed Brown 
740574034a9SJed Brown     Options Database Key:
741811af0c4SBarry Smith +  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
7428b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7438b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
744574034a9SJed Brown 
745574034a9SJed Brown     Level: advanced
746574034a9SJed Brown 
747811af0c4SBarry Smith     Notes:
748811af0c4SBarry Smith     Must be called after `PetscMallocSetDebug()`
74992f119d6SBarry Smith 
750811af0c4SBarry Smith     Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
75192f119d6SBarry Smith 
752db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`
753574034a9SJed Brown @*/
754d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
755d71ae5a4SJacob Faibussowitsch {
756574034a9SJed Brown   PetscFunctionBegin;
75792f119d6SBarry Smith   PetscLogMalloc = 0;
7589566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
759574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
760574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
7613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
762574034a9SJed Brown }
763574034a9SJed Brown 
764dc37d89fSBarry Smith /*@
765811af0c4SBarry Smith     PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
76618a2528dSJed Brown 
76718a2528dSJed Brown     Not Collective
76818a2528dSJed Brown 
7694165533cSJose E. Roman     Output Parameter
770811af0c4SBarry Smith .   logging - `PETSC_TRUE` if logging is active
77118a2528dSJed Brown 
77218a2528dSJed Brown     Options Database Key:
773811af0c4SBarry Smith .  -malloc_view <optional filename> - Activates `PetscMallocView()`
77418a2528dSJed Brown 
77518a2528dSJed Brown     Level: advanced
77618a2528dSJed Brown 
777db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`
77818a2528dSJed Brown @*/
779d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging)
780d71ae5a4SJacob Faibussowitsch {
78118a2528dSJed Brown   PetscFunctionBegin;
78218a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
7833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78418a2528dSJed Brown }
78518a2528dSJed Brown 
786608c71bfSMatthew G. Knepley /*@
787811af0c4SBarry Smith   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`
788608c71bfSMatthew G. Knepley 
789608c71bfSMatthew G. Knepley   Not Collective
790608c71bfSMatthew G. Knepley 
7914165533cSJose E. Roman   Input Parameters:
792608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout
793608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
794608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
795608c71bfSMatthew G. Knepley 
796608c71bfSMatthew G. Knepley   Note:
797608c71bfSMatthew G. Knepley   The viewer should not be collective.
798608c71bfSMatthew G. Knepley 
799608c71bfSMatthew G. Knepley   Level: advanced
800608c71bfSMatthew G. Knepley 
801db781477SPatrick Sanan .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
802608c71bfSMatthew G. Knepley @*/
803d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
804d71ae5a4SJacob Faibussowitsch {
805608c71bfSMatthew G. Knepley   PetscFunctionBegin;
8069371c9d4SSatish Balay   if (!active) {
8079371c9d4SSatish Balay     PetscLogMallocTrace = -1;
8083ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8099371c9d4SSatish Balay   }
810608c71bfSMatthew G. Knepley   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
811608c71bfSMatthew G. Knepley   PetscLogMallocTrace       = 0;
8129566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
813608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
814608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t)logmin;
8153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
816608c71bfSMatthew G. Knepley }
817608c71bfSMatthew G. Knepley 
818608c71bfSMatthew G. Knepley /*@
819811af0c4SBarry Smith   PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
820608c71bfSMatthew G. Knepley 
821608c71bfSMatthew G. Knepley   Not Collective
822608c71bfSMatthew G. Knepley 
8234165533cSJose E. Roman   Output Parameter:
824811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
825608c71bfSMatthew G. Knepley 
826608c71bfSMatthew G. Knepley   Options Database Key:
827608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView()
828608c71bfSMatthew G. Knepley 
829608c71bfSMatthew G. Knepley   Level: advanced
830608c71bfSMatthew G. Knepley 
831db781477SPatrick Sanan .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
832608c71bfSMatthew G. Knepley @*/
833d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
834d71ae5a4SJacob Faibussowitsch {
835608c71bfSMatthew G. Knepley   PetscFunctionBegin;
836608c71bfSMatthew G. Knepley   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
8373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
838608c71bfSMatthew G. Knepley }
839608c71bfSMatthew G. Knepley 
840e5c89e4eSSatish Balay /*@C
841811af0c4SBarry Smith     PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls
842811af0c4SBarry Smith        `PetscMemoryGetMaximumUsage()`
843e5c89e4eSSatish Balay 
84492f119d6SBarry Smith     Not Collective
845e5c89e4eSSatish Balay 
846e5c89e4eSSatish Balay     Input Parameter:
8470298fd71SBarry Smith .   fp - file pointer; or NULL
848e5c89e4eSSatish Balay 
849e5c89e4eSSatish Balay     Options Database Key:
850811af0c4SBarry Smith .  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
851e5c89e4eSSatish Balay 
852e5c89e4eSSatish Balay     Level: advanced
853e5c89e4eSSatish Balay 
85492f119d6SBarry Smith    Notes:
855811af0c4SBarry Smith      `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated
85692f119d6SBarry Smith 
857811af0c4SBarry Smith      `PetscMemoryView()` gives a brief summary of current memory usage
85892f119d6SBarry Smith 
859*20f4b53cSBarry Smith    Fortran Notes:
860*20f4b53cSBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
861*20f4b53cSBarry Smith 
862*20f4b53cSBarry Smith    The `fp` defaults to stdout.
863*20f4b53cSBarry Smith 
864db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`
865e5c89e4eSSatish Balay @*/
866d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp)
867d71ae5a4SJacob Faibussowitsch {
86892f119d6SBarry Smith   PetscInt       i, j, n, *perm;
869e5c89e4eSSatish Balay   size_t        *shortlength;
870c69effb2SJacob Faibussowitsch   int           *shortcount;
87192f119d6SBarry Smith   PetscMPIInt    rank;
872ace3abfcSBarry Smith   PetscBool      match;
873e5c89e4eSSatish Balay   const char   **shortfunction;
874e5c89e4eSSatish Balay   PetscLogDouble rss;
875e5c89e4eSSatish Balay 
876e5c89e4eSSatish Balay   PetscFunctionBegin;
8779566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
878c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
879f56c2debSBarry Smith 
88008401ef6SPierre Jolivet   PetscCheck(PetscLogMalloc >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscMallocView() called without call to PetscMallocViewSet() this is often due to\n                      setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
881768aa557SSatish Balay 
882da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
8839566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&rss));
884e5c89e4eSSatish Balay   if (rss) {
88592f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
886e5c89e4eSSatish Balay   } else {
88792f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
888e5c89e4eSSatish Balay   }
889b13f2904SStefano Zampini   if (PetscLogMalloc > 0) {
8909371c9d4SSatish Balay     shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
8919371c9d4SSatish Balay     PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8929371c9d4SSatish Balay     shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
8939371c9d4SSatish Balay     PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8949371c9d4SSatish Balay     shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
8959371c9d4SSatish Balay     PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
89697b9d747SJed Brown     for (i = 0, n = 0; i < PetscLogMalloc; i++) {
897e5c89e4eSSatish Balay       for (j = 0; j < n; j++) {
8989566063dSJacob Faibussowitsch         PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
899e5c89e4eSSatish Balay         if (match) {
900e5c89e4eSSatish Balay           shortlength[j] += PetscLogMallocLength[i];
90159ffdab8SBarry Smith           shortcount[j]++;
902e5c89e4eSSatish Balay           goto foundit;
903e5c89e4eSSatish Balay         }
904e5c89e4eSSatish Balay       }
905e5c89e4eSSatish Balay       shortfunction[n] = PetscLogMallocFunction[i];
906e5c89e4eSSatish Balay       shortlength[n]   = PetscLogMallocLength[i];
90759ffdab8SBarry Smith       shortcount[n]    = 1;
908e5c89e4eSSatish Balay       n++;
909e5c89e4eSSatish Balay     foundit:;
910e5c89e4eSSatish Balay     }
911e5c89e4eSSatish Balay 
9129371c9d4SSatish Balay     perm = (PetscInt *)malloc(n * sizeof(PetscInt));
9139371c9d4SSatish Balay     PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
914e5c89e4eSSatish Balay     for (i = 0; i < n; i++) perm[i] = i;
9159566063dSJacob Faibussowitsch     PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
916e5c89e4eSSatish Balay 
91792f119d6SBarry Smith     (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
918ad540459SPierre Jolivet     for (i = 0; i < n; i++) (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]);
919e5c89e4eSSatish Balay     free(perm);
920e5c89e4eSSatish Balay     free(shortlength);
92159ffdab8SBarry Smith     free(shortcount);
922e5c89e4eSSatish Balay     free((char **)shortfunction);
923b13f2904SStefano Zampini   }
924c69effb2SJacob Faibussowitsch   PetscCall(PetscFFlush(fp));
9253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
926e5c89e4eSSatish Balay }
927e5c89e4eSSatish Balay 
928e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
929e5c89e4eSSatish Balay 
930dc37d89fSBarry Smith /*@
93192f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
932e5c89e4eSSatish Balay 
933e5c89e4eSSatish Balay     Not Collective
934e5c89e4eSSatish Balay 
935d8d19677SJose E. Roman     Input Parameters:
936811af0c4SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
9372d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
938e5c89e4eSSatish Balay 
939811af0c4SBarry Smith     Options Database Keys:
94079dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
94192f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
94279dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
94392f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
94479dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
94579dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
946e5c89e4eSSatish Balay 
94792f119d6SBarry Smith    Level: developer
94892f119d6SBarry Smith 
949811af0c4SBarry Smith     Note:
950811af0c4SBarry Smith     This is called in `PetscInitialize()` and should not be called elsewhere
95192f119d6SBarry Smith 
952db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`
953e5c89e4eSSatish Balay @*/
954d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
955d71ae5a4SJacob Faibussowitsch {
956e5c89e4eSSatish Balay   PetscFunctionBegin;
95708401ef6SPierre 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()");
9589566063dSJacob Faibussowitsch   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
95992f119d6SBarry Smith 
96092f119d6SBarry Smith   TRallocated           = 0;
96192f119d6SBarry Smith   TRfrags               = 0;
96292f119d6SBarry Smith   TRhead                = NULL;
96392f119d6SBarry Smith   TRid                  = 0;
96492f119d6SBarry Smith   TRdebugLevel          = eachcall;
96592f119d6SBarry Smith   TRMaxMem              = 0;
96692f119d6SBarry Smith   PetscLogMallocMax     = 10000;
96792f119d6SBarry Smith   PetscLogMalloc        = -1;
9682d4ee042Sprj-   TRdebugIinitializenan = initializenan;
9693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
970e5c89e4eSSatish Balay }
9710acecf5bSBarry Smith 
972dc37d89fSBarry Smith /*@
97392f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9740acecf5bSBarry Smith 
9750acecf5bSBarry Smith     Not Collective
9760acecf5bSBarry Smith 
97792f119d6SBarry Smith     Output Parameters:
97892f119d6SBarry Smith +    basic - doing basic debugging
979811af0c4SBarry Smith .    eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()`
98079dccf82SBarry Smith -    initializenan - initializes memory with NaN
9810acecf5bSBarry Smith 
9820acecf5bSBarry Smith    Level: intermediate
9830acecf5bSBarry Smith 
984811af0c4SBarry Smith    Note:
98579dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
9860acecf5bSBarry Smith 
987db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`
9880acecf5bSBarry Smith @*/
989d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
990d71ae5a4SJacob Faibussowitsch {
9910acecf5bSBarry Smith   PetscFunctionBegin;
99279dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
99379dccf82SBarry Smith   if (eachcall) *eachcall = TRdebugLevel;
9942d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9960acecf5bSBarry Smith }
997608c71bfSMatthew G. Knepley 
998608c71bfSMatthew G. Knepley /*@
999608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
1000608c71bfSMatthew G. Knepley 
1001608c71bfSMatthew G. Knepley   Not Collective
1002608c71bfSMatthew G. Knepley 
1003608c71bfSMatthew G. Knepley   Input Parameter:
1004811af0c4SBarry Smith . flg - `PETSC_TRUE` to log the requested memory size
1005608c71bfSMatthew G. Knepley 
1006811af0c4SBarry Smith   Options Database Key:
1007608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1008608c71bfSMatthew G. Knepley 
1009608c71bfSMatthew G. Knepley   Level: developer
1010608c71bfSMatthew G. Knepley 
1011db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`
1012608c71bfSMatthew G. Knepley @*/
1013d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1014d71ae5a4SJacob Faibussowitsch {
1015608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1016608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
10173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1018608c71bfSMatthew G. Knepley }
1019608c71bfSMatthew G. Knepley 
1020608c71bfSMatthew G. Knepley /*@
1021608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1022608c71bfSMatthew G. Knepley 
1023608c71bfSMatthew G. Knepley   Not Collective
1024608c71bfSMatthew G. Knepley 
1025608c71bfSMatthew G. Knepley   Output Parameter:
1026811af0c4SBarry Smith . flg - `PETSC_TRUE` if we log the requested memory size
1027608c71bfSMatthew G. Knepley 
1028608c71bfSMatthew G. Knepley   Level: developer
1029608c71bfSMatthew G. Knepley 
1030db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()`
1031608c71bfSMatthew G. Knepley @*/
1032d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1033d71ae5a4SJacob Faibussowitsch {
1034608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1035608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
10363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1037608c71bfSMatthew G. Knepley }
1038