xref: /petsc/src/sys/memory/mtr.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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;
298bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
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
7492f119d6SBarry 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 
8492f119d6SBarry Smith    Options Database:.
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:
9479dccf82SBarry 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 
9692f119d6SBarry Smith     You should generally use CHKMEMQ as a short cut for calling this  routine.
97e5c89e4eSSatish Balay 
98e5c89e4eSSatish Balay     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:
10392f119d6SBarry 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 
107e5c89e4eSSatish Balay @*/
1089371c9d4SSatish Balay PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[]) {
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  */
1709371c9d4SSatish Balay PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result) {
171e5c89e4eSSatish Balay   TRSPACE       *head;
172e5c89e4eSSatish Balay   char          *inew;
173e5c89e4eSSatish Balay   size_t         nsize;
174e5c89e4eSSatish Balay   PetscErrorCode ierr;
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 
1839371c9d4SSatish Balay   ierr = PetscMallocValidate(lineno, function, filename);
1849371c9d4SSatish Balay   if (ierr) PetscFunctionReturn(ierr);
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 
2168bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
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
2309371c9d4SSatish Balay     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   }
254*48a46eb9SPierre 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;
256e5c89e4eSSatish Balay   PetscFunctionReturn(0);
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  */
2679371c9d4SSatish Balay PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[]) {
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 */
3499371c9d4SSatish Balay PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) {
3503221ece2SMatthew G. Knepley   char          *a = (char *)*result;
3513221ece2SMatthew G. Knepley   TRSPACE       *head;
3523221ece2SMatthew G. Knepley   char          *ahead, *inew;
3533221ece2SMatthew G. Knepley   PetscClassId  *nend;
3543221ece2SMatthew G. Knepley   size_t         nsize;
3553221ece2SMatthew G. Knepley   PetscErrorCode ierr;
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 
3709371c9d4SSatish Balay   ierr = PetscMallocValidate(lineno, function, filename);
3719371c9d4SSatish Balay   if (ierr) PetscFunctionReturn(ierr);
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) {
379ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3803221ece2SMatthew G. Knepley     (*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) {
386ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3873221ece2SMatthew G. Knepley       (*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 */) {
389ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno);
3903221ece2SMatthew G. Knepley       } else {
391ccd65f63SJunchao Zhang         (*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 */
396ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno);
3973221ece2SMatthew 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);
398ccd65f63SJunchao Zhang       (*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 
4403221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
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;
4663221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
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 
472e5c89e4eSSatish Balay     Collective on PetscViewer
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 
4780841954dSBarry Smith     Options Database:
47992f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
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  @*/
4869371c9d4SSatish Balay PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) {
4870841954dSBarry Smith   PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax;
4880841954dSBarry Smith   PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax;
489e5c89e4eSSatish Balay   MPI_Comm       comm;
490e5c89e4eSSatish Balay 
491e5c89e4eSSatish Balay   PetscFunctionBegin;
492e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4939566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetCurrentUsage(&allocated));
4949566063dSJacob Faibussowitsch   PetscCall(PetscMallocGetMaximumUsage(&allocatedmax));
4959566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetCurrentUsage(&resident));
4969566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&residentmax));
497e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident, residentmax);
4989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
4999566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message));
500e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
5019566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5049566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5089566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5129566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax));
5139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5149566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5159566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
517e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5189566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5199566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5209566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5219566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax));
5229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5249566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5259566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
526e5c89e4eSSatish Balay   } else if (resident && allocated) {
5279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5289566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory:                                  total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident));
5319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5359566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
536e5c89e4eSSatish Balay   } else if (allocated) {
5379566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm));
5389566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm));
5399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm));
5409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated));
5419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n"));
5429566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n"));
543e5c89e4eSSatish Balay   } else {
5449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
545e5c89e4eSSatish Balay   }
5469566063dSJacob Faibussowitsch   PetscCall(PetscViewerFlush(viewer));
547e5c89e4eSSatish Balay   PetscFunctionReturn(0);
548e5c89e4eSSatish Balay }
549e5c89e4eSSatish Balay 
55046eb3923SBarry Smith /*@
551e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
552e5c89e4eSSatish Balay 
553e5c89e4eSSatish Balay     Not Collective
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay     Output Parameters:
556e5c89e4eSSatish Balay .   space - number of bytes currently allocated
557e5c89e4eSSatish Balay 
558e5c89e4eSSatish Balay     Level: intermediate
559e5c89e4eSSatish Balay 
560db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
561db781477SPatrick Sanan           `PetscMemoryGetMaximumUsage()`
562e5c89e4eSSatish Balay  @*/
5639371c9d4SSatish Balay PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) {
564e5c89e4eSSatish Balay   PetscFunctionBegin;
565e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRallocated;
566e5c89e4eSSatish Balay   PetscFunctionReturn(0);
567e5c89e4eSSatish Balay }
568e5c89e4eSSatish Balay 
569dc37d89fSBarry Smith /*@
570e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
571e5c89e4eSSatish Balay         during this run.
572e5c89e4eSSatish Balay 
573e5c89e4eSSatish Balay     Not Collective
574e5c89e4eSSatish Balay 
575e5c89e4eSSatish Balay     Output Parameters:
576e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
577e5c89e4eSSatish Balay 
578e5c89e4eSSatish Balay     Level: intermediate
579e5c89e4eSSatish Balay 
580db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
581db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
582e5c89e4eSSatish Balay  @*/
5839371c9d4SSatish Balay PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) {
584e5c89e4eSSatish Balay   PetscFunctionBegin;
585e5c89e4eSSatish Balay   *space = (PetscLogDouble)TRMaxMem;
586e5c89e4eSSatish Balay   PetscFunctionReturn(0);
587e5c89e4eSSatish Balay }
588e5c89e4eSSatish Balay 
589e3ed9ee7SBarry Smith /*@
590e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
591e3ed9ee7SBarry Smith 
592e3ed9ee7SBarry Smith     Not Collective
593e3ed9ee7SBarry Smith 
594e3ed9ee7SBarry Smith     Input Parameter:
595e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
596e3ed9ee7SBarry Smith 
597e3ed9ee7SBarry Smith     Level: developer
598e3ed9ee7SBarry Smith 
599db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
600db781477SPatrick Sanan           `PetscMallocPopMaximumUsage()`
601e3ed9ee7SBarry Smith  @*/
6029371c9d4SSatish Balay PetscErrorCode PetscMallocPushMaximumUsage(int event) {
603e3ed9ee7SBarry Smith   PetscFunctionBegin;
604e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
605e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems - 1]       = TRallocated;
606e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems - 1] = event;
607e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
608e3ed9ee7SBarry Smith }
609e3ed9ee7SBarry Smith 
610e3ed9ee7SBarry Smith /*@
611e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
612e3ed9ee7SBarry Smith 
613e3ed9ee7SBarry Smith     Not Collective
614e3ed9ee7SBarry Smith 
615e3ed9ee7SBarry Smith     Input Parameter:
616e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
617e3ed9ee7SBarry Smith 
618e3ed9ee7SBarry Smith     Output Parameter:
619e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
620e3ed9ee7SBarry Smith 
621e3ed9ee7SBarry Smith     Level: developer
622e3ed9ee7SBarry Smith 
623db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`,
624db781477SPatrick Sanan           `PetscMallocPushMaximumUsage()`
625e3ed9ee7SBarry Smith  @*/
6269371c9d4SSatish Balay PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) {
627e3ed9ee7SBarry Smith   PetscFunctionBegin;
628e3ed9ee7SBarry Smith   *mu = 0;
629e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
63008401ef6SPierre Jolivet   PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested");
631e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
632e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
633e3ed9ee7SBarry Smith }
634e3ed9ee7SBarry Smith 
635a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
636a64a8e02SBarry Smith /*@C
637a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
638a64a8e02SBarry Smith 
639a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
640a64a8e02SBarry Smith 
641a64a8e02SBarry Smith    Input Parameter:
642a64a8e02SBarry Smith .    ptr - the memory location
643a64a8e02SBarry Smith 
644fd292e60Sprj-    Output Parameter:
645a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
646a64a8e02SBarry Smith 
647a64a8e02SBarry Smith    Level: intermediate
648a64a8e02SBarry Smith 
649db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`
650a64a8e02SBarry Smith @*/
6519371c9d4SSatish Balay PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) {
652a64a8e02SBarry Smith   TRSPACE *head;
653a64a8e02SBarry Smith 
654a64a8e02SBarry Smith   PetscFunctionBegin;
655a64a8e02SBarry Smith   head   = (TRSPACE *)(((char *)ptr) - HEADER_BYTES);
656a64a8e02SBarry Smith   *stack = &head->stack;
657a64a8e02SBarry Smith   PetscFunctionReturn(0);
658a64a8e02SBarry Smith }
65976386721SLisandro Dalcin #else
6609371c9d4SSatish Balay PetscErrorCode PetscMallocGetStack(void *ptr, void **stack) {
66176386721SLisandro Dalcin   PetscFunctionBegin;
662f0ba7cfcSLisandro Dalcin   *stack = NULL;
66376386721SLisandro Dalcin   PetscFunctionReturn(0);
66476386721SLisandro Dalcin }
665a64a8e02SBarry Smith #endif
666a64a8e02SBarry Smith 
667e5c89e4eSSatish Balay /*@C
66892f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
669e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
670e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
671e5c89e4eSSatish Balay    allocated.
672e5c89e4eSSatish Balay 
67392f119d6SBarry Smith    Not Collective
674e5c89e4eSSatish Balay 
675e5c89e4eSSatish Balay    Input Parameter:
676e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
677e5c89e4eSSatish Balay 
678e5c89e4eSSatish Balay    Options Database Key:
67992f119d6SBarry Smith .  -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
680e5c89e4eSSatish Balay 
681e5c89e4eSSatish Balay    Level: intermediate
682e5c89e4eSSatish Balay 
683e5c89e4eSSatish Balay    Fortran Note:
684e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
685e5c89e4eSSatish Balay    The fp defaults to stdout.
686e5c89e4eSSatish Balay 
68795452b02SPatrick Sanan    Notes:
68892f119d6SBarry Smith      Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
689e5c89e4eSSatish Balay 
69092f119d6SBarry Smith      When called in PetscFinalize() dumps only the allocations that have not been properly freed
69192f119d6SBarry Smith 
69292f119d6SBarry Smith      PetscMallocView() prints a list of all memory ever allocated
69392f119d6SBarry Smith 
694db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()`
695e5c89e4eSSatish Balay @*/
6969371c9d4SSatish Balay PetscErrorCode PetscMallocDump(FILE *fp) {
697e5c89e4eSSatish Balay   TRSPACE    *head;
698e3ed9ee7SBarry Smith   size_t      libAlloc = 0;
699e5c89e4eSSatish Balay   PetscMPIInt rank;
700e5c89e4eSSatish Balay 
701e5c89e4eSSatish Balay   PetscFunctionBegin;
7029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
703da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
704e5c89e4eSSatish Balay   head = TRhead;
705e5c89e4eSSatish Balay   while (head) {
706608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7075486ca60SMatthew G. Knepley     head = head->next;
7085486ca60SMatthew G. Knepley   }
7095486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated);
7105486ca60SMatthew G. Knepley   head = TRhead;
7115486ca60SMatthew G. Knepley   while (head) {
7125486ca60SMatthew G. Knepley     PetscBool isLib;
7135486ca60SMatthew G. Knepley 
7149566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7155486ca60SMatthew G. Knepley     if (!isLib) {
716ccd65f63SJunchao Zhang       fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno);
7178bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
7189566063dSJacob Faibussowitsch       PetscCall(PetscStackPrint(&head->stack, fp));
719e5c89e4eSSatish Balay #endif
7205486ca60SMatthew G. Knepley     }
721e5c89e4eSSatish Balay     head = head->next;
722e5c89e4eSSatish Balay   }
723e5c89e4eSSatish Balay   PetscFunctionReturn(0);
724e5c89e4eSSatish Balay }
725e5c89e4eSSatish Balay 
726dc37d89fSBarry Smith /*@
72792f119d6SBarry Smith     PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
728574034a9SJed Brown 
729574034a9SJed Brown     Not Collective
730574034a9SJed Brown 
7314165533cSJose E. Roman     Input Parameter:
732574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
733574034a9SJed Brown 
734574034a9SJed Brown     Options Database Key:
73592f119d6SBarry Smith +  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
7368b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7378b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
738574034a9SJed Brown 
739574034a9SJed Brown     Level: advanced
740574034a9SJed Brown 
74192f119d6SBarry Smith     Notes: Must be called after PetscMallocSetDebug()
74292f119d6SBarry Smith 
74392f119d6SBarry Smith     Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
74492f119d6SBarry Smith 
745db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()`
746574034a9SJed Brown @*/
7479371c9d4SSatish Balay PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) {
748574034a9SJed Brown   PetscFunctionBegin;
74992f119d6SBarry Smith   PetscLogMalloc = 0;
7509566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
751574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
752574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
753574034a9SJed Brown   PetscFunctionReturn(0);
754574034a9SJed Brown }
755574034a9SJed Brown 
756dc37d89fSBarry Smith /*@
75792f119d6SBarry Smith     PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
75818a2528dSJed Brown 
75918a2528dSJed Brown     Not Collective
76018a2528dSJed Brown 
7614165533cSJose E. Roman     Output Parameter
76218a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
76318a2528dSJed Brown 
76418a2528dSJed Brown     Options Database Key:
76592f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView()
76618a2528dSJed Brown 
76718a2528dSJed Brown     Level: advanced
76818a2528dSJed Brown 
769db781477SPatrick Sanan .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()`
77018a2528dSJed Brown @*/
7719371c9d4SSatish Balay PetscErrorCode PetscMallocViewGet(PetscBool *logging) {
77218a2528dSJed Brown   PetscFunctionBegin;
77318a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
77418a2528dSJed Brown   PetscFunctionReturn(0);
77518a2528dSJed Brown }
77618a2528dSJed Brown 
777608c71bfSMatthew G. Knepley /*@
778608c71bfSMatthew G. Knepley   PetscMallocTraceSet - Trace all calls to PetscMalloc()
779608c71bfSMatthew G. Knepley 
780608c71bfSMatthew G. Knepley   Not Collective
781608c71bfSMatthew G. Knepley 
7824165533cSJose E. Roman   Input Parameters:
783608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout
784608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
785608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
786608c71bfSMatthew G. Knepley 
787608c71bfSMatthew G. Knepley   Note:
788608c71bfSMatthew G. Knepley   The viewer should not be collective.
789608c71bfSMatthew G. Knepley 
790608c71bfSMatthew G. Knepley   Level: advanced
791608c71bfSMatthew G. Knepley 
792db781477SPatrick Sanan .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
793608c71bfSMatthew G. Knepley @*/
7949371c9d4SSatish Balay PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) {
795608c71bfSMatthew G. Knepley   PetscFunctionBegin;
7969371c9d4SSatish Balay   if (!active) {
7979371c9d4SSatish Balay     PetscLogMallocTrace = -1;
7989371c9d4SSatish Balay     PetscFunctionReturn(0);
7999371c9d4SSatish Balay   }
800608c71bfSMatthew G. Knepley   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
801608c71bfSMatthew G. Knepley   PetscLogMallocTrace       = 0;
8029566063dSJacob Faibussowitsch   PetscCall(PetscMemorySetGetMaximumUsage());
803608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
804608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t)logmin;
805608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
806608c71bfSMatthew G. Knepley }
807608c71bfSMatthew G. Knepley 
808608c71bfSMatthew G. Knepley /*@
809608c71bfSMatthew G. Knepley   PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
810608c71bfSMatthew G. Knepley 
811608c71bfSMatthew G. Knepley   Not Collective
812608c71bfSMatthew G. Knepley 
8134165533cSJose E. Roman   Output Parameter:
814608c71bfSMatthew G. Knepley . logging - PETSC_TRUE if logging is active
815608c71bfSMatthew G. Knepley 
816608c71bfSMatthew G. Knepley   Options Database Key:
817608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView()
818608c71bfSMatthew G. Knepley 
819608c71bfSMatthew G. Knepley   Level: advanced
820608c71bfSMatthew G. Knepley 
821db781477SPatrick Sanan .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()`
822608c71bfSMatthew G. Knepley @*/
8239371c9d4SSatish Balay PetscErrorCode PetscMallocTraceGet(PetscBool *logging) {
824608c71bfSMatthew G. Knepley   PetscFunctionBegin;
825608c71bfSMatthew G. Knepley   *logging = (PetscBool)(PetscLogMallocTrace >= 0);
826608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
827608c71bfSMatthew G. Knepley }
828608c71bfSMatthew G. Knepley 
829e5c89e4eSSatish Balay /*@C
83092f119d6SBarry Smith     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
83121b680ceSJed Brown        PetscMemoryGetMaximumUsage()
832e5c89e4eSSatish Balay 
83392f119d6SBarry Smith     Not Collective
834e5c89e4eSSatish Balay 
835e5c89e4eSSatish Balay     Input Parameter:
8360298fd71SBarry Smith .   fp - file pointer; or NULL
837e5c89e4eSSatish Balay 
838e5c89e4eSSatish Balay     Options Database Key:
83992f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
840e5c89e4eSSatish Balay 
841e5c89e4eSSatish Balay     Level: advanced
842e5c89e4eSSatish Balay 
843e5c89e4eSSatish Balay    Fortran Note:
84492f119d6SBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
845e5c89e4eSSatish Balay    The fp defaults to stdout.
846e5c89e4eSSatish Balay 
84792f119d6SBarry Smith    Notes:
84892f119d6SBarry Smith      PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
84992f119d6SBarry Smith 
85092f119d6SBarry Smith      PetscMemoryView() gives a brief summary of current memory usage
85192f119d6SBarry Smith 
852db781477SPatrick Sanan .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()`
853e5c89e4eSSatish Balay @*/
8549371c9d4SSatish Balay PetscErrorCode PetscMallocView(FILE *fp) {
85592f119d6SBarry Smith   PetscInt       i, j, n, *perm;
856e5c89e4eSSatish Balay   size_t        *shortlength;
857f56c2debSBarry Smith   int           *shortcount, err;
85892f119d6SBarry Smith   PetscMPIInt    rank;
859ace3abfcSBarry Smith   PetscBool      match;
860e5c89e4eSSatish Balay   const char   **shortfunction;
861e5c89e4eSSatish Balay   PetscLogDouble rss;
862e5c89e4eSSatish Balay 
863e5c89e4eSSatish Balay   PetscFunctionBegin;
8649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank));
865f56c2debSBarry Smith   err = fflush(fp);
86628b400f6SJacob Faibussowitsch   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
867f56c2debSBarry Smith 
86808401ef6SPierre 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()");
869768aa557SSatish Balay 
870da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
8719566063dSJacob Faibussowitsch   PetscCall(PetscMemoryGetMaximumUsage(&rss));
872e5c89e4eSSatish Balay   if (rss) {
87392f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss);
874e5c89e4eSSatish Balay   } else {
87592f119d6SBarry Smith     (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem);
876e5c89e4eSSatish Balay   }
8779371c9d4SSatish Balay   shortcount = (int *)malloc(PetscLogMalloc * sizeof(int));
8789371c9d4SSatish Balay   PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8799371c9d4SSatish Balay   shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t));
8809371c9d4SSatish Balay   PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
8819371c9d4SSatish Balay   shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *));
8829371c9d4SSatish Balay   PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
88397b9d747SJed Brown   for (i = 0, n = 0; i < PetscLogMalloc; i++) {
884e5c89e4eSSatish Balay     for (j = 0; j < n; j++) {
8859566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match));
886e5c89e4eSSatish Balay       if (match) {
887e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
88859ffdab8SBarry Smith         shortcount[j]++;
889e5c89e4eSSatish Balay         goto foundit;
890e5c89e4eSSatish Balay       }
891e5c89e4eSSatish Balay     }
892e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
893e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
89459ffdab8SBarry Smith     shortcount[n]    = 1;
895e5c89e4eSSatish Balay     n++;
896e5c89e4eSSatish Balay   foundit:;
897e5c89e4eSSatish Balay   }
898e5c89e4eSSatish Balay 
8999371c9d4SSatish Balay   perm = (PetscInt *)malloc(n * sizeof(PetscInt));
9009371c9d4SSatish Balay   PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory");
901e5c89e4eSSatish Balay   for (i = 0; i < n; i++) perm[i] = i;
9029566063dSJacob Faibussowitsch   PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm));
903e5c89e4eSSatish Balay 
90492f119d6SBarry Smith   (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank);
9059371c9d4SSatish Balay   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]]); }
906e5c89e4eSSatish Balay   free(perm);
907e5c89e4eSSatish Balay   free(shortlength);
90859ffdab8SBarry Smith   free(shortcount);
909e5c89e4eSSatish Balay   free((char **)shortfunction);
910f56c2debSBarry Smith   err = fflush(fp);
91128b400f6SJacob Faibussowitsch   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file");
912e5c89e4eSSatish Balay   PetscFunctionReturn(0);
913e5c89e4eSSatish Balay }
914e5c89e4eSSatish Balay 
915e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
916e5c89e4eSSatish Balay 
917dc37d89fSBarry Smith /*@
91892f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
919e5c89e4eSSatish Balay 
920e5c89e4eSSatish Balay     Not Collective
921e5c89e4eSSatish Balay 
922d8d19677SJose E. Roman     Input Parameters:
92392f119d6SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
9242d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
925e5c89e4eSSatish Balay 
92692f119d6SBarry Smith     Options Database:
92779dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
92892f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
92979dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
93092f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
93179dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
93279dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
933e5c89e4eSSatish Balay 
93492f119d6SBarry Smith    Level: developer
93592f119d6SBarry Smith 
93692f119d6SBarry Smith     Notes: This is called in PetscInitialize() and should not be called elsewhere
93792f119d6SBarry Smith 
938db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()`
939e5c89e4eSSatish Balay @*/
9409371c9d4SSatish Balay PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) {
941e5c89e4eSSatish Balay   PetscFunctionBegin;
94208401ef6SPierre 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()");
9439566063dSJacob Faibussowitsch   PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault));
94492f119d6SBarry Smith 
94592f119d6SBarry Smith   TRallocated           = 0;
94692f119d6SBarry Smith   TRfrags               = 0;
94792f119d6SBarry Smith   TRhead                = NULL;
94892f119d6SBarry Smith   TRid                  = 0;
94992f119d6SBarry Smith   TRdebugLevel          = eachcall;
95092f119d6SBarry Smith   TRMaxMem              = 0;
95192f119d6SBarry Smith   PetscLogMallocMax     = 10000;
95292f119d6SBarry Smith   PetscLogMalloc        = -1;
9532d4ee042Sprj-   TRdebugIinitializenan = initializenan;
954e5c89e4eSSatish Balay   PetscFunctionReturn(0);
955e5c89e4eSSatish Balay }
9560acecf5bSBarry Smith 
957dc37d89fSBarry Smith /*@
95892f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9590acecf5bSBarry Smith 
9600acecf5bSBarry Smith     Not Collective
9610acecf5bSBarry Smith 
96292f119d6SBarry Smith     Output Parameters:
96392f119d6SBarry Smith +    basic - doing basic debugging
96492f119d6SBarry Smith .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
96579dccf82SBarry Smith -    initializenan - initializes memory with NaN
9660acecf5bSBarry Smith 
9670acecf5bSBarry Smith    Level: intermediate
9680acecf5bSBarry Smith 
96992f119d6SBarry Smith    Notes:
97079dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
9710acecf5bSBarry Smith 
972db781477SPatrick Sanan .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()`
9730acecf5bSBarry Smith @*/
9749371c9d4SSatish Balay PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) {
9750acecf5bSBarry Smith   PetscFunctionBegin;
97679dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
97779dccf82SBarry Smith   if (eachcall) *eachcall = TRdebugLevel;
9782d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9790acecf5bSBarry Smith   PetscFunctionReturn(0);
9800acecf5bSBarry Smith }
981608c71bfSMatthew G. Knepley 
982608c71bfSMatthew G. Knepley /*@
983608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
984608c71bfSMatthew G. Knepley 
985608c71bfSMatthew G. Knepley   Not Collective
986608c71bfSMatthew G. Knepley 
987608c71bfSMatthew G. Knepley   Input Parameter:
988608c71bfSMatthew G. Knepley . flg - PETSC_TRUE to log the requested memory size
989608c71bfSMatthew G. Knepley 
990608c71bfSMatthew G. Knepley   Options Database:
991608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
992608c71bfSMatthew G. Knepley 
993608c71bfSMatthew G. Knepley   Level: developer
994608c71bfSMatthew G. Knepley 
995db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()`
996608c71bfSMatthew G. Knepley @*/
9979371c9d4SSatish Balay PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) {
998608c71bfSMatthew G. Knepley   PetscFunctionBegin;
999608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
1000608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1001608c71bfSMatthew G. Knepley }
1002608c71bfSMatthew G. Knepley 
1003608c71bfSMatthew G. Knepley /*@
1004608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1005608c71bfSMatthew G. Knepley 
1006608c71bfSMatthew G. Knepley   Not Collective
1007608c71bfSMatthew G. Knepley 
1008608c71bfSMatthew G. Knepley   Output Parameter:
1009608c71bfSMatthew G. Knepley . flg - PETSC_TRUE if we log the requested memory size
1010608c71bfSMatthew G. Knepley 
1011608c71bfSMatthew G. Knepley   Level: developer
1012608c71bfSMatthew G. Knepley 
1013db781477SPatrick Sanan .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()`
1014608c71bfSMatthew G. Knepley @*/
10159371c9d4SSatish Balay PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) {
1016608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1017608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
1018608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1019608c71bfSMatthew G. Knepley }
1020