xref: /petsc/src/sys/memory/mtr.c (revision ccd65f6325a2212a5fe1f4fe4d73f30fbecd7d64)
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;
1146c093d5bSvictor   head = TRhead; lasthead = NULL;
1152cba8197SMatthew G. Knepley   if (head && head->prev) {
116*ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
1172cba8197SMatthew G. Knepley     (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n",head,head->prev);
1184ed0ab5bSBarry Smith     return PETSC_ERR_MEMC;
1192cba8197SMatthew G. Knepley   }
120e5c89e4eSSatish Balay   while (head) {
1210700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
122*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
123e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
1244ed0ab5bSBarry Smith       (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n");
125e269983cSBarry Smith       if (lasthead) {
126e269983cSBarry Smith         a    = (char*)(((TrSPACE*)head) + 1);
127*ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Last intact block [id=%d(%.0f)] at address %p allocated in %s() at %s:%d\n",lasthead->id,(PetscLogDouble)lasthead->size,a,lasthead->functionname,lasthead->filename,lasthead->lineno);
128e269983cSBarry Smith       }
129e269983cSBarry Smith       abort();
1304ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
131e5c89e4eSSatish Balay     }
132e5c89e4eSSatish Balay     a    = (char*)(((TrSPACE*)head) + 1);
1330700a824SBarry Smith     nend = (PetscClassId*)(a + head->size);
1340700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
135*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
136e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
137e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
1384ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
139e5c89e4eSSatish Balay       } else {
140e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
141*ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
1424ed0ab5bSBarry Smith         return PETSC_ERR_MEMC;
143e5c89e4eSSatish Balay       }
144e5c89e4eSSatish Balay     }
1452cba8197SMatthew G. Knepley     if (head->prev && head->prev != lasthead) {
146*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n",function,file,line);
1472cba8197SMatthew G. Knepley       (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n",head->prev,lasthead);
148*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n",lasthead->functionname,lasthead->filename,lasthead->lineno);
149*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
1504ed0ab5bSBarry Smith       return PETSC_ERR_MEMC;
1512cba8197SMatthew G. Knepley     }
1526c093d5bSvictor     lasthead = head;
153e5c89e4eSSatish Balay     head     = head->next;
154e5c89e4eSSatish Balay   }
1554ed0ab5bSBarry Smith   return 0;
156e5c89e4eSSatish Balay }
157e5c89e4eSSatish Balay 
158e5c89e4eSSatish Balay /*
159e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
160e5c89e4eSSatish Balay 
161e5c89e4eSSatish Balay     Input Parameters:
162e5c89e4eSSatish Balay +   a   - number of bytes to allocate
163e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
164efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
165e5c89e4eSSatish Balay 
166e5c89e4eSSatish Balay     Returns:
16792f119d6SBarry Smith     double aligned pointer to requested storage, or null if not  available.
168e5c89e4eSSatish Balay  */
169071fcb05SBarry Smith PetscErrorCode  PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
170e5c89e4eSSatish Balay {
171e5c89e4eSSatish Balay   TRSPACE        *head;
172e5c89e4eSSatish Balay   char           *inew;
173e5c89e4eSSatish Balay   size_t         nsize;
174e5c89e4eSSatish Balay   PetscErrorCode ierr;
175e5c89e4eSSatish Balay 
176e5c89e4eSSatish Balay   PetscFunctionBegin;
177f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
178f0ba7cfcSLisandro Dalcin   if (!a) { *result = NULL; PetscFunctionReturn(0); }
179f0ba7cfcSLisandro Dalcin 
180efca3c55SSatish Balay   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
181e5c89e4eSSatish Balay 
18225b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
183071fcb05SBarry Smith   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
184e3ed9ee7SBarry Smith 
185e5c89e4eSSatish Balay   head  = (TRSPACE*)inew;
186e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
187e5c89e4eSSatish Balay 
188e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
189e5c89e4eSSatish Balay   head->next   = TRhead;
190e5c89e4eSSatish Balay   TRhead       = head;
191f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
192e5c89e4eSSatish Balay   head->size   = nsize;
193608c71bfSMatthew G. Knepley   head->rsize  = a;
194e269983cSBarry Smith   head->id     = TRid++;
195e5c89e4eSSatish Balay   head->lineno = lineno;
196e5c89e4eSSatish Balay 
197e5c89e4eSSatish Balay   head->filename                 = filename;
198e5c89e4eSSatish Balay   head->functionname             = function;
1990700a824SBarry Smith   head->classid                  = CLASSID_VALUE;
2000700a824SBarry Smith   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
201e5c89e4eSSatish Balay 
202608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
203a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
204e3ed9ee7SBarry Smith   if (PetscLogMemory) {
205e3ed9ee7SBarry Smith     PetscInt i;
206e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
207e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
208e3ed9ee7SBarry Smith     }
209e3ed9ee7SBarry Smith   }
210e5c89e4eSSatish Balay   TRfrags++;
211e5c89e4eSSatish Balay 
2128bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
21376386721SLisandro Dalcin   if (PetscStackActive()) {
2145c25fcd7SBarry Smith     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
2152c9581d2SBarry Smith     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2162c9581d2SBarry Smith     head->stack.line[head->stack.currentsize-2] = lineno;
2179de0f6ecSBarry Smith   } else {
2189de0f6ecSBarry Smith     head->stack.currentsize = 0;
21976386721SLisandro Dalcin   }
22092f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2212d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
22292f119d6SBarry Smith     size_t     i, n = a/sizeof(PetscReal);
22392f119d6SBarry Smith     PetscReal *s = (PetscReal*) inew;
22492f119d6SBarry Smith     /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
22592f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
226df282883SBarry Smith     int        nas = 0x7F800002;
22792f119d6SBarry Smith #else
22892f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22992f119d6SBarry Smith #endif
23092f119d6SBarry Smith     for (i=0; i<n; i++) {
23192f119d6SBarry Smith       memcpy(s+i,&nas,sizeof(PetscReal));
23292f119d6SBarry Smith     }
23392f119d6SBarry Smith   }
23492f119d6SBarry Smith #endif
235e5c89e4eSSatish Balay #endif
236e5c89e4eSSatish Balay 
237e5c89e4eSSatish Balay   /*
23892f119d6SBarry Smith          Allow logging of all mallocs made.
23992f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
240e5c89e4eSSatish Balay   */
241574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
242e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
243e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
244e32f2f54SBarry Smith       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
245a297a907SKarl Rupp 
246a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
247e32f2f54SBarry Smith       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
248a297a907SKarl Rupp 
249a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
250e32f2f54SBarry Smith       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
251e5c89e4eSSatish Balay     }
252e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
253e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
254e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
255e5c89e4eSSatish Balay   }
256608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) {
257608c71bfSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(PetscLogMallocTraceViewer,"Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null");CHKERRQ(ierr);
258608c71bfSMatthew G. Knepley   }
259e5c89e4eSSatish Balay   *result = (void*)inew;
260e5c89e4eSSatish Balay   PetscFunctionReturn(0);
261e5c89e4eSSatish Balay }
262e5c89e4eSSatish Balay 
263e5c89e4eSSatish Balay /*
264e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay    Input Parameters:
267e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
268e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
269608c71bfSMatthew G. Knepley .   filename  - file name where used.  Use __FILE__ for this
270e5c89e4eSSatish Balay  */
271608c71bfSMatthew G. Knepley PetscErrorCode  PetscTrFreeDefault(void *aa,int lineno,const char function[],const char filename[])
272e5c89e4eSSatish Balay {
273e5c89e4eSSatish Balay   char           *a = (char*)aa;
274e5c89e4eSSatish Balay   TRSPACE        *head;
275e5c89e4eSSatish Balay   char           *ahead;
276608c71bfSMatthew G. Knepley   size_t         asize;
277e5c89e4eSSatish Balay   PetscErrorCode ierr;
2780700a824SBarry Smith   PetscClassId   *nend;
279e5c89e4eSSatish Balay 
280e5c89e4eSSatish Balay   PetscFunctionBegin;
281e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
28249d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
283e5c89e4eSSatish Balay 
284608c71bfSMatthew G. Knepley   ierr = PetscMallocValidate(lineno,function,filename);CHKERRQ(ierr);
285e5c89e4eSSatish Balay 
286e5c89e4eSSatish Balay   ahead = a;
287e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
288e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
289e5c89e4eSSatish Balay 
2900700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
291*ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
292e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
293e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
294e5c89e4eSSatish Balay   }
2950700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2960700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
297e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
298*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
299e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
300e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
301*ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
302e5c89e4eSSatish Balay       } else {
303*ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
304e5c89e4eSSatish Balay       }
305e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
306e5c89e4eSSatish Balay     } else {
307e5c89e4eSSatish Balay       /* Damaged tail */
308*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
309e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
310*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
311e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
312e5c89e4eSSatish Balay     }
313e5c89e4eSSatish Balay   }
314608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
315608c71bfSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null");CHKERRQ(ierr);
316608c71bfSMatthew G. Knepley   }
317e5c89e4eSSatish Balay   /* Mark the location freed */
318e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
319e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
320608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
321608c71bfSMatthew G. Knepley     head->lineno       = lineno;
322608c71bfSMatthew G. Knepley     head->filename     = filename;
323e5c89e4eSSatish Balay     head->functionname = function;
324e5c89e4eSSatish Balay   } else {
325e5c89e4eSSatish Balay     head->lineno = -head->lineno;
326e5c89e4eSSatish Balay   }
327608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
328608c71bfSMatthew G. Knepley   if (TRallocated < asize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
329608c71bfSMatthew G. Knepley   TRallocated -= asize;
330e5c89e4eSSatish Balay   TRfrags--;
331e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
332e5c89e4eSSatish Balay   else TRhead = head->next;
333e5c89e4eSSatish Balay 
334e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
335608c71bfSMatthew G. Knepley   ierr = PetscFreeAlign(a,lineno,function,filename);CHKERRQ(ierr);
336e5c89e4eSSatish Balay   PetscFunctionReturn(0);
337e5c89e4eSSatish Balay }
338e5c89e4eSSatish Balay 
3393221ece2SMatthew G. Knepley /*
3403221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3413221ece2SMatthew G. Knepley 
3423221ece2SMatthew G. Knepley   Input Parameters:
3433221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3443221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3453221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
34692f119d6SBarry Smith - result - original memory
3473221ece2SMatthew G. Knepley 
3483221ece2SMatthew G. Knepley   Output Parameter:
3493221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3503221ece2SMatthew G. Knepley 
3513221ece2SMatthew G. Knepley   Level: developer
3523221ece2SMatthew G. Knepley 
3533221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3543221ece2SMatthew G. Knepley */
3553221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3563221ece2SMatthew G. Knepley {
3573221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3583221ece2SMatthew G. Knepley   TRSPACE        *head;
3593221ece2SMatthew G. Knepley   char           *ahead, *inew;
3603221ece2SMatthew G. Knepley   PetscClassId   *nend;
3613221ece2SMatthew G. Knepley   size_t         nsize;
3623221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3633221ece2SMatthew G. Knepley 
3643221ece2SMatthew G. Knepley   PetscFunctionBegin;
36592f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
366c22f1541SToby Isaac   if (!len) {
367c22f1541SToby Isaac     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
368c22f1541SToby Isaac     *result = NULL;
369c22f1541SToby Isaac     PetscFunctionReturn(0);
370c22f1541SToby Isaac   }
37192f119d6SBarry Smith   /* If the orginal space was NULL just use the regular malloc() */
372f590eff4SLisandro Dalcin   if (!*result) {
373071fcb05SBarry Smith     ierr = PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);CHKERRQ(ierr);
374f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
375f590eff4SLisandro Dalcin   }
3763221ece2SMatthew G. Knepley 
37738548759SBarry Smith   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
3783221ece2SMatthew G. Knepley 
3793221ece2SMatthew G. Knepley   ahead = a;
3803221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3813221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3823221ece2SMatthew G. Knepley   inew  = a;
3833221ece2SMatthew G. Knepley 
3843221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
385*ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
3863221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3873221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3883221ece2SMatthew G. Knepley   }
3893221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3903221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3913221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
392*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
3933221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3943221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
395*ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
3963221ece2SMatthew G. Knepley       } else {
397*ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
3983221ece2SMatthew G. Knepley       }
3993221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
4003221ece2SMatthew G. Knepley     } else {
4013221ece2SMatthew G. Knepley       /* Damaged tail */
402*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
4033221ece2SMatthew 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);
404*ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
4053221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
4063221ece2SMatthew G. Knepley     }
4073221ece2SMatthew G. Knepley   }
4083221ece2SMatthew G. Knepley 
40992f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
410608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
4113221ece2SMatthew G. Knepley   TRfrags--;
4123221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4133221ece2SMatthew G. Knepley   else TRhead = head->next;
4143221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4153221ece2SMatthew G. Knepley 
4163221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
4173221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
4183221ece2SMatthew G. Knepley 
4193221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
4203221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4213221ece2SMatthew G. Knepley 
4223221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4233221ece2SMatthew G. Knepley   head->next   = TRhead;
4243221ece2SMatthew G. Knepley   TRhead       = head;
4253221ece2SMatthew G. Knepley   head->prev   = NULL;
4263221ece2SMatthew G. Knepley   head->size   = nsize;
427608c71bfSMatthew G. Knepley   head->rsize  = len;
428e269983cSBarry Smith   head->id     = TRid++;
4293221ece2SMatthew G. Knepley   head->lineno = lineno;
4303221ece2SMatthew G. Knepley 
4313221ece2SMatthew G. Knepley   head->filename                 = filename;
4323221ece2SMatthew G. Knepley   head->functionname             = function;
4333221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4343221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4353221ece2SMatthew G. Knepley 
436608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4373221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
438e3ed9ee7SBarry Smith   if (PetscLogMemory) {
439e3ed9ee7SBarry Smith     PetscInt i;
440e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
441e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
442e3ed9ee7SBarry Smith     }
443e3ed9ee7SBarry Smith   }
4443221ece2SMatthew G. Knepley   TRfrags++;
4453221ece2SMatthew G. Knepley 
4463221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4473221ece2SMatthew G. Knepley   if (PetscStackActive()) {
4483221ece2SMatthew G. Knepley     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
4493221ece2SMatthew G. Knepley     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4503221ece2SMatthew G. Knepley     head->stack.line[head->stack.currentsize-2] = lineno;
4513221ece2SMatthew G. Knepley   } else {
4523221ece2SMatthew G. Knepley     head->stack.currentsize = 0;
4533221ece2SMatthew G. Knepley   }
4543221ece2SMatthew G. Knepley #endif
4553221ece2SMatthew G. Knepley 
4563221ece2SMatthew G. Knepley   /*
45792f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
45892f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4593221ece2SMatthew G. Knepley   */
4603221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4613221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4623221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
4633221ece2SMatthew G. Knepley       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4643221ece2SMatthew G. Knepley 
4653221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4663221ece2SMatthew G. Knepley       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4673221ece2SMatthew G. Knepley 
4683221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4693221ece2SMatthew G. Knepley       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4703221ece2SMatthew G. Knepley     }
4713221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4723221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4733221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4743221ece2SMatthew G. Knepley   }
4753221ece2SMatthew G. Knepley   *result = (void*)inew;
4763221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4773221ece2SMatthew G. Knepley }
4783221ece2SMatthew G. Knepley 
479fe7fb379SMatthew Knepley /*@C
48092f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
481e5c89e4eSSatish Balay 
482e5c89e4eSSatish Balay     Collective on PetscViewer
483e5c89e4eSSatish Balay 
484e5c89e4eSSatish Balay     Input Parameter:
485e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
486e5c89e4eSSatish Balay -    message - string printed before values
487e5c89e4eSSatish Balay 
4880841954dSBarry Smith     Options Database:
48992f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
4900841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4910841954dSBarry Smith 
492e5c89e4eSSatish Balay     Level: intermediate
493e5c89e4eSSatish Balay 
49492f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
495e5c89e4eSSatish Balay  @*/
4960841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
497e5c89e4eSSatish Balay {
4980841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4990841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
500e5c89e4eSSatish Balay   PetscErrorCode ierr;
501e5c89e4eSSatish Balay   MPI_Comm       comm;
502e5c89e4eSSatish Balay 
503e5c89e4eSSatish Balay   PetscFunctionBegin;
504e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
505e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
5060841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
507e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
508e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
509e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
510e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
511e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
512e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
513ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
514ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
515ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5160841954dSBarry 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);
517ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
518ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
519ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5200841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
521ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
522ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
523ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5240841954dSBarry 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);
525ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
526ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
527ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5280841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
529e5c89e4eSSatish Balay   } else if (resident && residentmax) {
530ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
531ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
532ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5330841954dSBarry 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);
534ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
535ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
536ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5370841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
538e5c89e4eSSatish Balay   } else if (resident && allocated) {
539ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
540ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
541ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5420841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
543ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
544ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
545ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5460841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5470841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
548e5c89e4eSSatish Balay   } else if (allocated) {
549ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
550ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
551ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5520841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5530841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5540841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
555e5c89e4eSSatish Balay   } else {
55692f119d6SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
557e5c89e4eSSatish Balay   }
558e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
559e5c89e4eSSatish Balay   PetscFunctionReturn(0);
560e5c89e4eSSatish Balay }
561e5c89e4eSSatish Balay 
56246eb3923SBarry Smith /*@
563e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
564e5c89e4eSSatish Balay 
565e5c89e4eSSatish Balay     Not Collective
566e5c89e4eSSatish Balay 
567e5c89e4eSSatish Balay     Output Parameters:
568e5c89e4eSSatish Balay .   space - number of bytes currently allocated
569e5c89e4eSSatish Balay 
570e5c89e4eSSatish Balay     Level: intermediate
571e5c89e4eSSatish Balay 
572540e20f2SPierre Jolivet .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
573e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
574e5c89e4eSSatish Balay  @*/
5757087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
576e5c89e4eSSatish Balay {
577e5c89e4eSSatish Balay   PetscFunctionBegin;
578e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
579e5c89e4eSSatish Balay   PetscFunctionReturn(0);
580e5c89e4eSSatish Balay }
581e5c89e4eSSatish Balay 
582dc37d89fSBarry Smith /*@
583e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
584e5c89e4eSSatish Balay         during this run.
585e5c89e4eSSatish Balay 
586e5c89e4eSSatish Balay     Not Collective
587e5c89e4eSSatish Balay 
588e5c89e4eSSatish Balay     Output Parameters:
589e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
590e5c89e4eSSatish Balay 
591e5c89e4eSSatish Balay     Level: intermediate
592e5c89e4eSSatish Balay 
59392f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
594e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
595e5c89e4eSSatish Balay  @*/
5967087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
597e5c89e4eSSatish Balay {
598e5c89e4eSSatish Balay   PetscFunctionBegin;
599e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
600e5c89e4eSSatish Balay   PetscFunctionReturn(0);
601e5c89e4eSSatish Balay }
602e5c89e4eSSatish Balay 
603e3ed9ee7SBarry Smith /*@
604e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
605e3ed9ee7SBarry Smith 
606e3ed9ee7SBarry Smith     Not Collective
607e3ed9ee7SBarry Smith 
608e3ed9ee7SBarry Smith     Input Parameter:
609e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
610e3ed9ee7SBarry Smith 
611e3ed9ee7SBarry Smith     Level: developer
612e3ed9ee7SBarry Smith 
61392f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
614e3ed9ee7SBarry Smith           PetscMallocPopMaximumUsage()
615e3ed9ee7SBarry Smith  @*/
616e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPushMaximumUsage(int event)
617e3ed9ee7SBarry Smith {
618e3ed9ee7SBarry Smith   PetscFunctionBegin;
619e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
620e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
621e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems-1] = event;
622e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
623e3ed9ee7SBarry Smith }
624e3ed9ee7SBarry Smith 
625e3ed9ee7SBarry Smith /*@
626e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
627e3ed9ee7SBarry Smith 
628e3ed9ee7SBarry Smith     Not Collective
629e3ed9ee7SBarry Smith 
630e3ed9ee7SBarry Smith     Input Parameter:
631e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
632e3ed9ee7SBarry Smith 
633e3ed9ee7SBarry Smith     Output Parameter:
634e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
635e3ed9ee7SBarry Smith 
636e3ed9ee7SBarry Smith     Level: developer
637e3ed9ee7SBarry Smith 
63892f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
639e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
640e3ed9ee7SBarry Smith  @*/
641e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
642e3ed9ee7SBarry Smith {
643e3ed9ee7SBarry Smith   PetscFunctionBegin;
644e3ed9ee7SBarry Smith   *mu = 0;
645e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
646e3ed9ee7SBarry Smith   if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
647e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
648e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
649e3ed9ee7SBarry Smith }
650e3ed9ee7SBarry Smith 
651a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
652a64a8e02SBarry Smith /*@C
653a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
654a64a8e02SBarry Smith 
655a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
656a64a8e02SBarry Smith 
657a64a8e02SBarry Smith    Input Parameter:
658a64a8e02SBarry Smith .    ptr - the memory location
659a64a8e02SBarry Smith 
660fd292e60Sprj-    Output Parameter:
661a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
662a64a8e02SBarry Smith 
663a64a8e02SBarry Smith    Level: intermediate
664a64a8e02SBarry Smith 
66592f119d6SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView()
666a64a8e02SBarry Smith @*/
667a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
668a64a8e02SBarry Smith {
669a64a8e02SBarry Smith   TRSPACE *head;
670a64a8e02SBarry Smith 
671a64a8e02SBarry Smith   PetscFunctionBegin;
672a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
673a64a8e02SBarry Smith   *stack = &head->stack;
674a64a8e02SBarry Smith   PetscFunctionReturn(0);
675a64a8e02SBarry Smith }
67676386721SLisandro Dalcin #else
67776386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
67876386721SLisandro Dalcin {
67976386721SLisandro Dalcin   PetscFunctionBegin;
680f0ba7cfcSLisandro Dalcin   *stack = NULL;
68176386721SLisandro Dalcin   PetscFunctionReturn(0);
68276386721SLisandro Dalcin }
683a64a8e02SBarry Smith #endif
684a64a8e02SBarry Smith 
685e5c89e4eSSatish Balay /*@C
68692f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
687e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
688e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
689e5c89e4eSSatish Balay    allocated.
690e5c89e4eSSatish Balay 
69192f119d6SBarry Smith    Not Collective
692e5c89e4eSSatish Balay 
693e5c89e4eSSatish Balay    Input Parameter:
694e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
695e5c89e4eSSatish Balay 
696e5c89e4eSSatish Balay    Options Database Key:
69792f119d6SBarry Smith .  -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
698e5c89e4eSSatish Balay 
699e5c89e4eSSatish Balay    Level: intermediate
700e5c89e4eSSatish Balay 
701e5c89e4eSSatish Balay    Fortran Note:
702e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
703e5c89e4eSSatish Balay    The fp defaults to stdout.
704e5c89e4eSSatish Balay 
70595452b02SPatrick Sanan    Notes:
70692f119d6SBarry Smith      Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
707e5c89e4eSSatish Balay 
70892f119d6SBarry Smith      When called in PetscFinalize() dumps only the allocations that have not been properly freed
70992f119d6SBarry Smith 
71092f119d6SBarry Smith      PetscMallocView() prints a list of all memory ever allocated
71192f119d6SBarry Smith 
712f0b7f91aSBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
713e5c89e4eSSatish Balay @*/
7147087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
715e5c89e4eSSatish Balay {
716e5c89e4eSSatish Balay   TRSPACE        *head;
717e3ed9ee7SBarry Smith   size_t         libAlloc = 0;
718e5c89e4eSSatish Balay   PetscErrorCode ierr;
719e5c89e4eSSatish Balay   PetscMPIInt    rank;
720e5c89e4eSSatish Balay 
721e5c89e4eSSatish Balay   PetscFunctionBegin;
722ffc4695bSBarry Smith   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRMPI(ierr);
723da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
724e5c89e4eSSatish Balay   head = TRhead;
725e5c89e4eSSatish Balay   while (head) {
726608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7275486ca60SMatthew G. Knepley     head = head->next;
7285486ca60SMatthew G. Knepley   }
7295486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
7305486ca60SMatthew G. Knepley   head = TRhead;
7315486ca60SMatthew G. Knepley   while (head) {
7325486ca60SMatthew G. Knepley     PetscBool isLib;
7335486ca60SMatthew G. Knepley 
7345486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
7355486ca60SMatthew G. Knepley     if (!isLib) {
736*ccd65f63SJunchao Zhang       fprintf(fp,"[%2d] %.0f bytes %s() at %s:%d\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->filename,head->lineno);
7378bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
738e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
739e5c89e4eSSatish Balay #endif
7405486ca60SMatthew G. Knepley     }
741e5c89e4eSSatish Balay     head = head->next;
742e5c89e4eSSatish Balay   }
743e5c89e4eSSatish Balay   PetscFunctionReturn(0);
744e5c89e4eSSatish Balay }
745e5c89e4eSSatish Balay 
746dc37d89fSBarry Smith /*@
74792f119d6SBarry Smith     PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
748574034a9SJed Brown 
749574034a9SJed Brown     Not Collective
750574034a9SJed Brown 
751574034a9SJed Brown     Input Arguments:
752574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
753574034a9SJed Brown 
754574034a9SJed Brown     Options Database Key:
75592f119d6SBarry Smith +  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
7568b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7578b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
758574034a9SJed Brown 
759574034a9SJed Brown     Level: advanced
760574034a9SJed Brown 
76192f119d6SBarry Smith     Notes: Must be called after PetscMallocSetDebug()
76292f119d6SBarry Smith 
76392f119d6SBarry Smith     Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
76492f119d6SBarry Smith 
765f0b7f91aSBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
766574034a9SJed Brown @*/
76792f119d6SBarry Smith PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
768574034a9SJed Brown {
769574034a9SJed Brown   PetscErrorCode ierr;
770574034a9SJed Brown 
771574034a9SJed Brown   PetscFunctionBegin;
77292f119d6SBarry Smith   PetscLogMalloc = 0;
77392f119d6SBarry Smith   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
774574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
775574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
776574034a9SJed Brown   PetscFunctionReturn(0);
777574034a9SJed Brown }
778574034a9SJed Brown 
779dc37d89fSBarry Smith /*@
78092f119d6SBarry Smith     PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
78118a2528dSJed Brown 
78218a2528dSJed Brown     Not Collective
78318a2528dSJed Brown 
78418a2528dSJed Brown     Output Arguments
78518a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
78618a2528dSJed Brown 
78718a2528dSJed Brown     Options Database Key:
78892f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView()
78918a2528dSJed Brown 
79018a2528dSJed Brown     Level: advanced
79118a2528dSJed Brown 
792608c71bfSMatthew G. Knepley .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
79318a2528dSJed Brown @*/
79492f119d6SBarry Smith PetscErrorCode PetscMallocViewGet(PetscBool *logging)
79518a2528dSJed Brown {
79618a2528dSJed Brown 
79718a2528dSJed Brown   PetscFunctionBegin;
79818a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
79918a2528dSJed Brown   PetscFunctionReturn(0);
80018a2528dSJed Brown }
80118a2528dSJed Brown 
802608c71bfSMatthew G. Knepley /*@
803608c71bfSMatthew G. Knepley   PetscMallocTraceSet - Trace all calls to PetscMalloc()
804608c71bfSMatthew G. Knepley 
805608c71bfSMatthew G. Knepley   Not Collective
806608c71bfSMatthew G. Knepley 
807608c71bfSMatthew G. Knepley   Input Arguments:
808608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout
809608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
810608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
811608c71bfSMatthew G. Knepley 
812608c71bfSMatthew G. Knepley   Note:
813608c71bfSMatthew G. Knepley   The viewer should not be collective.
814608c71bfSMatthew G. Knepley 
815608c71bfSMatthew G. Knepley   Level: advanced
816608c71bfSMatthew G. Knepley 
817608c71bfSMatthew G. Knepley .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
818608c71bfSMatthew G. Knepley @*/
819608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
820608c71bfSMatthew G. Knepley {
821608c71bfSMatthew G. Knepley   PetscErrorCode ierr;
822608c71bfSMatthew G. Knepley 
823608c71bfSMatthew G. Knepley   PetscFunctionBegin;
824608c71bfSMatthew G. Knepley   if (!active) {PetscLogMallocTrace = -1; PetscFunctionReturn(0);}
825608c71bfSMatthew G. Knepley   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
826608c71bfSMatthew G. Knepley   PetscLogMallocTrace = 0;
827608c71bfSMatthew G. Knepley   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
828608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
829608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t) logmin;
830608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
831608c71bfSMatthew G. Knepley }
832608c71bfSMatthew G. Knepley 
833608c71bfSMatthew G. Knepley /*@
834608c71bfSMatthew G. Knepley   PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
835608c71bfSMatthew G. Knepley 
836608c71bfSMatthew G. Knepley   Not Collective
837608c71bfSMatthew G. Knepley 
838608c71bfSMatthew G. Knepley   Output Argument:
839608c71bfSMatthew G. Knepley . logging - PETSC_TRUE if logging is active
840608c71bfSMatthew G. Knepley 
841608c71bfSMatthew G. Knepley   Options Database Key:
842608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView()
843608c71bfSMatthew G. Knepley 
844608c71bfSMatthew G. Knepley   Level: advanced
845608c71bfSMatthew G. Knepley 
846608c71bfSMatthew G. Knepley .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
847608c71bfSMatthew G. Knepley @*/
848608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
849608c71bfSMatthew G. Knepley {
850608c71bfSMatthew G. Knepley 
851608c71bfSMatthew G. Knepley   PetscFunctionBegin;
852608c71bfSMatthew G. Knepley   *logging = (PetscBool) (PetscLogMallocTrace >= 0);
853608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
854608c71bfSMatthew G. Knepley }
855608c71bfSMatthew G. Knepley 
856e5c89e4eSSatish Balay /*@C
85792f119d6SBarry Smith     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
85821b680ceSJed Brown        PetscMemoryGetMaximumUsage()
859e5c89e4eSSatish Balay 
86092f119d6SBarry Smith     Not Collective
861e5c89e4eSSatish Balay 
862e5c89e4eSSatish Balay     Input Parameter:
8630298fd71SBarry Smith .   fp - file pointer; or NULL
864e5c89e4eSSatish Balay 
865e5c89e4eSSatish Balay     Options Database Key:
86692f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
867e5c89e4eSSatish Balay 
868e5c89e4eSSatish Balay     Level: advanced
869e5c89e4eSSatish Balay 
870e5c89e4eSSatish Balay    Fortran Note:
87192f119d6SBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
872e5c89e4eSSatish Balay    The fp defaults to stdout.
873e5c89e4eSSatish Balay 
87492f119d6SBarry Smith    Notes:
87592f119d6SBarry Smith      PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
87692f119d6SBarry Smith 
87792f119d6SBarry Smith      PetscMemoryView() gives a brief summary of current memory usage
87892f119d6SBarry Smith 
87992f119d6SBarry Smith .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
880e5c89e4eSSatish Balay @*/
88192f119d6SBarry Smith PetscErrorCode  PetscMallocView(FILE *fp)
882e5c89e4eSSatish Balay {
88392f119d6SBarry Smith   PetscInt       i,j,n,*perm;
884e5c89e4eSSatish Balay   size_t         *shortlength;
885f56c2debSBarry Smith   int            *shortcount,err;
88692f119d6SBarry Smith   PetscMPIInt    rank;
887ace3abfcSBarry Smith   PetscBool      match;
888e5c89e4eSSatish Balay   const char     **shortfunction;
889e5c89e4eSSatish Balay   PetscLogDouble rss;
890e5c89e4eSSatish Balay   PetscErrorCode ierr;
891e5c89e4eSSatish Balay 
892e5c89e4eSSatish Balay   PetscFunctionBegin;
893ffc4695bSBarry Smith   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRMPI(ierr);
894f56c2debSBarry Smith   err = fflush(fp);
895e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
896f56c2debSBarry Smith 
89779dccf82SBarry 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()");
898768aa557SSatish Balay 
899da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
900f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
901e5c89e4eSSatish Balay   if (rss) {
90292f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
903e5c89e4eSSatish Balay   } else {
90492f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
905e5c89e4eSSatish Balay   }
906e32f2f54SBarry Smith   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
907e32f2f54SBarry Smith   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
908e32f2f54SBarry Smith   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
90997b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
910e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
911e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
912e5c89e4eSSatish Balay       if (match) {
913e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
91459ffdab8SBarry Smith         shortcount[j]++;
915e5c89e4eSSatish Balay         goto foundit;
916e5c89e4eSSatish Balay       }
917e5c89e4eSSatish Balay     }
918e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
919e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
92059ffdab8SBarry Smith     shortcount[n]    = 1;
921e5c89e4eSSatish Balay     n++;
922e5c89e4eSSatish Balay foundit:;
923e5c89e4eSSatish Balay   }
924e5c89e4eSSatish Balay 
925e32f2f54SBarry Smith   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
926e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
927e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
928e5c89e4eSSatish Balay 
92992f119d6SBarry Smith   (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
930e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
93192f119d6SBarry Smith     (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
932e5c89e4eSSatish Balay   }
933e5c89e4eSSatish Balay   free(perm);
934e5c89e4eSSatish Balay   free(shortlength);
93559ffdab8SBarry Smith   free(shortcount);
936e5c89e4eSSatish Balay   free((char**)shortfunction);
937f56c2debSBarry Smith   err = fflush(fp);
938e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
939e5c89e4eSSatish Balay   PetscFunctionReturn(0);
940e5c89e4eSSatish Balay }
941e5c89e4eSSatish Balay 
942e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
943e5c89e4eSSatish Balay 
944dc37d89fSBarry Smith /*@
94592f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
946e5c89e4eSSatish Balay 
947e5c89e4eSSatish Balay     Not Collective
948e5c89e4eSSatish Balay 
949e5c89e4eSSatish Balay     Input Parameter:
95092f119d6SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
9512d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
952e5c89e4eSSatish Balay 
95392f119d6SBarry Smith     Options Database:
95479dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
95592f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
95679dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
95792f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
95879dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
95979dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
960e5c89e4eSSatish Balay 
96192f119d6SBarry Smith    Level: developer
96292f119d6SBarry Smith 
96392f119d6SBarry Smith     Notes: This is called in PetscInitialize() and should not be called elsewhere
96492f119d6SBarry Smith 
96592f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
966e5c89e4eSSatish Balay @*/
96792f119d6SBarry Smith PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
968e5c89e4eSSatish Balay {
96992f119d6SBarry Smith   PetscErrorCode ierr;
97092f119d6SBarry Smith 
971e5c89e4eSSatish Balay   PetscFunctionBegin;
97292f119d6SBarry 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()");
97392f119d6SBarry Smith   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);CHKERRQ(ierr);
97492f119d6SBarry Smith 
97592f119d6SBarry Smith   TRallocated         = 0;
97692f119d6SBarry Smith   TRfrags             = 0;
97792f119d6SBarry Smith   TRhead              = NULL;
97892f119d6SBarry Smith   TRid                = 0;
97992f119d6SBarry Smith   TRdebugLevel        = eachcall;
98092f119d6SBarry Smith   TRMaxMem            = 0;
98192f119d6SBarry Smith   PetscLogMallocMax   = 10000;
98292f119d6SBarry Smith   PetscLogMalloc      = -1;
9832d4ee042Sprj-   TRdebugIinitializenan = initializenan;
984e5c89e4eSSatish Balay   PetscFunctionReturn(0);
985e5c89e4eSSatish Balay }
9860acecf5bSBarry Smith 
987dc37d89fSBarry Smith /*@
98892f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9890acecf5bSBarry Smith 
9900acecf5bSBarry Smith     Not Collective
9910acecf5bSBarry Smith 
99292f119d6SBarry Smith     Output Parameters:
99392f119d6SBarry Smith +    basic - doing basic debugging
99492f119d6SBarry Smith .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
99579dccf82SBarry Smith -    initializenan - initializes memory with NaN
9960acecf5bSBarry Smith 
9970acecf5bSBarry Smith    Level: intermediate
9980acecf5bSBarry Smith 
99992f119d6SBarry Smith    Notes:
100079dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
10010acecf5bSBarry Smith 
100292f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
10030acecf5bSBarry Smith @*/
100492f119d6SBarry Smith PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
10050acecf5bSBarry Smith {
10060acecf5bSBarry Smith   PetscFunctionBegin;
100779dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
100879dccf82SBarry Smith   if (eachcall) *eachcall           = TRdebugLevel;
10092d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
10100acecf5bSBarry Smith   PetscFunctionReturn(0);
10110acecf5bSBarry Smith }
1012608c71bfSMatthew G. Knepley 
1013608c71bfSMatthew G. Knepley /*@
1014608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
1015608c71bfSMatthew G. Knepley 
1016608c71bfSMatthew G. Knepley   Not Collective
1017608c71bfSMatthew G. Knepley 
1018608c71bfSMatthew G. Knepley   Input Parameter:
1019608c71bfSMatthew G. Knepley . flg - PETSC_TRUE to log the requested memory size
1020608c71bfSMatthew G. Knepley 
1021608c71bfSMatthew G. Knepley   Options Database:
1022608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1023608c71bfSMatthew G. Knepley 
1024608c71bfSMatthew G. Knepley   Level: developer
1025608c71bfSMatthew G. Knepley 
1026608c71bfSMatthew G. Knepley .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
1027608c71bfSMatthew G. Knepley @*/
1028608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1029608c71bfSMatthew G. Knepley {
1030608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1031608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
1032608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1033608c71bfSMatthew G. Knepley }
1034608c71bfSMatthew G. Knepley 
1035608c71bfSMatthew G. Knepley /*@
1036608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1037608c71bfSMatthew G. Knepley 
1038608c71bfSMatthew G. Knepley   Not Collective
1039608c71bfSMatthew G. Knepley 
1040608c71bfSMatthew G. Knepley   Output Parameter:
1041608c71bfSMatthew G. Knepley . flg - PETSC_TRUE if we log the requested memory size
1042608c71bfSMatthew G. Knepley 
1043608c71bfSMatthew G. Knepley   Level: developer
1044608c71bfSMatthew G. Knepley 
1045608c71bfSMatthew G. Knepley .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1046608c71bfSMatthew G. Knepley @*/
1047608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1048608c71bfSMatthew G. Knepley {
1049608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1050608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
1051608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1052608c71bfSMatthew G. Knepley }
1053