xref: /petsc/src/sys/memory/mtr.c (revision f0b7f91a62ffb6ce9197d97f11c1a2bde724cef8)
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 {
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 */
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;
55608c71bfSMatthew G. Knepley static PetscBool TRrequestedSize      = PETSC_FALSE;
56e5c89e4eSSatish Balay static size_t    TRMaxMem             = 0;
57e3ed9ee7SBarry Smith static int       NumTRMaxMems         = 0;
58e3ed9ee7SBarry Smith static size_t    TRMaxMems[MAXTRMAXMEMS];
59e3ed9ee7SBarry Smith static int       TRMaxMemsEvents[MAXTRMAXMEMS];
60e5c89e4eSSatish Balay /*
6192f119d6SBarry Smith       Arrays to log information on mallocs for PetscMallocView()
62e5c89e4eSSatish Balay */
63f0ba7cfcSLisandro Dalcin static int        PetscLogMallocMax       = 10000;
64f0ba7cfcSLisandro Dalcin static int        PetscLogMalloc          = -1;
65574034a9SJed Brown static size_t     PetscLogMallocThreshold = 0;
66e5c89e4eSSatish Balay static size_t     *PetscLogMallocLength;
67efca3c55SSatish Balay static const char **PetscLogMallocFile,**PetscLogMallocFunction;
68608c71bfSMatthew G. Knepley static int        PetscLogMallocTrace          = -1;
69608c71bfSMatthew G. Knepley static size_t     PetscLogMallocTraceThreshold = 0;
70608c71bfSMatthew G. Knepley static PetscViewer PetscLogMallocTraceViewer   = NULL;
71b022a5c1SBarry Smith 
72e5c89e4eSSatish Balay /*@C
7392f119d6SBarry Smith    PetscMallocValidate - Test the memory for corruption.  This can be called at any time between PetscInitialize() and PetscFinalize()
74e5c89e4eSSatish Balay 
7592f119d6SBarry Smith    Input Parameters:
76e5c89e4eSSatish Balay +  line - line number where call originated.
77e5c89e4eSSatish Balay .  function - name of function calling
78efca3c55SSatish Balay -  file - file where function is
79e5c89e4eSSatish Balay 
80e5c89e4eSSatish Balay    Return value:
81e5c89e4eSSatish Balay    The number of errors detected.
82e5c89e4eSSatish Balay 
8392f119d6SBarry Smith    Options Database:.
8492f119d6SBarry Smith +  -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0
8592f119d6SBarry Smith -  -malloc_debug - turns this feature on anytime
8692f119d6SBarry Smith 
87e5c89e4eSSatish Balay    Output Effect:
88e5c89e4eSSatish Balay    Error messages are written to stdout.
89e5c89e4eSSatish Balay 
90e5c89e4eSSatish Balay    Level: advanced
91e5c89e4eSSatish Balay 
92e5c89e4eSSatish Balay    Notes:
9379dccf82SBarry 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)
9438548759SBarry Smith 
9592f119d6SBarry Smith     You should generally use CHKMEMQ as a short cut for calling this  routine.
96e5c89e4eSSatish Balay 
97e5c89e4eSSatish Balay     The Fortran calling sequence is simply PetscMallocValidate(ierr)
98e5c89e4eSSatish Balay 
99e5c89e4eSSatish Balay    No output is generated if there are no problems detected.
100e5c89e4eSSatish Balay 
10192f119d6SBarry Smith    Developers Note:
10292f119d6SBarry Smith      Uses the flg TRdebugLevel (set as the first argument to PetscMallocSetDebug()) to determine if it should run
10392f119d6SBarry Smith 
104e5c89e4eSSatish Balay .seealso: CHKMEMQ
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay @*/
107efca3c55SSatish Balay PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
108e5c89e4eSSatish Balay {
1096c093d5bSvictor   TRSPACE      *head,*lasthead;
110e5c89e4eSSatish Balay   char         *a;
1110700a824SBarry Smith   PetscClassId *nend;
112e5c89e4eSSatish Balay 
11338548759SBarry Smith   if (!TRdebugLevel) return 0;
114e5c89e4eSSatish Balay   PetscFunctionBegin;
1156c093d5bSvictor   head = TRhead; lasthead = NULL;
1162cba8197SMatthew G. Knepley   if (head && head->prev) {
1172cba8197SMatthew G. Knepley     (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
1182cba8197SMatthew G. Knepley     (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n",head,head->prev);
1192cba8197SMatthew G. Knepley   }
120e5c89e4eSSatish Balay   while (head) {
1210700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
122efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s\n",function,line,file);
123e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
124e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
125efca3c55SSatish Balay       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
126e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
127e5c89e4eSSatish Balay     }
128e5c89e4eSSatish Balay     a    = (char*)(((TrSPACE*)head) + 1);
1290700a824SBarry Smith     nend = (PetscClassId*)(a + head->size);
1300700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
131efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
132e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
133e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
134e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
135e5c89e4eSSatish Balay       } else {
136e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
137efca3c55SSatish Balay         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
138e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
139e5c89e4eSSatish Balay       }
140e5c89e4eSSatish Balay     }
1412cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
1422cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
1432cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n",head->prev,lasthead);
1442cba8197SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
1452cba8197SMatthew G. Knepley     }
1462cba8197SMatthew G. Knepley     if (head->next && head != head->next->prev) {
1472cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
1482cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("Next memory header %p has invalid back pointer %p, should be %p\n",head->next,head->next->prev,head);
1492cba8197SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
1502cba8197SMatthew G. Knepley     }
1516c093d5bSvictor     lasthead = head;
152e5c89e4eSSatish Balay     head     = head->next;
153e5c89e4eSSatish Balay   }
154e5c89e4eSSatish Balay   PetscFunctionReturn(0);
155e5c89e4eSSatish Balay }
156e5c89e4eSSatish Balay 
157e5c89e4eSSatish Balay /*
158e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
159e5c89e4eSSatish Balay 
160e5c89e4eSSatish Balay     Input Parameters:
161e5c89e4eSSatish Balay +   a   - number of bytes to allocate
162e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
163efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
164e5c89e4eSSatish Balay 
165e5c89e4eSSatish Balay     Returns:
16692f119d6SBarry Smith     double aligned pointer to requested storage, or null if not  available.
167e5c89e4eSSatish Balay  */
168071fcb05SBarry Smith PetscErrorCode  PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
169e5c89e4eSSatish Balay {
170e5c89e4eSSatish Balay   TRSPACE        *head;
171e5c89e4eSSatish Balay   char           *inew;
172e5c89e4eSSatish Balay   size_t         nsize;
173e5c89e4eSSatish Balay   PetscErrorCode ierr;
174e5c89e4eSSatish Balay 
175e5c89e4eSSatish Balay   PetscFunctionBegin;
176f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
177f0ba7cfcSLisandro Dalcin   if (!a) { *result = NULL; PetscFunctionReturn(0); }
178f0ba7cfcSLisandro Dalcin 
179efca3c55SSatish Balay   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
180e5c89e4eSSatish Balay 
18125b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
182071fcb05SBarry Smith   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
183e3ed9ee7SBarry Smith 
184e5c89e4eSSatish Balay   head  = (TRSPACE*)inew;
185e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
186e5c89e4eSSatish Balay 
187e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
188e5c89e4eSSatish Balay   head->next   = TRhead;
189e5c89e4eSSatish Balay   TRhead       = head;
190f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
191e5c89e4eSSatish Balay   head->size   = nsize;
192608c71bfSMatthew G. Knepley   head->rsize  = a;
193e5c89e4eSSatish Balay   head->id     = TRid;
194e5c89e4eSSatish Balay   head->lineno = lineno;
195e5c89e4eSSatish Balay 
196e5c89e4eSSatish Balay   head->filename                 = filename;
197e5c89e4eSSatish Balay   head->functionname             = function;
1980700a824SBarry Smith   head->classid                  = CLASSID_VALUE;
1990700a824SBarry Smith   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
200e5c89e4eSSatish Balay 
201608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
202a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
203e3ed9ee7SBarry Smith   if (PetscLogMemory) {
204e3ed9ee7SBarry Smith     PetscInt i;
205e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
206e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
207e3ed9ee7SBarry Smith     }
208e3ed9ee7SBarry Smith   }
209e5c89e4eSSatish Balay   TRfrags++;
210e5c89e4eSSatish Balay 
2118bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
21276386721SLisandro Dalcin   if (PetscStackActive()) {
2135c25fcd7SBarry Smith     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
2142c9581d2SBarry Smith     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2152c9581d2SBarry Smith     head->stack.line[head->stack.currentsize-2] = lineno;
2169de0f6ecSBarry Smith   } else {
2179de0f6ecSBarry Smith     head->stack.currentsize = 0;
21876386721SLisandro Dalcin   }
21992f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2202d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
22192f119d6SBarry Smith     size_t     i, n = a/sizeof(PetscReal);
22292f119d6SBarry Smith     PetscReal *s = (PetscReal*) inew;
22392f119d6SBarry Smith     /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
22492f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
225df282883SBarry Smith     int        nas = 0x7F800002;
22692f119d6SBarry Smith #else
22792f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22892f119d6SBarry Smith #endif
22992f119d6SBarry Smith     for (i=0; i<n; i++) {
23092f119d6SBarry Smith       memcpy(s+i,&nas,sizeof(PetscReal));
23192f119d6SBarry Smith     }
23292f119d6SBarry Smith   }
23392f119d6SBarry Smith #endif
234e5c89e4eSSatish Balay #endif
235e5c89e4eSSatish Balay 
236e5c89e4eSSatish Balay   /*
23792f119d6SBarry Smith          Allow logging of all mallocs made.
23892f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
239e5c89e4eSSatish Balay   */
240574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
241e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
242e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
243e32f2f54SBarry Smith       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
244a297a907SKarl Rupp 
245a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
246e32f2f54SBarry Smith       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
247a297a907SKarl Rupp 
248a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
249e32f2f54SBarry Smith       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
250e5c89e4eSSatish Balay     }
251e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
252e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
253e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
254e5c89e4eSSatish Balay   }
255608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) {
256608c71bfSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(PetscLogMallocTraceViewer,"Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null");CHKERRQ(ierr);
257608c71bfSMatthew G. Knepley   }
258e5c89e4eSSatish Balay   *result = (void*)inew;
259e5c89e4eSSatish Balay   PetscFunctionReturn(0);
260e5c89e4eSSatish Balay }
261e5c89e4eSSatish Balay 
262e5c89e4eSSatish Balay /*
263e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
264e5c89e4eSSatish Balay 
265e5c89e4eSSatish Balay    Input Parameters:
266e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
267e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
268608c71bfSMatthew G. Knepley .   filename  - file name where used.  Use __FILE__ for this
269e5c89e4eSSatish Balay  */
270608c71bfSMatthew G. Knepley PetscErrorCode  PetscTrFreeDefault(void *aa,int lineno,const char function[],const char filename[])
271e5c89e4eSSatish Balay {
272e5c89e4eSSatish Balay   char           *a = (char*)aa;
273e5c89e4eSSatish Balay   TRSPACE        *head;
274e5c89e4eSSatish Balay   char           *ahead;
275608c71bfSMatthew G. Knepley   size_t         asize;
276e5c89e4eSSatish Balay   PetscErrorCode ierr;
2770700a824SBarry Smith   PetscClassId   *nend;
278e5c89e4eSSatish Balay 
279e5c89e4eSSatish Balay   PetscFunctionBegin;
280e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
28149d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
282e5c89e4eSSatish Balay 
283608c71bfSMatthew G. Knepley   ierr = PetscMallocValidate(lineno,function,filename);CHKERRQ(ierr);
284e5c89e4eSSatish Balay 
285e5c89e4eSSatish Balay   ahead = a;
286e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
287e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
288e5c89e4eSSatish Balay 
2890700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
290608c71bfSMatthew G. Knepley     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
291e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
292e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
293e5c89e4eSSatish Balay   }
2940700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2950700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
296e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
297608c71bfSMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
298e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
299e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
300efca3c55SSatish Balay         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
301e5c89e4eSSatish Balay       } else {
302efca3c55SSatish Balay         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
303e5c89e4eSSatish Balay       }
304e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
305e5c89e4eSSatish Balay     } else {
306e5c89e4eSSatish Balay       /* Damaged tail */
307608c71bfSMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,lineno,filename);
308e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
309efca3c55SSatish Balay       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
310e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
311e5c89e4eSSatish Balay     }
312e5c89e4eSSatish Balay   }
313608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
314608c71bfSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null");CHKERRQ(ierr);
315608c71bfSMatthew G. Knepley   }
316e5c89e4eSSatish Balay   /* Mark the location freed */
317e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
318e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
319608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
320608c71bfSMatthew G. Knepley     head->lineno       = lineno;
321608c71bfSMatthew G. Knepley     head->filename     = filename;
322e5c89e4eSSatish Balay     head->functionname = function;
323e5c89e4eSSatish Balay   } else {
324e5c89e4eSSatish Balay     head->lineno = -head->lineno;
325e5c89e4eSSatish Balay   }
326608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
327608c71bfSMatthew G. Knepley   if (TRallocated < asize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
328608c71bfSMatthew G. Knepley   TRallocated -= asize;
329e5c89e4eSSatish Balay   TRfrags--;
330e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
331e5c89e4eSSatish Balay   else TRhead = head->next;
332e5c89e4eSSatish Balay 
333e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
334608c71bfSMatthew G. Knepley   ierr = PetscFreeAlign(a,lineno,function,filename);CHKERRQ(ierr);
335e5c89e4eSSatish Balay   PetscFunctionReturn(0);
336e5c89e4eSSatish Balay }
337e5c89e4eSSatish Balay 
3383221ece2SMatthew G. Knepley /*
3393221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3403221ece2SMatthew G. Knepley 
3413221ece2SMatthew G. Knepley   Input Parameters:
3423221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3433221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3443221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
34592f119d6SBarry Smith - result - original memory
3463221ece2SMatthew G. Knepley 
3473221ece2SMatthew G. Knepley   Output Parameter:
3483221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3493221ece2SMatthew G. Knepley 
3503221ece2SMatthew G. Knepley   Level: developer
3513221ece2SMatthew G. Knepley 
3523221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3533221ece2SMatthew G. Knepley */
3543221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3553221ece2SMatthew G. Knepley {
3563221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3573221ece2SMatthew G. Knepley   TRSPACE        *head;
3583221ece2SMatthew G. Knepley   char           *ahead, *inew;
3593221ece2SMatthew G. Knepley   PetscClassId   *nend;
3603221ece2SMatthew G. Knepley   size_t         nsize;
3613221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3623221ece2SMatthew G. Knepley 
3633221ece2SMatthew G. Knepley   PetscFunctionBegin;
36492f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
365c22f1541SToby Isaac   if (!len) {
366c22f1541SToby Isaac     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
367c22f1541SToby Isaac     *result = NULL;
368c22f1541SToby Isaac     PetscFunctionReturn(0);
369c22f1541SToby Isaac   }
37092f119d6SBarry Smith   /* If the orginal space was NULL just use the regular malloc() */
371f590eff4SLisandro Dalcin   if (!*result) {
372071fcb05SBarry Smith     ierr = PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);CHKERRQ(ierr);
373f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
374f590eff4SLisandro Dalcin   }
3753221ece2SMatthew G. Knepley 
37638548759SBarry Smith   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
3773221ece2SMatthew G. Knepley 
3783221ece2SMatthew G. Knepley   ahead = a;
3793221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3803221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3813221ece2SMatthew G. Knepley   inew  = a;
3823221ece2SMatthew G. Knepley 
3833221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3843221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3853221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3863221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3873221ece2SMatthew G. Knepley   }
3883221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3893221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3903221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3913221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3923221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3933221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3943221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3953221ece2SMatthew G. Knepley       } else {
3963221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
3973221ece2SMatthew G. Knepley       }
3983221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3993221ece2SMatthew G. Knepley     } else {
4003221ece2SMatthew G. Knepley       /* Damaged tail */
4013221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
4023221ece2SMatthew 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);
4033221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
4043221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
4053221ece2SMatthew G. Knepley     }
4063221ece2SMatthew G. Knepley   }
4073221ece2SMatthew G. Knepley 
40892f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
409608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
4103221ece2SMatthew G. Knepley   TRfrags--;
4113221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4123221ece2SMatthew G. Knepley   else TRhead = head->next;
4133221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4143221ece2SMatthew G. Knepley 
4153221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
4163221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
4173221ece2SMatthew G. Knepley 
4183221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
4193221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4203221ece2SMatthew G. Knepley 
4213221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4223221ece2SMatthew G. Knepley   head->next   = TRhead;
4233221ece2SMatthew G. Knepley   TRhead       = head;
4243221ece2SMatthew G. Knepley   head->prev   = NULL;
4253221ece2SMatthew G. Knepley   head->size   = nsize;
426608c71bfSMatthew G. Knepley   head->rsize  = len;
4273221ece2SMatthew G. Knepley   head->id     = TRid;
4283221ece2SMatthew G. Knepley   head->lineno = lineno;
4293221ece2SMatthew G. Knepley 
4303221ece2SMatthew G. Knepley   head->filename                 = filename;
4313221ece2SMatthew G. Knepley   head->functionname             = function;
4323221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4333221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4343221ece2SMatthew G. Knepley 
435608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4363221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
437e3ed9ee7SBarry Smith   if (PetscLogMemory) {
438e3ed9ee7SBarry Smith     PetscInt i;
439e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
440e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
441e3ed9ee7SBarry Smith     }
442e3ed9ee7SBarry Smith   }
4433221ece2SMatthew G. Knepley   TRfrags++;
4443221ece2SMatthew G. Knepley 
4453221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4463221ece2SMatthew G. Knepley   if (PetscStackActive()) {
4473221ece2SMatthew G. Knepley     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
4483221ece2SMatthew G. Knepley     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4493221ece2SMatthew G. Knepley     head->stack.line[head->stack.currentsize-2] = lineno;
4503221ece2SMatthew G. Knepley   } else {
4513221ece2SMatthew G. Knepley     head->stack.currentsize = 0;
4523221ece2SMatthew G. Knepley   }
4533221ece2SMatthew G. Knepley #endif
4543221ece2SMatthew G. Knepley 
4553221ece2SMatthew G. Knepley   /*
45692f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
45792f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4583221ece2SMatthew G. Knepley   */
4593221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4603221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4613221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
4623221ece2SMatthew G. Knepley       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4633221ece2SMatthew G. Knepley 
4643221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4653221ece2SMatthew G. Knepley       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4663221ece2SMatthew G. Knepley 
4673221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4683221ece2SMatthew G. Knepley       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4693221ece2SMatthew G. Knepley     }
4703221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4713221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4723221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4733221ece2SMatthew G. Knepley   }
4743221ece2SMatthew G. Knepley   *result = (void*)inew;
4753221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4763221ece2SMatthew G. Knepley }
4773221ece2SMatthew G. Knepley 
478fe7fb379SMatthew Knepley /*@C
47992f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
480e5c89e4eSSatish Balay 
481e5c89e4eSSatish Balay     Collective on PetscViewer
482e5c89e4eSSatish Balay 
483e5c89e4eSSatish Balay     Input Parameter:
484e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
485e5c89e4eSSatish Balay -    message - string printed before values
486e5c89e4eSSatish Balay 
4870841954dSBarry Smith     Options Database:
48892f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
4890841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4900841954dSBarry Smith 
491e5c89e4eSSatish Balay     Level: intermediate
492e5c89e4eSSatish Balay 
49392f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
494e5c89e4eSSatish Balay  @*/
4950841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
496e5c89e4eSSatish Balay {
4970841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4980841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
499e5c89e4eSSatish Balay   PetscErrorCode ierr;
500e5c89e4eSSatish Balay   MPI_Comm       comm;
501e5c89e4eSSatish Balay 
502e5c89e4eSSatish Balay   PetscFunctionBegin;
503e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
504e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
5050841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
506e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
507e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
508e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
509e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
510e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
511e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
5120841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5130841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5140841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5150841954dSBarry 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);
5160841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5170841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5180841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5190841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5200841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5210841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5220841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5230841954dSBarry 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);
5240841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5250841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5260841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5270841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
528e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5290841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5300841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5310841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5320841954dSBarry 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);
5330841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5340841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5350841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5360841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
537e5c89e4eSSatish Balay   } else if (resident && allocated) {
5380841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5390841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5400841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5410841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5420841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5430841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5440841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5450841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5460841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
547e5c89e4eSSatish Balay   } else if (allocated) {
5480841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5490841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5500841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5510841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5520841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5530841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
554e5c89e4eSSatish Balay   } else {
55592f119d6SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
556e5c89e4eSSatish Balay   }
557e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
558e5c89e4eSSatish Balay   PetscFunctionReturn(0);
559e5c89e4eSSatish Balay }
560e5c89e4eSSatish Balay 
56146eb3923SBarry Smith /*@
562e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
563e5c89e4eSSatish Balay 
564e5c89e4eSSatish Balay     Not Collective
565e5c89e4eSSatish Balay 
566e5c89e4eSSatish Balay     Output Parameters:
567e5c89e4eSSatish Balay .   space - number of bytes currently allocated
568e5c89e4eSSatish Balay 
569e5c89e4eSSatish Balay     Level: intermediate
570e5c89e4eSSatish Balay 
571540e20f2SPierre Jolivet .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
572e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
573e5c89e4eSSatish Balay  @*/
5747087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
575e5c89e4eSSatish Balay {
576e5c89e4eSSatish Balay   PetscFunctionBegin;
577e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
578e5c89e4eSSatish Balay   PetscFunctionReturn(0);
579e5c89e4eSSatish Balay }
580e5c89e4eSSatish Balay 
581dc37d89fSBarry Smith /*@
582e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
583e5c89e4eSSatish Balay         during this run.
584e5c89e4eSSatish Balay 
585e5c89e4eSSatish Balay     Not Collective
586e5c89e4eSSatish Balay 
587e5c89e4eSSatish Balay     Output Parameters:
588e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
589e5c89e4eSSatish Balay 
590e5c89e4eSSatish Balay     Level: intermediate
591e5c89e4eSSatish Balay 
59292f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
593e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
594e5c89e4eSSatish Balay  @*/
5957087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
596e5c89e4eSSatish Balay {
597e5c89e4eSSatish Balay   PetscFunctionBegin;
598e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
599e5c89e4eSSatish Balay   PetscFunctionReturn(0);
600e5c89e4eSSatish Balay }
601e5c89e4eSSatish Balay 
602e3ed9ee7SBarry Smith /*@
603e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
604e3ed9ee7SBarry Smith 
605e3ed9ee7SBarry Smith     Not Collective
606e3ed9ee7SBarry Smith 
607e3ed9ee7SBarry Smith     Input Parameter:
608e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
609e3ed9ee7SBarry Smith 
610e3ed9ee7SBarry Smith     Level: developer
611e3ed9ee7SBarry Smith 
61292f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
613e3ed9ee7SBarry Smith           PetscMallocPopMaximumUsage()
614e3ed9ee7SBarry Smith  @*/
615e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPushMaximumUsage(int event)
616e3ed9ee7SBarry Smith {
617e3ed9ee7SBarry Smith   PetscFunctionBegin;
618e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
619e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
620e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems-1] = event;
621e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
622e3ed9ee7SBarry Smith }
623e3ed9ee7SBarry Smith 
624e3ed9ee7SBarry Smith /*@
625e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
626e3ed9ee7SBarry Smith 
627e3ed9ee7SBarry Smith     Not Collective
628e3ed9ee7SBarry Smith 
629e3ed9ee7SBarry Smith     Input Parameter:
630e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
631e3ed9ee7SBarry Smith 
632e3ed9ee7SBarry Smith     Output Parameter:
633e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
634e3ed9ee7SBarry Smith 
635e3ed9ee7SBarry Smith     Level: developer
636e3ed9ee7SBarry Smith 
63792f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
638e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
639e3ed9ee7SBarry Smith  @*/
640e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
641e3ed9ee7SBarry Smith {
642e3ed9ee7SBarry Smith   PetscFunctionBegin;
643e3ed9ee7SBarry Smith   *mu = 0;
644e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
645e3ed9ee7SBarry Smith   if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
646e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
647e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
648e3ed9ee7SBarry Smith }
649e3ed9ee7SBarry Smith 
650a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
651a64a8e02SBarry Smith /*@C
652a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
653a64a8e02SBarry Smith 
654a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
655a64a8e02SBarry Smith 
656a64a8e02SBarry Smith    Input Parameter:
657a64a8e02SBarry Smith .    ptr - the memory location
658a64a8e02SBarry Smith 
659fd292e60Sprj-    Output Parameter:
660a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
661a64a8e02SBarry Smith 
662a64a8e02SBarry Smith    Level: intermediate
663a64a8e02SBarry Smith 
66492f119d6SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView()
665a64a8e02SBarry Smith @*/
666a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
667a64a8e02SBarry Smith {
668a64a8e02SBarry Smith   TRSPACE *head;
669a64a8e02SBarry Smith 
670a64a8e02SBarry Smith   PetscFunctionBegin;
671a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
672a64a8e02SBarry Smith   *stack = &head->stack;
673a64a8e02SBarry Smith   PetscFunctionReturn(0);
674a64a8e02SBarry Smith }
67576386721SLisandro Dalcin #else
67676386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
67776386721SLisandro Dalcin {
67876386721SLisandro Dalcin   PetscFunctionBegin;
679f0ba7cfcSLisandro Dalcin   *stack = NULL;
68076386721SLisandro Dalcin   PetscFunctionReturn(0);
68176386721SLisandro Dalcin }
682a64a8e02SBarry Smith #endif
683a64a8e02SBarry Smith 
684e5c89e4eSSatish Balay /*@C
68592f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
686e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
687e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
688e5c89e4eSSatish Balay    allocated.
689e5c89e4eSSatish Balay 
69092f119d6SBarry Smith    Not Collective
691e5c89e4eSSatish Balay 
692e5c89e4eSSatish Balay    Input Parameter:
693e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
694e5c89e4eSSatish Balay 
695e5c89e4eSSatish Balay    Options Database Key:
69692f119d6SBarry Smith .  -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
697e5c89e4eSSatish Balay 
698e5c89e4eSSatish Balay    Level: intermediate
699e5c89e4eSSatish Balay 
700e5c89e4eSSatish Balay    Fortran Note:
701e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
702e5c89e4eSSatish Balay    The fp defaults to stdout.
703e5c89e4eSSatish Balay 
70495452b02SPatrick Sanan    Notes:
70592f119d6SBarry Smith      Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
706e5c89e4eSSatish Balay 
70792f119d6SBarry Smith      When called in PetscFinalize() dumps only the allocations that have not been properly freed
70892f119d6SBarry Smith 
70992f119d6SBarry Smith      PetscMallocView() prints a list of all memory ever allocated
71092f119d6SBarry Smith 
711*f0b7f91aSBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
712e5c89e4eSSatish Balay @*/
7137087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
714e5c89e4eSSatish Balay {
715e5c89e4eSSatish Balay   TRSPACE        *head;
716e3ed9ee7SBarry Smith   size_t         libAlloc = 0;
717e5c89e4eSSatish Balay   PetscErrorCode ierr;
718e5c89e4eSSatish Balay   PetscMPIInt    rank;
719e5c89e4eSSatish Balay 
720e5c89e4eSSatish Balay   PetscFunctionBegin;
721e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
722da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
723e5c89e4eSSatish Balay   head = TRhead;
724e5c89e4eSSatish Balay   while (head) {
725608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7265486ca60SMatthew G. Knepley     head = head->next;
7275486ca60SMatthew G. Knepley   }
7285486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
7295486ca60SMatthew G. Knepley   head = TRhead;
7305486ca60SMatthew G. Knepley   while (head) {
7315486ca60SMatthew G. Knepley     PetscBool isLib;
7325486ca60SMatthew G. Knepley 
7335486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
7345486ca60SMatthew G. Knepley     if (!isLib) {
735608c71bfSMatthew G. Knepley       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->lineno,head->filename);
7368bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
737e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
738e5c89e4eSSatish Balay #endif
7395486ca60SMatthew G. Knepley     }
740e5c89e4eSSatish Balay     head = head->next;
741e5c89e4eSSatish Balay   }
742e5c89e4eSSatish Balay   PetscFunctionReturn(0);
743e5c89e4eSSatish Balay }
744e5c89e4eSSatish Balay 
745dc37d89fSBarry Smith /*@
74692f119d6SBarry Smith     PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
747574034a9SJed Brown 
748574034a9SJed Brown     Not Collective
749574034a9SJed Brown 
750574034a9SJed Brown     Input Arguments:
751574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
752574034a9SJed Brown 
753574034a9SJed Brown     Options Database Key:
75492f119d6SBarry Smith +  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
7558b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7568b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
757574034a9SJed Brown 
758574034a9SJed Brown     Level: advanced
759574034a9SJed Brown 
76092f119d6SBarry Smith     Notes: Must be called after PetscMallocSetDebug()
76192f119d6SBarry Smith 
76292f119d6SBarry Smith     Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
76392f119d6SBarry Smith 
764*f0b7f91aSBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
765574034a9SJed Brown @*/
76692f119d6SBarry Smith PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
767574034a9SJed Brown {
768574034a9SJed Brown   PetscErrorCode ierr;
769574034a9SJed Brown 
770574034a9SJed Brown   PetscFunctionBegin;
77192f119d6SBarry Smith   PetscLogMalloc = 0;
77292f119d6SBarry Smith   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
773574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
774574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
775574034a9SJed Brown   PetscFunctionReturn(0);
776574034a9SJed Brown }
777574034a9SJed Brown 
778dc37d89fSBarry Smith /*@
77992f119d6SBarry Smith     PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
78018a2528dSJed Brown 
78118a2528dSJed Brown     Not Collective
78218a2528dSJed Brown 
78318a2528dSJed Brown     Output Arguments
78418a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
78518a2528dSJed Brown 
78618a2528dSJed Brown     Options Database Key:
78792f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView()
78818a2528dSJed Brown 
78918a2528dSJed Brown     Level: advanced
79018a2528dSJed Brown 
791608c71bfSMatthew G. Knepley .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
79218a2528dSJed Brown @*/
79392f119d6SBarry Smith PetscErrorCode PetscMallocViewGet(PetscBool *logging)
79418a2528dSJed Brown {
79518a2528dSJed Brown 
79618a2528dSJed Brown   PetscFunctionBegin;
79718a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
79818a2528dSJed Brown   PetscFunctionReturn(0);
79918a2528dSJed Brown }
80018a2528dSJed Brown 
801608c71bfSMatthew G. Knepley /*@
802608c71bfSMatthew G. Knepley   PetscMallocTraceSet - Trace all calls to PetscMalloc()
803608c71bfSMatthew G. Knepley 
804608c71bfSMatthew G. Knepley   Not Collective
805608c71bfSMatthew G. Knepley 
806608c71bfSMatthew G. Knepley   Input Arguments:
807608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout
808608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
809608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
810608c71bfSMatthew G. Knepley 
811608c71bfSMatthew G. Knepley   Note:
812608c71bfSMatthew G. Knepley   The viewer should not be collective.
813608c71bfSMatthew G. Knepley 
814608c71bfSMatthew G. Knepley   Level: advanced
815608c71bfSMatthew G. Knepley 
816608c71bfSMatthew G. Knepley .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
817608c71bfSMatthew G. Knepley @*/
818608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
819608c71bfSMatthew G. Knepley {
820608c71bfSMatthew G. Knepley   PetscErrorCode ierr;
821608c71bfSMatthew G. Knepley 
822608c71bfSMatthew G. Knepley   PetscFunctionBegin;
823608c71bfSMatthew G. Knepley   if (!active) {PetscLogMallocTrace = -1; PetscFunctionReturn(0);}
824608c71bfSMatthew G. Knepley   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
825608c71bfSMatthew G. Knepley   PetscLogMallocTrace = 0;
826608c71bfSMatthew G. Knepley   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
827608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
828608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t) logmin;
829608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
830608c71bfSMatthew G. Knepley }
831608c71bfSMatthew G. Knepley 
832608c71bfSMatthew G. Knepley /*@
833608c71bfSMatthew G. Knepley   PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
834608c71bfSMatthew G. Knepley 
835608c71bfSMatthew G. Knepley   Not Collective
836608c71bfSMatthew G. Knepley 
837608c71bfSMatthew G. Knepley   Output Argument:
838608c71bfSMatthew G. Knepley . logging - PETSC_TRUE if logging is active
839608c71bfSMatthew G. Knepley 
840608c71bfSMatthew G. Knepley   Options Database Key:
841608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView()
842608c71bfSMatthew G. Knepley 
843608c71bfSMatthew G. Knepley   Level: advanced
844608c71bfSMatthew G. Knepley 
845608c71bfSMatthew G. Knepley .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
846608c71bfSMatthew G. Knepley @*/
847608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
848608c71bfSMatthew G. Knepley {
849608c71bfSMatthew G. Knepley 
850608c71bfSMatthew G. Knepley   PetscFunctionBegin;
851608c71bfSMatthew G. Knepley   *logging = (PetscBool) (PetscLogMallocTrace >= 0);
852608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
853608c71bfSMatthew G. Knepley }
854608c71bfSMatthew G. Knepley 
855e5c89e4eSSatish Balay /*@C
85692f119d6SBarry Smith     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
85721b680ceSJed Brown        PetscMemoryGetMaximumUsage()
858e5c89e4eSSatish Balay 
85992f119d6SBarry Smith     Not Collective
860e5c89e4eSSatish Balay 
861e5c89e4eSSatish Balay     Input Parameter:
8620298fd71SBarry Smith .   fp - file pointer; or NULL
863e5c89e4eSSatish Balay 
864e5c89e4eSSatish Balay     Options Database Key:
86592f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
866e5c89e4eSSatish Balay 
867e5c89e4eSSatish Balay     Level: advanced
868e5c89e4eSSatish Balay 
869e5c89e4eSSatish Balay    Fortran Note:
87092f119d6SBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
871e5c89e4eSSatish Balay    The fp defaults to stdout.
872e5c89e4eSSatish Balay 
87392f119d6SBarry Smith    Notes:
87492f119d6SBarry Smith      PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
87592f119d6SBarry Smith 
87692f119d6SBarry Smith      PetscMemoryView() gives a brief summary of current memory usage
87792f119d6SBarry Smith 
87892f119d6SBarry Smith .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
879e5c89e4eSSatish Balay @*/
88092f119d6SBarry Smith PetscErrorCode  PetscMallocView(FILE *fp)
881e5c89e4eSSatish Balay {
88292f119d6SBarry Smith   PetscInt       i,j,n,*perm;
883e5c89e4eSSatish Balay   size_t         *shortlength;
884f56c2debSBarry Smith   int            *shortcount,err;
88592f119d6SBarry Smith   PetscMPIInt    rank;
886ace3abfcSBarry Smith   PetscBool      match;
887e5c89e4eSSatish Balay   const char     **shortfunction;
888e5c89e4eSSatish Balay   PetscLogDouble rss;
889e5c89e4eSSatish Balay   PetscErrorCode ierr;
890e5c89e4eSSatish Balay 
891e5c89e4eSSatish Balay   PetscFunctionBegin;
892e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
893f56c2debSBarry Smith   err = fflush(fp);
894e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
895f56c2debSBarry Smith 
89679dccf82SBarry 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()");
897768aa557SSatish Balay 
898da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
899f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
900e5c89e4eSSatish Balay   if (rss) {
90192f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
902e5c89e4eSSatish Balay   } else {
90392f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
904e5c89e4eSSatish Balay   }
905e32f2f54SBarry Smith   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
906e32f2f54SBarry Smith   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
907e32f2f54SBarry Smith   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
90897b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
909e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
910e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
911e5c89e4eSSatish Balay       if (match) {
912e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
91359ffdab8SBarry Smith         shortcount[j]++;
914e5c89e4eSSatish Balay         goto foundit;
915e5c89e4eSSatish Balay       }
916e5c89e4eSSatish Balay     }
917e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
918e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
91959ffdab8SBarry Smith     shortcount[n]    = 1;
920e5c89e4eSSatish Balay     n++;
921e5c89e4eSSatish Balay foundit:;
922e5c89e4eSSatish Balay   }
923e5c89e4eSSatish Balay 
924e32f2f54SBarry Smith   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
925e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
926e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
927e5c89e4eSSatish Balay 
92892f119d6SBarry Smith   (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
929e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
93092f119d6SBarry Smith     (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
931e5c89e4eSSatish Balay   }
932e5c89e4eSSatish Balay   free(perm);
933e5c89e4eSSatish Balay   free(shortlength);
93459ffdab8SBarry Smith   free(shortcount);
935e5c89e4eSSatish Balay   free((char**)shortfunction);
936f56c2debSBarry Smith   err = fflush(fp);
937e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
938e5c89e4eSSatish Balay   PetscFunctionReturn(0);
939e5c89e4eSSatish Balay }
940e5c89e4eSSatish Balay 
941e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
942e5c89e4eSSatish Balay 
943dc37d89fSBarry Smith /*@
94492f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
945e5c89e4eSSatish Balay 
946e5c89e4eSSatish Balay     Not Collective
947e5c89e4eSSatish Balay 
948e5c89e4eSSatish Balay     Input Parameter:
94992f119d6SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
9502d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
951e5c89e4eSSatish Balay 
95292f119d6SBarry Smith     Options Database:
95379dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
95492f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
95579dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
95692f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
95779dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
95879dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
959e5c89e4eSSatish Balay 
96092f119d6SBarry Smith    Level: developer
96192f119d6SBarry Smith 
96292f119d6SBarry Smith     Notes: This is called in PetscInitialize() and should not be called elsewhere
96392f119d6SBarry Smith 
96492f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
965e5c89e4eSSatish Balay @*/
96692f119d6SBarry Smith PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
967e5c89e4eSSatish Balay {
96892f119d6SBarry Smith   PetscErrorCode ierr;
96992f119d6SBarry Smith 
970e5c89e4eSSatish Balay   PetscFunctionBegin;
97192f119d6SBarry 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()");
97292f119d6SBarry Smith   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);CHKERRQ(ierr);
97392f119d6SBarry Smith 
97492f119d6SBarry Smith   TRallocated         = 0;
97592f119d6SBarry Smith   TRfrags             = 0;
97692f119d6SBarry Smith   TRhead              = NULL;
97792f119d6SBarry Smith   TRid                = 0;
97892f119d6SBarry Smith   TRdebugLevel        = eachcall;
97992f119d6SBarry Smith   TRMaxMem            = 0;
98092f119d6SBarry Smith   PetscLogMallocMax   = 10000;
98192f119d6SBarry Smith   PetscLogMalloc      = -1;
9822d4ee042Sprj-   TRdebugIinitializenan = initializenan;
983e5c89e4eSSatish Balay   PetscFunctionReturn(0);
984e5c89e4eSSatish Balay }
9850acecf5bSBarry Smith 
986dc37d89fSBarry Smith /*@
98792f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9880acecf5bSBarry Smith 
9890acecf5bSBarry Smith     Not Collective
9900acecf5bSBarry Smith 
99192f119d6SBarry Smith     Output Parameters:
99292f119d6SBarry Smith +    basic - doing basic debugging
99392f119d6SBarry Smith .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
99479dccf82SBarry Smith -    initializenan - initializes memory with NaN
9950acecf5bSBarry Smith 
9960acecf5bSBarry Smith    Level: intermediate
9970acecf5bSBarry Smith 
99892f119d6SBarry Smith    Notes:
99979dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
10000acecf5bSBarry Smith 
100192f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
10020acecf5bSBarry Smith @*/
100392f119d6SBarry Smith PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
10040acecf5bSBarry Smith {
10050acecf5bSBarry Smith   PetscFunctionBegin;
100679dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
100779dccf82SBarry Smith   if (eachcall) *eachcall           = TRdebugLevel;
10082d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
10090acecf5bSBarry Smith   PetscFunctionReturn(0);
10100acecf5bSBarry Smith }
1011608c71bfSMatthew G. Knepley 
1012608c71bfSMatthew G. Knepley /*@
1013608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
1014608c71bfSMatthew G. Knepley 
1015608c71bfSMatthew G. Knepley   Not Collective
1016608c71bfSMatthew G. Knepley 
1017608c71bfSMatthew G. Knepley   Input Parameter:
1018608c71bfSMatthew G. Knepley . flg - PETSC_TRUE to log the requested memory size
1019608c71bfSMatthew G. Knepley 
1020608c71bfSMatthew G. Knepley   Options Database:
1021608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1022608c71bfSMatthew G. Knepley 
1023608c71bfSMatthew G. Knepley   Level: developer
1024608c71bfSMatthew G. Knepley 
1025608c71bfSMatthew G. Knepley .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
1026608c71bfSMatthew G. Knepley @*/
1027608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1028608c71bfSMatthew G. Knepley {
1029608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1030608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
1031608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1032608c71bfSMatthew G. Knepley }
1033608c71bfSMatthew G. Knepley 
1034608c71bfSMatthew G. Knepley /*@
1035608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1036608c71bfSMatthew G. Knepley 
1037608c71bfSMatthew G. Knepley   Not Collective
1038608c71bfSMatthew G. Knepley 
1039608c71bfSMatthew G. Knepley   Output Parameter:
1040608c71bfSMatthew G. Knepley . flg - PETSC_TRUE if we log the requested memory size
1041608c71bfSMatthew G. Knepley 
1042608c71bfSMatthew G. Knepley   Level: developer
1043608c71bfSMatthew G. Knepley 
1044608c71bfSMatthew G. Knepley .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1045608c71bfSMatthew G. Knepley @*/
1046608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1047608c71bfSMatthew G. Knepley {
1048608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1049608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
1050608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1051608c71bfSMatthew G. Knepley }
1052