xref: /petsc/src/sys/memory/mtr.c (revision 2cba81977152c2730de22674f6dfc36b0b199900)
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 */
5c6db04a5SJed Brown #include <petscsys.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 {
23e5c89e4eSSatish Balay   size_t          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 */
43e5c89e4eSSatish Balay typedef union {
44e5c89e4eSSatish Balay   TRSPACE sp;
4525b53cc9SJed Brown   char    v[HEADER_BYTES];
46e5c89e4eSSatish Balay } TrSPACE;
47e5c89e4eSSatish Balay 
48e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50
49e5c89e4eSSatish Balay static size_t    TRallocated          = 0;
50e5c89e4eSSatish Balay static int       TRfrags              = 0;
51f0ba7cfcSLisandro Dalcin static TRSPACE   *TRhead              = NULL;
52e5c89e4eSSatish Balay static int       TRid                 = 0;
53ace3abfcSBarry Smith static PetscBool TRdebugLevel         = PETSC_FALSE;
542d4ee042Sprj- static PetscBool TRdebugIinitializenan= PETSC_FALSE;
55e5c89e4eSSatish Balay static size_t    TRMaxMem             = 0;
56e3ed9ee7SBarry Smith static int       NumTRMaxMems         = 0;
57e3ed9ee7SBarry Smith static size_t    TRMaxMems[MAXTRMAXMEMS];
58e3ed9ee7SBarry Smith static int       TRMaxMemsEvents[MAXTRMAXMEMS];
59e5c89e4eSSatish Balay /*
6092f119d6SBarry Smith       Arrays to log information on mallocs for PetscMallocView()
61e5c89e4eSSatish Balay */
62f0ba7cfcSLisandro Dalcin static int        PetscLogMallocMax       = 10000;
63f0ba7cfcSLisandro Dalcin static int        PetscLogMalloc          = -1;
64574034a9SJed Brown static size_t     PetscLogMallocThreshold = 0;
65e5c89e4eSSatish Balay static size_t     *PetscLogMallocLength;
66efca3c55SSatish Balay static const char **PetscLogMallocFile,**PetscLogMallocFunction;
67b022a5c1SBarry Smith 
68e5c89e4eSSatish Balay /*@C
6992f119d6SBarry Smith    PetscMallocValidate - Test the memory for corruption.  This can be called at any time between PetscInitialize() and PetscFinalize()
70e5c89e4eSSatish Balay 
7192f119d6SBarry Smith    Input Parameters:
72e5c89e4eSSatish Balay +  line - line number where call originated.
73e5c89e4eSSatish Balay .  function - name of function calling
74efca3c55SSatish Balay -  file - file where function is
75e5c89e4eSSatish Balay 
76e5c89e4eSSatish Balay    Return value:
77e5c89e4eSSatish Balay    The number of errors detected.
78e5c89e4eSSatish Balay 
7992f119d6SBarry Smith    Options Database:.
8092f119d6SBarry Smith +  -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0
8192f119d6SBarry Smith -  -malloc_debug - turns this feature on anytime
8292f119d6SBarry Smith 
83e5c89e4eSSatish Balay    Output Effect:
84e5c89e4eSSatish Balay    Error messages are written to stdout.
85e5c89e4eSSatish Balay 
86e5c89e4eSSatish Balay    Level: advanced
87e5c89e4eSSatish Balay 
88e5c89e4eSSatish Balay    Notes:
8979dccf82SBarry 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)
9038548759SBarry Smith 
9192f119d6SBarry Smith     You should generally use CHKMEMQ as a short cut for calling this  routine.
92e5c89e4eSSatish Balay 
93e5c89e4eSSatish Balay     The Fortran calling sequence is simply PetscMallocValidate(ierr)
94e5c89e4eSSatish Balay 
95e5c89e4eSSatish Balay    No output is generated if there are no problems detected.
96e5c89e4eSSatish Balay 
9792f119d6SBarry Smith    Developers Note:
9892f119d6SBarry Smith      Uses the flg TRdebugLevel (set as the first argument to PetscMallocSetDebug()) to determine if it should run
9992f119d6SBarry Smith 
100e5c89e4eSSatish Balay .seealso: CHKMEMQ
101e5c89e4eSSatish Balay 
102e5c89e4eSSatish Balay @*/
103efca3c55SSatish Balay PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
104e5c89e4eSSatish Balay {
1056c093d5bSvictor   TRSPACE      *head,*lasthead;
106e5c89e4eSSatish Balay   char         *a;
1070700a824SBarry Smith   PetscClassId *nend;
108e5c89e4eSSatish Balay 
10938548759SBarry Smith   if (!TRdebugLevel) return 0;
110e5c89e4eSSatish Balay   PetscFunctionBegin;
1116c093d5bSvictor   head = TRhead; lasthead = NULL;
112*2cba8197SMatthew G. Knepley   if (head && head->prev) {
113*2cba8197SMatthew G. Knepley     (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
114*2cba8197SMatthew G. Knepley     (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n",head,head->prev);
115*2cba8197SMatthew G. Knepley   }
116e5c89e4eSSatish Balay   while (head) {
1170700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
118efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s\n",function,line,file);
119e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
120e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
121efca3c55SSatish Balay       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
122e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
123e5c89e4eSSatish Balay     }
124e5c89e4eSSatish Balay     a    = (char*)(((TrSPACE*)head) + 1);
1250700a824SBarry Smith     nend = (PetscClassId*)(a + head->size);
1260700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
127efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
128e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
129e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
130e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
131e5c89e4eSSatish Balay       } else {
132e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
133efca3c55SSatish Balay         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
134e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
135e5c89e4eSSatish Balay       }
136e5c89e4eSSatish Balay     }
137*2cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
138*2cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
139*2cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n",head->prev,lasthead);
140*2cba8197SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
141*2cba8197SMatthew G. Knepley     }
142*2cba8197SMatthew G. Knepley     if (head->next && head != head->next->prev) {
143*2cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
144*2cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("Next memory header %p has invalid back pointer %p, should be %p\n",head->next,head->next->prev,head);
145*2cba8197SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
146*2cba8197SMatthew G. Knepley     }
1476c093d5bSvictor     lasthead = head;
148e5c89e4eSSatish Balay     head     = head->next;
149e5c89e4eSSatish Balay   }
150e5c89e4eSSatish Balay   PetscFunctionReturn(0);
151e5c89e4eSSatish Balay }
152e5c89e4eSSatish Balay 
153e5c89e4eSSatish Balay /*
154e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
155e5c89e4eSSatish Balay 
156e5c89e4eSSatish Balay     Input Parameters:
157e5c89e4eSSatish Balay +   a   - number of bytes to allocate
158e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
159efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
160e5c89e4eSSatish Balay 
161e5c89e4eSSatish Balay     Returns:
16292f119d6SBarry Smith     double aligned pointer to requested storage, or null if not  available.
163e5c89e4eSSatish Balay  */
164071fcb05SBarry Smith PetscErrorCode  PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
165e5c89e4eSSatish Balay {
166e5c89e4eSSatish Balay   TRSPACE        *head;
167e5c89e4eSSatish Balay   char           *inew;
168e5c89e4eSSatish Balay   size_t         nsize;
169e5c89e4eSSatish Balay   PetscErrorCode ierr;
170e5c89e4eSSatish Balay 
171e5c89e4eSSatish Balay   PetscFunctionBegin;
172f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
173f0ba7cfcSLisandro Dalcin   if (!a) { *result = NULL; PetscFunctionReturn(0); }
174f0ba7cfcSLisandro Dalcin 
175efca3c55SSatish Balay   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
176e5c89e4eSSatish Balay 
17725b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
178071fcb05SBarry Smith   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
179e3ed9ee7SBarry Smith 
180e5c89e4eSSatish Balay   head  = (TRSPACE*)inew;
181e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
182e5c89e4eSSatish Balay 
183e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
184e5c89e4eSSatish Balay   head->next   = TRhead;
185e5c89e4eSSatish Balay   TRhead       = head;
186f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
187e5c89e4eSSatish Balay   head->size   = nsize;
188e5c89e4eSSatish Balay   head->id     = TRid;
189e5c89e4eSSatish Balay   head->lineno = lineno;
190e5c89e4eSSatish Balay 
191e5c89e4eSSatish Balay   head->filename                 = filename;
192e5c89e4eSSatish Balay   head->functionname             = function;
1930700a824SBarry Smith   head->classid                  = CLASSID_VALUE;
1940700a824SBarry Smith   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
195e5c89e4eSSatish Balay 
196e5c89e4eSSatish Balay   TRallocated += nsize;
197a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
198e3ed9ee7SBarry Smith   if (PetscLogMemory) {
199e3ed9ee7SBarry Smith     PetscInt i;
200e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
201e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
202e3ed9ee7SBarry Smith     }
203e3ed9ee7SBarry Smith   }
204e5c89e4eSSatish Balay   TRfrags++;
205e5c89e4eSSatish Balay 
2068bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
20776386721SLisandro Dalcin   if (PetscStackActive()) {
2085c25fcd7SBarry Smith     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
2092c9581d2SBarry Smith     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2102c9581d2SBarry Smith     head->stack.line[head->stack.currentsize-2] = lineno;
2119de0f6ecSBarry Smith   } else {
2129de0f6ecSBarry Smith     head->stack.currentsize = 0;
21376386721SLisandro Dalcin   }
21492f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2152d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
21692f119d6SBarry Smith     size_t     i, n = a/sizeof(PetscReal);
21792f119d6SBarry Smith     PetscReal *s = (PetscReal*) inew;
21892f119d6SBarry Smith     /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
21992f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
220df282883SBarry Smith     int        nas = 0x7F800002;
22192f119d6SBarry Smith #else
22292f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22392f119d6SBarry Smith #endif
22492f119d6SBarry Smith     for (i=0; i<n; i++) {
22592f119d6SBarry Smith       memcpy(s+i,&nas,sizeof(PetscReal));
22692f119d6SBarry Smith     }
22792f119d6SBarry Smith   }
22892f119d6SBarry Smith #endif
229e5c89e4eSSatish Balay #endif
230e5c89e4eSSatish Balay 
231e5c89e4eSSatish Balay   /*
23292f119d6SBarry Smith          Allow logging of all mallocs made.
23392f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
234e5c89e4eSSatish Balay   */
235574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
236e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
237e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
238e32f2f54SBarry Smith       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
239a297a907SKarl Rupp 
240a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
241e32f2f54SBarry Smith       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
242a297a907SKarl Rupp 
243a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
244e32f2f54SBarry Smith       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
245e5c89e4eSSatish Balay     }
246e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
247e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
248e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
249e5c89e4eSSatish Balay   }
250e5c89e4eSSatish Balay   *result = (void*)inew;
251e5c89e4eSSatish Balay   PetscFunctionReturn(0);
252e5c89e4eSSatish Balay }
253e5c89e4eSSatish Balay 
254e5c89e4eSSatish Balay /*
255e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
256e5c89e4eSSatish Balay 
257e5c89e4eSSatish Balay    Input Parameters:
258e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
259e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
260e5c89e4eSSatish Balay .   file  - file name where used.  Use __FILE__ for this
261e5c89e4eSSatish Balay  */
262efca3c55SSatish Balay PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
263e5c89e4eSSatish Balay {
264e5c89e4eSSatish Balay   char           *a = (char*)aa;
265e5c89e4eSSatish Balay   TRSPACE        *head;
266e5c89e4eSSatish Balay   char           *ahead;
267e5c89e4eSSatish Balay   PetscErrorCode ierr;
2680700a824SBarry Smith   PetscClassId   *nend;
269e5c89e4eSSatish Balay 
270e5c89e4eSSatish Balay   PetscFunctionBegin;
271e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
27249d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
273e5c89e4eSSatish Balay 
274efca3c55SSatish Balay   ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr);
275e5c89e4eSSatish Balay 
276e5c89e4eSSatish Balay   ahead = a;
277e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
278e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
279e5c89e4eSSatish Balay 
2800700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
281efca3c55SSatish Balay     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
282e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
283e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
284e5c89e4eSSatish Balay   }
2850700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2860700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
287e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
288efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
289e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
290e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
291efca3c55SSatish Balay         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
292e5c89e4eSSatish Balay       } else {
293efca3c55SSatish Balay         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
294e5c89e4eSSatish Balay       }
295e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
296e5c89e4eSSatish Balay     } else {
297e5c89e4eSSatish Balay       /* Damaged tail */
298efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
299e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
300efca3c55SSatish Balay       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
301e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
302e5c89e4eSSatish Balay     }
303e5c89e4eSSatish Balay   }
304e5c89e4eSSatish Balay   /* Mark the location freed */
305e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
306e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
307e5c89e4eSSatish Balay   if (line > 0 && line < 50000) {
308e5c89e4eSSatish Balay     head->lineno       = line;
309e5c89e4eSSatish Balay     head->filename     = file;
310e5c89e4eSSatish Balay     head->functionname = function;
311e5c89e4eSSatish Balay   } else {
312e5c89e4eSSatish Balay     head->lineno = -head->lineno;
313e5c89e4eSSatish Balay   }
314e3ed9ee7SBarry Smith   if (TRallocated < head->size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
315e5c89e4eSSatish Balay   TRallocated -= head->size;
316e5c89e4eSSatish Balay   TRfrags--;
317e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
318e5c89e4eSSatish Balay   else TRhead = head->next;
319e5c89e4eSSatish Balay 
320e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
321efca3c55SSatish Balay   ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr);
322e5c89e4eSSatish Balay   PetscFunctionReturn(0);
323e5c89e4eSSatish Balay }
324e5c89e4eSSatish Balay 
3253221ece2SMatthew G. Knepley /*
3263221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3273221ece2SMatthew G. Knepley 
3283221ece2SMatthew G. Knepley   Input Parameters:
3293221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3303221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3313221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
33292f119d6SBarry Smith - result - original memory
3333221ece2SMatthew G. Knepley 
3343221ece2SMatthew G. Knepley   Output Parameter:
3353221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3363221ece2SMatthew G. Knepley 
3373221ece2SMatthew G. Knepley   Level: developer
3383221ece2SMatthew G. Knepley 
3393221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3403221ece2SMatthew G. Knepley */
3413221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3423221ece2SMatthew G. Knepley {
3433221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3443221ece2SMatthew G. Knepley   TRSPACE        *head;
3453221ece2SMatthew G. Knepley   char           *ahead, *inew;
3463221ece2SMatthew G. Knepley   PetscClassId   *nend;
3473221ece2SMatthew G. Knepley   size_t         nsize;
3483221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3493221ece2SMatthew G. Knepley 
3503221ece2SMatthew G. Knepley   PetscFunctionBegin;
35192f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
352c22f1541SToby Isaac   if (!len) {
353c22f1541SToby Isaac     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
354c22f1541SToby Isaac     *result = NULL;
355c22f1541SToby Isaac     PetscFunctionReturn(0);
356c22f1541SToby Isaac   }
35792f119d6SBarry Smith   /* If the orginal space was NULL just use the regular malloc() */
358f590eff4SLisandro Dalcin   if (!*result) {
359071fcb05SBarry Smith     ierr = PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);CHKERRQ(ierr);
360f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
361f590eff4SLisandro Dalcin   }
3623221ece2SMatthew G. Knepley 
36338548759SBarry Smith   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
3643221ece2SMatthew G. Knepley 
3653221ece2SMatthew G. Knepley   ahead = a;
3663221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3673221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3683221ece2SMatthew G. Knepley   inew  = a;
3693221ece2SMatthew G. Knepley 
3703221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3713221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3723221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3733221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3743221ece2SMatthew G. Knepley   }
3753221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3763221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3773221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3783221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3793221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3803221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3813221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3823221ece2SMatthew G. Knepley       } else {
3833221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
3843221ece2SMatthew G. Knepley       }
3853221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3863221ece2SMatthew G. Knepley     } else {
3873221ece2SMatthew G. Knepley       /* Damaged tail */
3883221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3893221ece2SMatthew 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);
3903221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3913221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
3923221ece2SMatthew G. Knepley     }
3933221ece2SMatthew G. Knepley   }
3943221ece2SMatthew G. Knepley 
39592f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
3963221ece2SMatthew G. Knepley   TRallocated -= head->size;
3973221ece2SMatthew G. Knepley   TRfrags--;
3983221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
3993221ece2SMatthew G. Knepley   else TRhead = head->next;
4003221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4013221ece2SMatthew G. Knepley 
4023221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
4033221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
4043221ece2SMatthew G. Knepley 
4053221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
4063221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4073221ece2SMatthew G. Knepley 
4083221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4093221ece2SMatthew G. Knepley   head->next   = TRhead;
4103221ece2SMatthew G. Knepley   TRhead       = head;
4113221ece2SMatthew G. Knepley   head->prev   = NULL;
4123221ece2SMatthew G. Knepley   head->size   = nsize;
4133221ece2SMatthew G. Knepley   head->id     = TRid;
4143221ece2SMatthew G. Knepley   head->lineno = lineno;
4153221ece2SMatthew G. Knepley 
4163221ece2SMatthew G. Knepley   head->filename                 = filename;
4173221ece2SMatthew G. Knepley   head->functionname             = function;
4183221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4193221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4203221ece2SMatthew G. Knepley 
4213221ece2SMatthew G. Knepley   TRallocated += nsize;
4223221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
423e3ed9ee7SBarry Smith   if (PetscLogMemory) {
424e3ed9ee7SBarry Smith     PetscInt i;
425e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
426e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
427e3ed9ee7SBarry Smith     }
428e3ed9ee7SBarry Smith   }
4293221ece2SMatthew G. Knepley   TRfrags++;
4303221ece2SMatthew G. Knepley 
4313221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4323221ece2SMatthew G. Knepley   if (PetscStackActive()) {
4333221ece2SMatthew G. Knepley     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
4343221ece2SMatthew G. Knepley     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4353221ece2SMatthew G. Knepley     head->stack.line[head->stack.currentsize-2] = lineno;
4363221ece2SMatthew G. Knepley   } else {
4373221ece2SMatthew G. Knepley     head->stack.currentsize = 0;
4383221ece2SMatthew G. Knepley   }
4393221ece2SMatthew G. Knepley #endif
4403221ece2SMatthew G. Knepley 
4413221ece2SMatthew G. Knepley   /*
44292f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
44392f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4443221ece2SMatthew G. Knepley   */
4453221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4463221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4473221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
4483221ece2SMatthew G. Knepley       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4493221ece2SMatthew G. Knepley 
4503221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4513221ece2SMatthew G. Knepley       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4523221ece2SMatthew G. Knepley 
4533221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4543221ece2SMatthew G. Knepley       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4553221ece2SMatthew G. Knepley     }
4563221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4573221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4583221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4593221ece2SMatthew G. Knepley   }
4603221ece2SMatthew G. Knepley   *result = (void*)inew;
4613221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4623221ece2SMatthew G. Knepley }
4633221ece2SMatthew G. Knepley 
464fe7fb379SMatthew Knepley /*@C
46592f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
466e5c89e4eSSatish Balay 
467e5c89e4eSSatish Balay     Collective on PetscViewer
468e5c89e4eSSatish Balay 
469e5c89e4eSSatish Balay     Input Parameter:
470e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
471e5c89e4eSSatish Balay -    message - string printed before values
472e5c89e4eSSatish Balay 
4730841954dSBarry Smith     Options Database:
47492f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
4750841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4760841954dSBarry Smith 
477e5c89e4eSSatish Balay     Level: intermediate
478e5c89e4eSSatish Balay 
47992f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
480e5c89e4eSSatish Balay  @*/
4810841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
482e5c89e4eSSatish Balay {
4830841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4840841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
485e5c89e4eSSatish Balay   PetscErrorCode ierr;
486e5c89e4eSSatish Balay   MPI_Comm       comm;
487e5c89e4eSSatish Balay 
488e5c89e4eSSatish Balay   PetscFunctionBegin;
489e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
490e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
4910841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
492e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
493e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
494e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
495e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
496e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
497e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4980841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4990841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5000841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5010841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr);
5020841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5030841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5040841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5050841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5060841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5070841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5080841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5090841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax);CHKERRQ(ierr);
5100841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5110841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5120841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5130841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
514e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5150841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5160841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5170841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5180841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax);CHKERRQ(ierr);
5190841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5200841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5210841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5220841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
523e5c89e4eSSatish Balay   } else if (resident && allocated) {
5240841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5250841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5260841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5270841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5280841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5290841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5300841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5310841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5320841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
533e5c89e4eSSatish Balay   } else if (allocated) {
5340841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5350841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5360841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5370841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5380841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5390841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
540e5c89e4eSSatish Balay   } else {
54192f119d6SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
542e5c89e4eSSatish Balay   }
543e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
544e5c89e4eSSatish Balay   PetscFunctionReturn(0);
545e5c89e4eSSatish Balay }
546e5c89e4eSSatish Balay 
54746eb3923SBarry Smith /*@
548e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
549e5c89e4eSSatish Balay 
550e5c89e4eSSatish Balay     Not Collective
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay     Output Parameters:
553e5c89e4eSSatish Balay .   space - number of bytes currently allocated
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay     Level: intermediate
556e5c89e4eSSatish Balay 
557540e20f2SPierre Jolivet .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
558e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
559e5c89e4eSSatish Balay  @*/
5607087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
561e5c89e4eSSatish Balay {
562e5c89e4eSSatish Balay   PetscFunctionBegin;
563e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
564e5c89e4eSSatish Balay   PetscFunctionReturn(0);
565e5c89e4eSSatish Balay }
566e5c89e4eSSatish Balay 
567dc37d89fSBarry Smith /*@
568e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
569e5c89e4eSSatish Balay         during this run.
570e5c89e4eSSatish Balay 
571e5c89e4eSSatish Balay     Not Collective
572e5c89e4eSSatish Balay 
573e5c89e4eSSatish Balay     Output Parameters:
574e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay     Level: intermediate
577e5c89e4eSSatish Balay 
57892f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
579e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
580e5c89e4eSSatish Balay  @*/
5817087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
582e5c89e4eSSatish Balay {
583e5c89e4eSSatish Balay   PetscFunctionBegin;
584e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
585e5c89e4eSSatish Balay   PetscFunctionReturn(0);
586e5c89e4eSSatish Balay }
587e5c89e4eSSatish Balay 
588e3ed9ee7SBarry Smith /*@
589e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
590e3ed9ee7SBarry Smith 
591e3ed9ee7SBarry Smith     Not Collective
592e3ed9ee7SBarry Smith 
593e3ed9ee7SBarry Smith     Input Parameter:
594e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
595e3ed9ee7SBarry Smith 
596e3ed9ee7SBarry Smith     Level: developer
597e3ed9ee7SBarry Smith 
59892f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
599e3ed9ee7SBarry Smith           PetscMallocPopMaximumUsage()
600e3ed9ee7SBarry Smith  @*/
601e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPushMaximumUsage(int event)
602e3ed9ee7SBarry Smith {
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 
62392f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
624e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
625e3ed9ee7SBarry Smith  @*/
626e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
627e3ed9ee7SBarry Smith {
628e3ed9ee7SBarry Smith   PetscFunctionBegin;
629e3ed9ee7SBarry Smith   *mu = 0;
630e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
631e3ed9ee7SBarry Smith   if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
632e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
633e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
634e3ed9ee7SBarry Smith }
635e3ed9ee7SBarry Smith 
636a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
637a64a8e02SBarry Smith /*@C
638a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
639a64a8e02SBarry Smith 
640a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
641a64a8e02SBarry Smith 
642a64a8e02SBarry Smith    Input Parameter:
643a64a8e02SBarry Smith .    ptr - the memory location
644a64a8e02SBarry Smith 
645fd292e60Sprj-    Output Parameter:
646a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
647a64a8e02SBarry Smith 
648a64a8e02SBarry Smith    Level: intermediate
649a64a8e02SBarry Smith 
65092f119d6SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView()
651a64a8e02SBarry Smith @*/
652a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
653a64a8e02SBarry Smith {
654a64a8e02SBarry Smith   TRSPACE *head;
655a64a8e02SBarry Smith 
656a64a8e02SBarry Smith   PetscFunctionBegin;
657a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
658a64a8e02SBarry Smith   *stack = &head->stack;
659a64a8e02SBarry Smith   PetscFunctionReturn(0);
660a64a8e02SBarry Smith }
66176386721SLisandro Dalcin #else
66276386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
66376386721SLisandro Dalcin {
66476386721SLisandro Dalcin   PetscFunctionBegin;
665f0ba7cfcSLisandro Dalcin   *stack = NULL;
66676386721SLisandro Dalcin   PetscFunctionReturn(0);
66776386721SLisandro Dalcin }
668a64a8e02SBarry Smith #endif
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:
68292f119d6SBarry 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:
69192f119d6SBarry Smith      Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
692e5c89e4eSSatish Balay 
69392f119d6SBarry Smith      When called in PetscFinalize() dumps only the allocations that have not been properly freed
69492f119d6SBarry Smith 
69592f119d6SBarry Smith      PetscMallocView() prints a list of all memory ever allocated
69692f119d6SBarry Smith 
69792f119d6SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet()
698e5c89e4eSSatish Balay @*/
6997087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
700e5c89e4eSSatish Balay {
701e5c89e4eSSatish Balay   TRSPACE        *head;
702e3ed9ee7SBarry Smith   size_t         libAlloc = 0;
703e5c89e4eSSatish Balay   PetscErrorCode ierr;
704e5c89e4eSSatish Balay   PetscMPIInt    rank;
705e5c89e4eSSatish Balay 
706e5c89e4eSSatish Balay   PetscFunctionBegin;
707e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
708da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
709e5c89e4eSSatish Balay   head = TRhead;
710e5c89e4eSSatish Balay   while (head) {
7115486ca60SMatthew G. Knepley     libAlloc += head->size;
7125486ca60SMatthew G. Knepley     head = head->next;
7135486ca60SMatthew G. Knepley   }
7145486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
7155486ca60SMatthew G. Knepley   head = TRhead;
7165486ca60SMatthew G. Knepley   while (head) {
7175486ca60SMatthew G. Knepley     PetscBool isLib;
7185486ca60SMatthew G. Knepley 
7195486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
7205486ca60SMatthew G. Knepley     if (!isLib) {
721efca3c55SSatish Balay       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
7228bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
723e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
724e5c89e4eSSatish Balay #endif
7255486ca60SMatthew G. Knepley     }
726e5c89e4eSSatish Balay     head = head->next;
727e5c89e4eSSatish Balay   }
728e5c89e4eSSatish Balay   PetscFunctionReturn(0);
729e5c89e4eSSatish Balay }
730e5c89e4eSSatish Balay 
731dc37d89fSBarry Smith /*@
73292f119d6SBarry Smith     PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
733574034a9SJed Brown 
734574034a9SJed Brown     Not Collective
735574034a9SJed Brown 
736574034a9SJed Brown     Input Arguments:
737574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
738574034a9SJed Brown 
739574034a9SJed Brown     Options Database Key:
74092f119d6SBarry Smith +  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
7418b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7428b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
743574034a9SJed Brown 
744574034a9SJed Brown     Level: advanced
745574034a9SJed Brown 
74692f119d6SBarry Smith     Notes: Must be called after PetscMallocSetDebug()
74792f119d6SBarry Smith 
74892f119d6SBarry Smith     Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
74992f119d6SBarry Smith 
75092f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet()
751574034a9SJed Brown @*/
75292f119d6SBarry Smith PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
753574034a9SJed Brown {
754574034a9SJed Brown   PetscErrorCode ierr;
755574034a9SJed Brown 
756574034a9SJed Brown   PetscFunctionBegin;
75792f119d6SBarry Smith   PetscLogMalloc = 0;
75892f119d6SBarry Smith   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
759574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
760574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
761574034a9SJed Brown   PetscFunctionReturn(0);
762574034a9SJed Brown }
763574034a9SJed Brown 
764dc37d89fSBarry Smith /*@
76592f119d6SBarry Smith     PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
76618a2528dSJed Brown 
76718a2528dSJed Brown     Not Collective
76818a2528dSJed Brown 
76918a2528dSJed Brown     Output Arguments
77018a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
77118a2528dSJed Brown 
77218a2528dSJed Brown     Options Database Key:
77392f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView()
77418a2528dSJed Brown 
77518a2528dSJed Brown     Level: advanced
77618a2528dSJed Brown 
77792f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView()
77818a2528dSJed Brown @*/
77992f119d6SBarry Smith PetscErrorCode PetscMallocViewGet(PetscBool *logging)
78018a2528dSJed Brown {
78118a2528dSJed Brown 
78218a2528dSJed Brown   PetscFunctionBegin;
78318a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
78418a2528dSJed Brown   PetscFunctionReturn(0);
78518a2528dSJed Brown }
78618a2528dSJed Brown 
787e5c89e4eSSatish Balay /*@C
78892f119d6SBarry Smith     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
78921b680ceSJed Brown        PetscMemoryGetMaximumUsage()
790e5c89e4eSSatish Balay 
79192f119d6SBarry Smith     Not Collective
792e5c89e4eSSatish Balay 
793e5c89e4eSSatish Balay     Input Parameter:
7940298fd71SBarry Smith .   fp - file pointer; or NULL
795e5c89e4eSSatish Balay 
796e5c89e4eSSatish Balay     Options Database Key:
79792f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
798e5c89e4eSSatish Balay 
799e5c89e4eSSatish Balay     Level: advanced
800e5c89e4eSSatish Balay 
801e5c89e4eSSatish Balay    Fortran Note:
80292f119d6SBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
803e5c89e4eSSatish Balay    The fp defaults to stdout.
804e5c89e4eSSatish Balay 
80592f119d6SBarry Smith    Notes:
80692f119d6SBarry Smith      PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
80792f119d6SBarry Smith 
80892f119d6SBarry Smith      PetscMemoryView() gives a brief summary of current memory usage
80992f119d6SBarry Smith 
81092f119d6SBarry Smith .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
811e5c89e4eSSatish Balay @*/
81292f119d6SBarry Smith PetscErrorCode  PetscMallocView(FILE *fp)
813e5c89e4eSSatish Balay {
81492f119d6SBarry Smith   PetscInt       i,j,n,*perm;
815e5c89e4eSSatish Balay   size_t         *shortlength;
816f56c2debSBarry Smith   int            *shortcount,err;
81792f119d6SBarry Smith   PetscMPIInt    rank;
818ace3abfcSBarry Smith   PetscBool      match;
819e5c89e4eSSatish Balay   const char     **shortfunction;
820e5c89e4eSSatish Balay   PetscLogDouble rss;
821e5c89e4eSSatish Balay   PetscErrorCode ierr;
822e5c89e4eSSatish Balay 
823e5c89e4eSSatish Balay   PetscFunctionBegin;
824e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
825f56c2debSBarry Smith   err = fflush(fp);
826e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
827f56c2debSBarry Smith 
82879dccf82SBarry Smith   if (PetscLogMalloc < 0) SETERRQ(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()");
829768aa557SSatish Balay 
830da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
831f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
832e5c89e4eSSatish Balay   if (rss) {
83392f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
834e5c89e4eSSatish Balay   } else {
83592f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
836e5c89e4eSSatish Balay   }
837e32f2f54SBarry Smith   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
838e32f2f54SBarry Smith   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
839e32f2f54SBarry Smith   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
84097b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
841e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
842e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
843e5c89e4eSSatish Balay       if (match) {
844e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
84559ffdab8SBarry Smith         shortcount[j]++;
846e5c89e4eSSatish Balay         goto foundit;
847e5c89e4eSSatish Balay       }
848e5c89e4eSSatish Balay     }
849e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
850e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
85159ffdab8SBarry Smith     shortcount[n]    = 1;
852e5c89e4eSSatish Balay     n++;
853e5c89e4eSSatish Balay foundit:;
854e5c89e4eSSatish Balay   }
855e5c89e4eSSatish Balay 
856e32f2f54SBarry Smith   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
857e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
858e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
859e5c89e4eSSatish Balay 
86092f119d6SBarry Smith   (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
861e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
86292f119d6SBarry Smith     (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
863e5c89e4eSSatish Balay   }
864e5c89e4eSSatish Balay   free(perm);
865e5c89e4eSSatish Balay   free(shortlength);
86659ffdab8SBarry Smith   free(shortcount);
867e5c89e4eSSatish Balay   free((char**)shortfunction);
868f56c2debSBarry Smith   err = fflush(fp);
869e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
870e5c89e4eSSatish Balay   PetscFunctionReturn(0);
871e5c89e4eSSatish Balay }
872e5c89e4eSSatish Balay 
873e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
874e5c89e4eSSatish Balay 
875dc37d89fSBarry Smith /*@
87692f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
877e5c89e4eSSatish Balay 
878e5c89e4eSSatish Balay     Not Collective
879e5c89e4eSSatish Balay 
880e5c89e4eSSatish Balay     Input Parameter:
88192f119d6SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
8822d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
883e5c89e4eSSatish Balay 
88492f119d6SBarry Smith     Options Database:
88579dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
88692f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
88779dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
88892f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
88979dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
89079dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
891e5c89e4eSSatish Balay 
89292f119d6SBarry Smith    Level: developer
89392f119d6SBarry Smith 
89492f119d6SBarry Smith     Notes: This is called in PetscInitialize() and should not be called elsewhere
89592f119d6SBarry Smith 
89692f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
897e5c89e4eSSatish Balay @*/
89892f119d6SBarry Smith PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
899e5c89e4eSSatish Balay {
90092f119d6SBarry Smith   PetscErrorCode ierr;
90192f119d6SBarry Smith 
902e5c89e4eSSatish Balay   PetscFunctionBegin;
90392f119d6SBarry Smith   if (PetscTrMalloc == PetscTrMallocDefault) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call this routine more than once, it can only be called in PetscInitialize()");
90492f119d6SBarry Smith   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);CHKERRQ(ierr);
90592f119d6SBarry Smith 
90692f119d6SBarry Smith   TRallocated         = 0;
90792f119d6SBarry Smith   TRfrags             = 0;
90892f119d6SBarry Smith   TRhead              = NULL;
90992f119d6SBarry Smith   TRid                = 0;
91092f119d6SBarry Smith   TRdebugLevel        = eachcall;
91192f119d6SBarry Smith   TRMaxMem            = 0;
91292f119d6SBarry Smith   PetscLogMallocMax   = 10000;
91392f119d6SBarry Smith   PetscLogMalloc      = -1;
9142d4ee042Sprj-   TRdebugIinitializenan = initializenan;
915e5c89e4eSSatish Balay   PetscFunctionReturn(0);
916e5c89e4eSSatish Balay }
9170acecf5bSBarry Smith 
918dc37d89fSBarry Smith /*@
91992f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9200acecf5bSBarry Smith 
9210acecf5bSBarry Smith     Not Collective
9220acecf5bSBarry Smith 
92392f119d6SBarry Smith     Output Parameters:
92492f119d6SBarry Smith +    basic - doing basic debugging
92592f119d6SBarry Smith .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
92679dccf82SBarry Smith -    initializenan - initializes memory with NaN
9270acecf5bSBarry Smith 
9280acecf5bSBarry Smith    Level: intermediate
9290acecf5bSBarry Smith 
93092f119d6SBarry Smith    Notes:
93179dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
9320acecf5bSBarry Smith 
93392f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
9340acecf5bSBarry Smith @*/
93592f119d6SBarry Smith PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
9360acecf5bSBarry Smith {
9370acecf5bSBarry Smith   PetscFunctionBegin;
93879dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
93979dccf82SBarry Smith   if (eachcall) *eachcall           = TRdebugLevel;
9402d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9410acecf5bSBarry Smith   PetscFunctionReturn(0);
9420acecf5bSBarry Smith }
943