xref: /petsc/src/sys/memory/mtr.c (revision dfb7d7afc6419f3665b48978fc015eb4d33caed1)
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;
29*dfb7d7afSStefano 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 
98811af0c4SBarry Smith     The Fortran calling sequence is simply `PetscMallocValidate(ierr)`
99e5c89e4eSSatish Balay 
100e5c89e4eSSatish Balay    No output is generated if there are no problems detected.
101e5c89e4eSSatish Balay 
10292f119d6SBarry Smith    Developers Note:
103811af0c4SBarry Smith      Uses the flg TRdebugLevel (set as the first argument to `PetscMallocSetDebug()`) to determine if it should run
10492f119d6SBarry Smith 
105db781477SPatrick Sanan .seealso: `CHKMEMQ`
106e5c89e4eSSatish Balay @*/
107d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[])
108d71ae5a4SJacob Faibussowitsch {
1096c093d5bSvictor   TRSPACE      *head, *lasthead;
110e5c89e4eSSatish Balay   char         *a;
1110700a824SBarry Smith   PetscClassId *nend;
112e5c89e4eSSatish Balay 
11338548759SBarry Smith   if (!TRdebugLevel) return 0;
1149371c9d4SSatish Balay   head     = TRhead;
1159371c9d4SSatish Balay   lasthead = NULL;
1162cba8197SMatthew G. Knepley   if (head && head->prev) {
117ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
1182cba8197SMatthew G. Knepley     (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", head, head->prev);
1194ed0ab5bSBarry Smith     return PETSC_ERR_MEMC;
1202cba8197SMatthew G. Knepley   }
121e5c89e4eSSatish Balay   while (head) {
1220700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
123ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
124e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Memory at address %p is corrupted\n", head);
1254ed0ab5bSBarry Smith       (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n");
126e269983cSBarry Smith       if (lasthead) {
127e269983cSBarry Smith         a = (char *)(((TrSPACE *)head) + 1);
128ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Last intact block [id=%d(%.0f)] at address %p allocated in %s() at %s:%d\n", lasthead->id, (PetscLogDouble)lasthead->size, a, lasthead->functionname, lasthead->filename, lasthead->lineno);
129e269983cSBarry Smith       }
130e269983cSBarry Smith       abort();
1314ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
132e5c89e4eSSatish Balay     }
133e5c89e4eSSatish Balay     a    = (char *)(((TrSPACE *)head) + 1);
1340700a824SBarry Smith     nend = (PetscClassId *)(a + head->size);
1350700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
136ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
137e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
138e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a);
1394ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
140e5c89e4eSSatish Balay       } else {
141e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a);
142ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
1434ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
144e5c89e4eSSatish Balay       }
145e5c89e4eSSatish Balay     }
1462cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
147ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line);
1482cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", head->prev, lasthead);
149ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno);
150ccd65f63SJunchao Zhang       (*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   }
1564ed0ab5bSBarry Smith   return 0;
157e5c89e4eSSatish Balay }
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay /*
160e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
161e5c89e4eSSatish Balay 
162e5c89e4eSSatish Balay     Input Parameters:
163e5c89e4eSSatish Balay +   a   - number of bytes to allocate
164e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
165efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
166e5c89e4eSSatish Balay 
167e5c89e4eSSatish Balay     Returns:
16892f119d6SBarry Smith     double aligned pointer to requested storage, or null if not  available.
169e5c89e4eSSatish Balay  */
170d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result)
171d71ae5a4SJacob Faibussowitsch {
172e5c89e4eSSatish Balay   TRSPACE *head;
173e5c89e4eSSatish Balay   char    *inew;
174e5c89e4eSSatish Balay   size_t   nsize;
175e5c89e4eSSatish Balay 
176e5c89e4eSSatish Balay   PetscFunctionBegin;
177f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
1789371c9d4SSatish Balay   if (!a) {
1799371c9d4SSatish Balay     *result = NULL;
1809371c9d4SSatish Balay     PetscFunctionReturn(0);
1819371c9d4SSatish Balay   }
182f0ba7cfcSLisandro Dalcin 
18311cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
184e5c89e4eSSatish Balay 
18525b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
1869566063dSJacob Faibussowitsch   PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew));
187e3ed9ee7SBarry Smith 
188e5c89e4eSSatish Balay   head = (TRSPACE *)inew;
189e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
190e5c89e4eSSatish Balay 
191e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
192e5c89e4eSSatish Balay   head->next   = TRhead;
193e5c89e4eSSatish Balay   TRhead       = head;
194f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
195e5c89e4eSSatish Balay   head->size   = nsize;
196608c71bfSMatthew G. Knepley   head->rsize  = a;
197e269983cSBarry Smith   head->id     = TRid++;
198e5c89e4eSSatish Balay   head->lineno = lineno;
199e5c89e4eSSatish Balay 
200e5c89e4eSSatish Balay   head->filename                  = filename;
201e5c89e4eSSatish Balay   head->functionname              = function;
2020700a824SBarry Smith   head->classid                   = CLASSID_VALUE;
2030700a824SBarry Smith   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
204e5c89e4eSSatish Balay 
205608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
206a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
207e3ed9ee7SBarry Smith   if (PetscLogMemory) {
208e3ed9ee7SBarry Smith     PetscInt i;
209e3ed9ee7SBarry Smith     for (i = 0; i < NumTRMaxMems; i++) {
210e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
211e3ed9ee7SBarry Smith     }
212e3ed9ee7SBarry Smith   }
213e5c89e4eSSatish Balay   TRfrags++;
214e5c89e4eSSatish Balay 
215*dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
2169566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
2172c9581d2SBarry Smith   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2182c9581d2SBarry Smith   head->stack.line[head->stack.currentsize - 2] = lineno;
21992f119d6SBarry Smith   #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2202d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
22192f119d6SBarry Smith     size_t     i, n = a / sizeof(PetscReal);
22292f119d6SBarry Smith     PetscReal *s = (PetscReal *)inew;
22392f119d6SBarry Smith       /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
22492f119d6SBarry Smith     #if defined(PETSC_USE_REAL_SINGLE)
225df282883SBarry Smith     int nas = 0x7F800002;
22692f119d6SBarry Smith     #else
22792f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22892f119d6SBarry Smith     #endif
229ad540459SPierre Jolivet     for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal));
23092f119d6SBarry Smith   }
23192f119d6SBarry Smith   #endif
232e5c89e4eSSatish Balay #endif
233e5c89e4eSSatish Balay 
234e5c89e4eSSatish Balay   /*
23592f119d6SBarry Smith          Allow logging of all mallocs made.
23692f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
237e5c89e4eSSatish Balay   */
238574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
239e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
240e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
24128b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
242a297a907SKarl Rupp 
243a2ea699eSBarry Smith       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
24428b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
245a297a907SKarl Rupp 
246a2ea699eSBarry Smith       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
24728b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
248e5c89e4eSSatish Balay     }
249e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
250e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
251e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
252e5c89e4eSSatish Balay   }
25348a46eb9SPierre Jolivet   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
254e5c89e4eSSatish Balay   *result = (void *)inew;
255e5c89e4eSSatish Balay   PetscFunctionReturn(0);
256e5c89e4eSSatish Balay }
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay /*
259e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
260e5c89e4eSSatish Balay 
261e5c89e4eSSatish Balay    Input Parameters:
262e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
263e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
264608c71bfSMatthew G. Knepley .   filename  - file name where used.  Use __FILE__ for this
265e5c89e4eSSatish Balay  */
266d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[])
267d71ae5a4SJacob Faibussowitsch {
268e5c89e4eSSatish Balay   char         *a = (char *)aa;
269e5c89e4eSSatish Balay   TRSPACE      *head;
270e5c89e4eSSatish Balay   char         *ahead;
271608c71bfSMatthew G. Knepley   size_t        asize;
2720700a824SBarry Smith   PetscClassId *nend;
273e5c89e4eSSatish Balay 
274e5c89e4eSSatish Balay   PetscFunctionBegin;
275e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
27649d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
277e5c89e4eSSatish Balay 
2789566063dSJacob Faibussowitsch   PetscCall(PetscMallocValidate(lineno, function, filename));
279e5c89e4eSSatish Balay 
280e5c89e4eSSatish Balay   ahead = a;
281e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
282e5c89e4eSSatish Balay   head  = (TRSPACE *)a;
283e5c89e4eSSatish Balay 
2840700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
285ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
286e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a);
287e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
288e5c89e4eSSatish Balay   }
2890700a824SBarry Smith   nend = (PetscClassId *)(ahead + head->size);
2900700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
291e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
292ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
293e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE));
294e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
295ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
296e5c89e4eSSatish Balay       } else {
297ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno);
298e5c89e4eSSatish Balay       }
299e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
300e5c89e4eSSatish Balay     } else {
301e5c89e4eSSatish Balay       /* Damaged tail */
302ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno);
303e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a);
304ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
305e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
306e5c89e4eSSatish Balay     }
307e5c89e4eSSatish Balay   }
308608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
3099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
310608c71bfSMatthew G. Knepley   }
311e5c89e4eSSatish Balay   /* Mark the location freed */
312e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
313e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
314608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
315608c71bfSMatthew G. Knepley     head->lineno       = lineno;
316608c71bfSMatthew G. Knepley     head->filename     = filename;
317e5c89e4eSSatish Balay     head->functionname = function;
318e5c89e4eSSatish Balay   } else {
319e5c89e4eSSatish Balay     head->lineno = -head->lineno;
320e5c89e4eSSatish Balay   }
321608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
32208401ef6SPierre Jolivet   PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed");
323608c71bfSMatthew G. Knepley   TRallocated -= asize;
324e5c89e4eSSatish Balay   TRfrags--;
325e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
326e5c89e4eSSatish Balay   else TRhead = head->next;
327e5c89e4eSSatish Balay 
328e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
3299566063dSJacob Faibussowitsch   PetscCall(PetscFreeAlign(a, lineno, function, filename));
330e5c89e4eSSatish Balay   PetscFunctionReturn(0);
331e5c89e4eSSatish Balay }
332e5c89e4eSSatish Balay 
3333221ece2SMatthew G. Knepley /*
3343221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3353221ece2SMatthew G. Knepley 
3363221ece2SMatthew G. Knepley   Input Parameters:
3373221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3383221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3393221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
34092f119d6SBarry Smith - result - original memory
3413221ece2SMatthew G. Knepley 
3423221ece2SMatthew G. Knepley   Output Parameter:
3433221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3443221ece2SMatthew G. Knepley 
3453221ece2SMatthew G. Knepley   Level: developer
3463221ece2SMatthew G. Knepley 
347db781477SPatrick Sanan .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()`
3483221ece2SMatthew G. Knepley */
349d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
350d71ae5a4SJacob Faibussowitsch {
3513221ece2SMatthew G. Knepley   char         *a = (char *)*result;
3523221ece2SMatthew G. Knepley   TRSPACE      *head;
3533221ece2SMatthew G. Knepley   char         *ahead, *inew;
3543221ece2SMatthew G. Knepley   PetscClassId *nend;
3553221ece2SMatthew G. Knepley   size_t        nsize;
3563221ece2SMatthew G. Knepley 
3573221ece2SMatthew G. Knepley   PetscFunctionBegin;
35892f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
359c22f1541SToby Isaac   if (!len) {
3609566063dSJacob Faibussowitsch     PetscCall(PetscTrFreeDefault(*result, lineno, function, filename));
361c22f1541SToby Isaac     *result = NULL;
362c22f1541SToby Isaac     PetscFunctionReturn(0);
363c22f1541SToby Isaac   }
36492f119d6SBarry Smith   /* If the orginal space was NULL just use the regular malloc() */
365f590eff4SLisandro Dalcin   if (!*result) {
3669566063dSJacob Faibussowitsch     PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result));
367f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
368f590eff4SLisandro Dalcin   }
3693221ece2SMatthew G. Knepley 
37011cc89d2SBarry Smith   PetscCall(PetscMallocValidate(lineno, function, filename));
3713221ece2SMatthew G. Knepley 
3723221ece2SMatthew G. Knepley   ahead = a;
3733221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3743221ece2SMatthew G. Knepley   head  = (TRSPACE *)a;
3753221ece2SMatthew G. Knepley   inew  = a;
3763221ece2SMatthew G. Knepley 
3773221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
378ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3793221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a);
3803221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory");
3813221ece2SMatthew G. Knepley   }
3823221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3833221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3843221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
385ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3863221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE));
3873221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
388ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
3893221ece2SMatthew G. Knepley       } else {
390ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno);
3913221ece2SMatthew G. Knepley       }
3923221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed");
3933221ece2SMatthew G. Knepley     } else {
3943221ece2SMatthew G. Knepley       /* Damaged tail */
395ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3963221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a);
397ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
3983221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory");
3993221ece2SMatthew G. Knepley     }
4003221ece2SMatthew G. Knepley   }
4013221ece2SMatthew G. Knepley 
40292f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
403608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
4043221ece2SMatthew G. Knepley   TRfrags--;
4053221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4063221ece2SMatthew G. Knepley   else TRhead = head->next;
4073221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4083221ece2SMatthew G. Knepley 
4093221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1);
4109566063dSJacob Faibussowitsch   PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew));
4113221ece2SMatthew G. Knepley 
4123221ece2SMatthew G. Knepley   head = (TRSPACE *)inew;
4133221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4143221ece2SMatthew G. Knepley 
4153221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4163221ece2SMatthew G. Knepley   head->next   = TRhead;
4173221ece2SMatthew G. Knepley   TRhead       = head;
4183221ece2SMatthew G. Knepley   head->prev   = NULL;
4193221ece2SMatthew G. Knepley   head->size   = nsize;
420608c71bfSMatthew G. Knepley   head->rsize  = len;
421e269983cSBarry Smith   head->id     = TRid++;
4223221ece2SMatthew G. Knepley   head->lineno = lineno;
4233221ece2SMatthew G. Knepley 
4243221ece2SMatthew G. Knepley   head->filename                  = filename;
4253221ece2SMatthew G. Knepley   head->functionname              = function;
4263221ece2SMatthew G. Knepley   head->classid                   = CLASSID_VALUE;
4273221ece2SMatthew G. Knepley   *(PetscClassId *)(inew + nsize) = CLASSID_VALUE;
4283221ece2SMatthew G. Knepley 
429608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4303221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
431e3ed9ee7SBarry Smith   if (PetscLogMemory) {
432e3ed9ee7SBarry Smith     PetscInt i;
433e3ed9ee7SBarry Smith     for (i = 0; i < NumTRMaxMems; i++) {
434e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
435e3ed9ee7SBarry Smith     }
436e3ed9ee7SBarry Smith   }
4373221ece2SMatthew G. Knepley   TRfrags++;
4383221ece2SMatthew G. Knepley 
439*dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
4409566063dSJacob Faibussowitsch   PetscCall(PetscStackCopy(&petscstack, &head->stack));
4413221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4423221ece2SMatthew G. Knepley   head->stack.line[head->stack.currentsize - 2] = lineno;
4433221ece2SMatthew G. Knepley #endif
4443221ece2SMatthew G. Knepley 
4453221ece2SMatthew G. Knepley   /*
44692f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
44792f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4483221ece2SMatthew G. Knepley   */
4493221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4503221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4513221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t));
45228b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4533221ece2SMatthew G. Knepley 
4543221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
45528b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4563221ece2SMatthew G. Knepley 
4573221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *));
45828b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " ");
4593221ece2SMatthew G. Knepley     }
4603221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4613221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4623221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4633221ece2SMatthew G. Knepley   }
4643221ece2SMatthew G. Knepley   *result = (void *)inew;
4653221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4663221ece2SMatthew G. Knepley }
4673221ece2SMatthew G. Knepley 
468fe7fb379SMatthew Knepley /*@C
46992f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
470e5c89e4eSSatish Balay 
471c3339decSBarry Smith     Collective
472e5c89e4eSSatish Balay 
473d8d19677SJose E. Roman     Input Parameters:
474e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
475e5c89e4eSSatish Balay -    message - string printed before values
476e5c89e4eSSatish Balay 
477811af0c4SBarry Smith     Options Database Keys:
47892f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
479811af0c4SBarry Smith .    -log_view_memory - print memory usage per event
4800841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4810841954dSBarry Smith 
482e5c89e4eSSatish Balay     Level: intermediate
483e5c89e4eSSatish Balay 
484db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()`
485e5c89e4eSSatish Balay  @*/
486d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[])
487d71ae5a4SJacob Faibussowitsch {
4880841954dSBarry Smith   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax;
4890841954dSBarry Smith   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax;
490e5c89e4eSSatish Balay   MPI_Comm       comm;
491e5c89e4eSSatish Balay 
492e5c89e4eSSatish Balay   PetscFunctionBegin;
493e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4949566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&allocated));
4959566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4969566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&resident));
4979566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
498e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
4999566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
5009566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
501e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
5029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5059566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5099566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5139566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
5149566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5159566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
518e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5199566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5249566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5259566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5269566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
527e5c89e4eSSatish Balay   } else if (resident && allocated) {
5289566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5319566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
537e5c89e4eSSatish Balay   } else if (allocated) {
5389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
544e5c89e4eSSatish Balay   } else {
5459566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
546e5c89e4eSSatish Balay   }
5479566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
548e5c89e4eSSatish Balay   PetscFunctionReturn(0);
549e5c89e4eSSatish Balay }
550e5c89e4eSSatish Balay 
55146eb3923SBarry Smith /*@
552811af0c4SBarry Smith     PetscMallocGetCurrentUsage - gets the current amount of memory used that was allocated with `PetscMalloc()`
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay     Not Collective
555e5c89e4eSSatish Balay 
556e5c89e4eSSatish Balay     Output Parameters:
557e5c89e4eSSatish Balay .   space - number of bytes currently allocated
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay     Level: intermediate
560e5c89e4eSSatish Balay 
561db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
562db781477SPatrick Sanan           `PetscMemoryGetMaximumUsage()`
563e5c89e4eSSatish Balay  @*/
564d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space)
565d71ae5a4SJacob Faibussowitsch {
566e5c89e4eSSatish Balay   PetscFunctionBegin;
567e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRallocated;
568e5c89e4eSSatish Balay   PetscFunctionReturn(0);
569e5c89e4eSSatish Balay }
570e5c89e4eSSatish Balay 
571dc37d89fSBarry Smith /*@
572811af0c4SBarry Smith     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was obtained with `PetscMalloc()` at any time
573811af0c4SBarry Smith         during this run, the high water mark.
574e5c89e4eSSatish Balay 
575e5c89e4eSSatish Balay     Not Collective
576e5c89e4eSSatish Balay 
577e5c89e4eSSatish Balay     Output Parameters:
578e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
579e5c89e4eSSatish Balay 
580e5c89e4eSSatish Balay     Level: intermediate
581e5c89e4eSSatish Balay 
582db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
583db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
584e5c89e4eSSatish Balay  @*/
585d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space)
586d71ae5a4SJacob Faibussowitsch {
587e5c89e4eSSatish Balay   PetscFunctionBegin;
588e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRMaxMem;
589e5c89e4eSSatish Balay   PetscFunctionReturn(0);
590e5c89e4eSSatish Balay }
591e5c89e4eSSatish Balay 
592e3ed9ee7SBarry Smith /*@
593e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
594e3ed9ee7SBarry Smith 
595e3ed9ee7SBarry Smith     Not Collective
596e3ed9ee7SBarry Smith 
597e3ed9ee7SBarry Smith     Input Parameter:
598e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
599e3ed9ee7SBarry Smith 
600e3ed9ee7SBarry Smith     Level: developer
601e3ed9ee7SBarry Smith 
602db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
603db781477SPatrick Sanan           `PetscMallocPopMaximumUsage()`
604e3ed9ee7SBarry Smith  @*/
605d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPushMaximumUsage(int event)
606d71ae5a4SJacob Faibussowitsch {
607e3ed9ee7SBarry Smith   PetscFunctionBegin;
608e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
609e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
610e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
611e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
612e3ed9ee7SBarry Smith }
613e3ed9ee7SBarry Smith 
614e3ed9ee7SBarry Smith /*@
615e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
616e3ed9ee7SBarry Smith 
617e3ed9ee7SBarry Smith     Not Collective
618e3ed9ee7SBarry Smith 
619e3ed9ee7SBarry Smith     Input Parameter:
620e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
621e3ed9ee7SBarry Smith 
622e3ed9ee7SBarry Smith     Output Parameter:
623e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
624e3ed9ee7SBarry Smith 
625e3ed9ee7SBarry Smith     Level: developer
626e3ed9ee7SBarry Smith 
627db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
628db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
629e3ed9ee7SBarry Smith  @*/
630d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu)
631d71ae5a4SJacob Faibussowitsch {
632e3ed9ee7SBarry Smith   PetscFunctionBegin;
633e3ed9ee7SBarry Smith   *mu = 0;
634e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
63508401ef6SPierre Jolivet   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
636e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
637e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
638e3ed9ee7SBarry Smith }
639e3ed9ee7SBarry Smith 
640a64a8e02SBarry Smith /*@C
641811af0c4SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory
642a64a8e02SBarry Smith 
643811af0c4SBarry Smith    Collective on `PETSC_COMM_WORLD`
644a64a8e02SBarry Smith 
645a64a8e02SBarry Smith    Input Parameter:
646a64a8e02SBarry Smith .    ptr - the memory location
647a64a8e02SBarry Smith 
648fd292e60Sprj-    Output Parameter:
649a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
650a64a8e02SBarry Smith 
651a64a8e02SBarry Smith    Level: intermediate
652a64a8e02SBarry Smith 
653db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`
654a64a8e02SBarry Smith @*/
655d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack)
656d71ae5a4SJacob Faibussowitsch {
657*dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
658a64a8e02SBarry Smith   TRSPACE *head;
659a64a8e02SBarry Smith 
660a64a8e02SBarry Smith   PetscFunctionBegin;
661a64a8e02SBarry Smith   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
662a64a8e02SBarry Smith   *stack = &head->stack;
663a64a8e02SBarry Smith   PetscFunctionReturn(0);
66476386721SLisandro Dalcin #else
665f0ba7cfcSLisandro Dalcin   *stack = NULL;
666*dfb7d7afSStefano Zampini   return 0;
667a64a8e02SBarry Smith #endif
668*dfb7d7afSStefano Zampini }
669a64a8e02SBarry Smith 
670e5c89e4eSSatish Balay /*@C
67192f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
672e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
673e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
674e5c89e4eSSatish Balay    allocated.
675e5c89e4eSSatish Balay 
67692f119d6SBarry Smith    Not Collective
677e5c89e4eSSatish Balay 
678e5c89e4eSSatish Balay    Input Parameter:
679e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
680e5c89e4eSSatish Balay 
681e5c89e4eSSatish Balay    Options Database Key:
682811af0c4SBarry Smith .  -malloc_dump <optional filename> - Dumps unfreed memory during call to `PetscFinalize()`
683e5c89e4eSSatish Balay 
684e5c89e4eSSatish Balay    Level: intermediate
685e5c89e4eSSatish Balay 
686e5c89e4eSSatish Balay    Fortran Note:
687e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
688e5c89e4eSSatish Balay    The fp defaults to stdout.
689e5c89e4eSSatish Balay 
69095452b02SPatrick Sanan    Notes:
691811af0c4SBarry Smith      Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed.
692e5c89e4eSSatish Balay 
693811af0c4SBarry Smith      When called in `PetscFinalize()` dumps only the allocations that have not been properly freed
69492f119d6SBarry Smith 
695811af0c4SBarry Smith      `PetscMallocView()` prints a list of all memory ever allocated
69692f119d6SBarry Smith 
697db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`
698e5c89e4eSSatish Balay @*/
699d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocDump(FILE *fp)
700d71ae5a4SJacob Faibussowitsch {
701e5c89e4eSSatish Balay   TRSPACE    *head;
702e3ed9ee7SBarry Smith   size_t      libAlloc = 0;
703e5c89e4eSSatish Balay   PetscMPIInt rank;
704e5c89e4eSSatish Balay 
705e5c89e4eSSatish Balay   PetscFunctionBegin;
7069566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
707da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
708e5c89e4eSSatish Balay   head = TRhead;
709e5c89e4eSSatish Balay   while (head) {
710608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7115486ca60SMatthew G. Knepley     head = head->next;
7125486ca60SMatthew G. Knepley   }
7135486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7145486ca60SMatthew G. Knepley   head = TRhead;
7155486ca60SMatthew G. Knepley   while (head) {
7165486ca60SMatthew G. Knepley     PetscBool isLib;
7175486ca60SMatthew G. Knepley 
7189566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7195486ca60SMatthew G. Knepley     if (!isLib) {
720ccd65f63SJunchao Zhang       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
721*dfb7d7afSStefano Zampini #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY)
7229566063dSJacob Faibussowitsch       PetscCall(PetscStackPrint(&head->stack, fp));
723e5c89e4eSSatish Balay #endif
7245486ca60SMatthew G. Knepley     }
725e5c89e4eSSatish Balay     head = head->next;
726e5c89e4eSSatish Balay   }
727e5c89e4eSSatish Balay   PetscFunctionReturn(0);
728e5c89e4eSSatish Balay }
729e5c89e4eSSatish Balay 
730dc37d89fSBarry Smith /*@
731811af0c4SBarry Smith     PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view
732574034a9SJed Brown 
733574034a9SJed Brown     Not Collective
734574034a9SJed Brown 
7354165533cSJose E. Roman     Input Parameter:
736811af0c4SBarry Smith .   logmin - minimum allocation size to log, or `PETSC_DEFAULT`
737574034a9SJed Brown 
738574034a9SJed Brown     Options Database Key:
739811af0c4SBarry Smith +  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
7408b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7418b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
742574034a9SJed Brown 
743574034a9SJed Brown     Level: advanced
744574034a9SJed Brown 
745811af0c4SBarry Smith     Notes:
746811af0c4SBarry Smith     Must be called after `PetscMallocSetDebug()`
74792f119d6SBarry Smith 
748811af0c4SBarry Smith     Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available
74992f119d6SBarry Smith 
750db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`
751574034a9SJed Brown @*/
752d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
753d71ae5a4SJacob Faibussowitsch {
754574034a9SJed Brown   PetscFunctionBegin;
75592f119d6SBarry Smith   PetscLogMalloc = 0;
7569566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
757574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
758574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
759574034a9SJed Brown   PetscFunctionReturn(0);
760574034a9SJed Brown }
761574034a9SJed Brown 
762dc37d89fSBarry Smith /*@
763811af0c4SBarry Smith     PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged
76418a2528dSJed Brown 
76518a2528dSJed Brown     Not Collective
76618a2528dSJed Brown 
7674165533cSJose E. Roman     Output Parameter
768811af0c4SBarry Smith .   logging - `PETSC_TRUE` if logging is active
76918a2528dSJed Brown 
77018a2528dSJed Brown     Options Database Key:
771811af0c4SBarry Smith .  -malloc_view <optional filename> - Activates `PetscMallocView()`
77218a2528dSJed Brown 
77318a2528dSJed Brown     Level: advanced
77418a2528dSJed Brown 
775db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`
77618a2528dSJed Brown @*/
777d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocViewGet(PetscBool *logging)
778d71ae5a4SJacob Faibussowitsch {
77918a2528dSJed Brown   PetscFunctionBegin;
78018a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
78118a2528dSJed Brown   PetscFunctionReturn(0);
78218a2528dSJed Brown }
78318a2528dSJed Brown 
784608c71bfSMatthew G. Knepley /*@
785811af0c4SBarry Smith   PetscMallocTraceSet - Trace all calls to `PetscMalloc()`
786608c71bfSMatthew G. Knepley 
787608c71bfSMatthew G. Knepley   Not Collective
788608c71bfSMatthew G. Knepley 
7894165533cSJose E. Roman   Input Parameters:
790608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout
791608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
792608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
793608c71bfSMatthew G. Knepley 
794608c71bfSMatthew G. Knepley   Note:
795608c71bfSMatthew G. Knepley   The viewer should not be collective.
796608c71bfSMatthew G. Knepley 
797608c71bfSMatthew G. Knepley   Level: advanced
798608c71bfSMatthew G. Knepley 
799db781477SPatrick Sanan .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
800608c71bfSMatthew G. Knepley @*/
801d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
802d71ae5a4SJacob Faibussowitsch {
803608c71bfSMatthew G. Knepley   PetscFunctionBegin;
8049371c9d4SSatish Balay   if (!active) {
8059371c9d4SSatish Balay     PetscLogMallocTrace = -1;
8069371c9d4SSatish Balay     PetscFunctionReturn(0);
8079371c9d4SSatish Balay   }
808608c71bfSMatthew G. Knepley   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
809608c71bfSMatthew G. Knepley   PetscLogMallocTrace       = 0;
8109566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
811608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
812608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t)logmin;
813608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
814608c71bfSMatthew G. Knepley }
815608c71bfSMatthew G. Knepley 
816608c71bfSMatthew G. Knepley /*@
817811af0c4SBarry Smith   PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced
818608c71bfSMatthew G. Knepley 
819608c71bfSMatthew G. Knepley   Not Collective
820608c71bfSMatthew G. Knepley 
8214165533cSJose E. Roman   Output Parameter:
822811af0c4SBarry Smith . logging - `PETSC_TRUE` if logging is active
823608c71bfSMatthew G. Knepley 
824608c71bfSMatthew G. Knepley   Options Database Key:
825608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView()
826608c71bfSMatthew G. Knepley 
827608c71bfSMatthew G. Knepley   Level: advanced
828608c71bfSMatthew G. Knepley 
829db781477SPatrick Sanan .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
830608c71bfSMatthew G. Knepley @*/
831d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
832d71ae5a4SJacob Faibussowitsch {
833608c71bfSMatthew G. Knepley   PetscFunctionBegin;
834608c71bfSMatthew G. Knepley   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
835608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
836608c71bfSMatthew G. Knepley }
837608c71bfSMatthew G. Knepley 
838e5c89e4eSSatish Balay /*@C
839811af0c4SBarry Smith     PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls
840811af0c4SBarry Smith        `PetscMemoryGetMaximumUsage()`
841e5c89e4eSSatish Balay 
84292f119d6SBarry Smith     Not Collective
843e5c89e4eSSatish Balay 
844e5c89e4eSSatish Balay     Input Parameter:
8450298fd71SBarry Smith .   fp - file pointer; or NULL
846e5c89e4eSSatish Balay 
847e5c89e4eSSatish Balay     Options Database Key:
848811af0c4SBarry Smith .  -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()`
849e5c89e4eSSatish Balay 
850e5c89e4eSSatish Balay     Level: advanced
851e5c89e4eSSatish Balay 
852e5c89e4eSSatish Balay    Fortran Note:
85392f119d6SBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
854e5c89e4eSSatish Balay    The fp defaults to stdout.
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 
861db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`
862e5c89e4eSSatish Balay @*/
863d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocView(FILE *fp)
864d71ae5a4SJacob Faibussowitsch {
86592f119d6SBarry Smith   PetscInt       i, j, n, *perm;
866e5c89e4eSSatish Balay   size_t        *shortlength;
867f56c2debSBarry Smith   int           *shortcount, err;
86892f119d6SBarry Smith   PetscMPIInt    rank;
869ace3abfcSBarry Smith   PetscBool      match;
870e5c89e4eSSatish Balay   const char   **shortfunction;
871e5c89e4eSSatish Balay   PetscLogDouble rss;
872e5c89e4eSSatish Balay 
873e5c89e4eSSatish Balay   PetscFunctionBegin;
8749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
875f56c2debSBarry Smith   err = fflush(fp);
87628b400f6SJacob Faibussowitsch   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
877f56c2debSBarry Smith 
87808401ef6SPierre 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()");
879768aa557SSatish Balay 
880da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
8819566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&rss));
882e5c89e4eSSatish Balay   if (rss) {
88392f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
884e5c89e4eSSatish Balay   } else {
88592f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
886e5c89e4eSSatish Balay   }
8879371c9d4SSatish Balay   shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
8889371c9d4SSatish Balay   PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8899371c9d4SSatish Balay   shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
8909371c9d4SSatish Balay   PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8919371c9d4SSatish Balay   shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
8929371c9d4SSatish Balay   PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
89397b9d747SJed Brown   for (i = 0, n = 0; i < PetscLogMalloc; i++) {
894e5c89e4eSSatish Balay     for (j = 0; j < n; j++) {
8959566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
896e5c89e4eSSatish Balay       if (match) {
897e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
89859ffdab8SBarry Smith         shortcount[j]++;
899e5c89e4eSSatish Balay         goto foundit;
900e5c89e4eSSatish Balay       }
901e5c89e4eSSatish Balay     }
902e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
903e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
90459ffdab8SBarry Smith     shortcount[n]    = 1;
905e5c89e4eSSatish Balay     n++;
906e5c89e4eSSatish Balay   foundit:;
907e5c89e4eSSatish Balay   }
908e5c89e4eSSatish Balay 
9099371c9d4SSatish Balay   perm = (PetscInt *)malloc(n * sizeof(PetscInt));
9109371c9d4SSatish Balay   PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
911e5c89e4eSSatish Balay   for (i = 0; i < n; i++) perm[i] = i;
9129566063dSJacob Faibussowitsch   PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
913e5c89e4eSSatish Balay 
91492f119d6SBarry Smith   (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
915ad540459SPierre 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]]);
916e5c89e4eSSatish Balay   free(perm);
917e5c89e4eSSatish Balay   free(shortlength);
91859ffdab8SBarry Smith   free(shortcount);
919e5c89e4eSSatish Balay   free((char **)shortfunction);
920f56c2debSBarry Smith   err = fflush(fp);
92128b400f6SJacob Faibussowitsch   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
922e5c89e4eSSatish Balay   PetscFunctionReturn(0);
923e5c89e4eSSatish Balay }
924e5c89e4eSSatish Balay 
925e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
926e5c89e4eSSatish Balay 
927dc37d89fSBarry Smith /*@
92892f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
929e5c89e4eSSatish Balay 
930e5c89e4eSSatish Balay     Not Collective
931e5c89e4eSSatish Balay 
932d8d19677SJose E. Roman     Input Parameters:
933811af0c4SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow
9342d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
935e5c89e4eSSatish Balay 
936811af0c4SBarry Smith     Options Database Keys:
93779dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
93892f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
93979dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
94092f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
94179dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
94279dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
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 
949db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`
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;
96192f119d6SBarry Smith   TRdebugLevel          = eachcall;
96292f119d6SBarry Smith   TRMaxMem              = 0;
96392f119d6SBarry Smith   PetscLogMallocMax     = 10000;
96492f119d6SBarry Smith   PetscLogMalloc        = -1;
9652d4ee042Sprj-   TRdebugIinitializenan = initializenan;
966e5c89e4eSSatish Balay   PetscFunctionReturn(0);
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()`
97779dccf82SBarry Smith -    initializenan - initializes memory with NaN
9780acecf5bSBarry Smith 
9790acecf5bSBarry Smith    Level: intermediate
9800acecf5bSBarry Smith 
981811af0c4SBarry Smith    Note:
98279dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
9830acecf5bSBarry Smith 
984db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`
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;
99079dccf82SBarry Smith   if (eachcall) *eachcall = TRdebugLevel;
9912d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9920acecf5bSBarry Smith   PetscFunctionReturn(0);
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 
1008db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`
1009608c71bfSMatthew G. Knepley @*/
1010d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1011d71ae5a4SJacob Faibussowitsch {
1012608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1013608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
1014608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
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 
1027db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()`
1028608c71bfSMatthew G. Knepley @*/
1029d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1030d71ae5a4SJacob Faibussowitsch {
1031608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1032608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
1033608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1034608c71bfSMatthew G. Knepley }
1035