xref: /petsc/src/sys/memory/mtr.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
392f119d6SBarry Smith      Interface to malloc() and free(). This code allows for logging of memory usage and some error checking
4e5c89e4eSSatish Balay */
527104ee2SJacob Faibussowitsch #include <petsc/private/petscimpl.h>           /*I "petscsys.h" I*/
6665c2dedSJed Brown #include <petscviewer.h>
7e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
8e5c89e4eSSatish Balay #include <malloc.h>
9e5c89e4eSSatish Balay #endif
10e5c89e4eSSatish Balay 
11e5c89e4eSSatish Balay /*
12e5c89e4eSSatish Balay      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
13e5c89e4eSSatish Balay */
14071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,PetscBool,int,const char[],const char[],void**);
1595c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]);
1695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**);
17e5c89e4eSSatish Balay 
180700a824SBarry Smith #define CLASSID_VALUE  ((PetscClassId) 0xf0e0d0c9)
190700a824SBarry Smith #define ALREADY_FREED  ((PetscClassId) 0x0f0e0d9c)
20e5c89e4eSSatish Balay 
2192f119d6SBarry Smith /*  this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */
22e5c89e4eSSatish Balay typedef struct _trSPACE {
23608c71bfSMatthew G. Knepley   size_t          size, rsize; /* Aligned size and requested size */
24e5c89e4eSSatish Balay   int             id;
25e5c89e4eSSatish Balay   int             lineno;
26e5c89e4eSSatish Balay   const char      *filename;
27e5c89e4eSSatish Balay   const char      *functionname;
280700a824SBarry Smith   PetscClassId    classid;
298bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
30e5c89e4eSSatish Balay   PetscStack      stack;
31e5c89e4eSSatish Balay #endif
32e5c89e4eSSatish Balay   struct _trSPACE *next,*prev;
33e5c89e4eSSatish Balay } TRSPACE;
34e5c89e4eSSatish Balay 
3525b53cc9SJed Brown /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
3692f119d6SBarry Smith    It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN.
3725b53cc9SJed Brown */
38a64a8e02SBarry Smith #define HEADER_BYTES  ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))
39e5c89e4eSSatish Balay 
4025b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains
4125b53cc9SJed Brown    a minimum alignment of PETSC_MEMALIGN.
4225b53cc9SJed Brown */
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) {
116ccd65f63SJunchao 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) {
122ccd65f63SJunchao 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);
127ccd65f63SJunchao 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) {
135ccd65f63SJunchao 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);
141ccd65f63SJunchao 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) {
146ccd65f63SJunchao 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);
148ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n",lasthead->functionname,lasthead->filename,lasthead->lineno);
149ccd65f63SJunchao 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)
21327104ee2SJacob Faibussowitsch   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;
21692f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE)
2172d4ee042Sprj-   if (!clear && TRdebugIinitializenan) {
21892f119d6SBarry Smith     size_t     i, n = a/sizeof(PetscReal);
21992f119d6SBarry Smith     PetscReal *s = (PetscReal*) inew;
22092f119d6SBarry Smith     /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */
22192f119d6SBarry Smith #if defined(PETSC_USE_REAL_SINGLE)
222df282883SBarry Smith     int        nas = 0x7F800002;
22392f119d6SBarry Smith #else
22492f119d6SBarry Smith     PetscInt64 nas = 0x7FF0000000000002;
22592f119d6SBarry Smith #endif
22692f119d6SBarry Smith     for (i=0; i<n; i++) {
22792f119d6SBarry Smith       memcpy(s+i,&nas,sizeof(PetscReal));
22892f119d6SBarry Smith     }
22992f119d6SBarry Smith   }
23092f119d6SBarry Smith #endif
231e5c89e4eSSatish Balay #endif
232e5c89e4eSSatish Balay 
233e5c89e4eSSatish Balay   /*
23492f119d6SBarry Smith          Allow logging of all mallocs made.
23592f119d6SBarry Smith          TODO: Currently this memory is never freed, it should be freed during PetscFinalize()
236e5c89e4eSSatish Balay   */
237574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
238e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
239e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
240*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!PetscLogMallocLength,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
241a297a907SKarl Rupp 
242a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
243*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!PetscLogMallocFile,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
244a297a907SKarl Rupp 
245a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
246*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!PetscLogMallocFunction,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
247e5c89e4eSSatish Balay     }
248e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
249e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
250e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
251e5c89e4eSSatish Balay   }
252608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) {
253608c71bfSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(PetscLogMallocTraceViewer,"Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null");CHKERRQ(ierr);
254608c71bfSMatthew G. Knepley   }
255e5c89e4eSSatish Balay   *result = (void*)inew;
256e5c89e4eSSatish Balay   PetscFunctionReturn(0);
257e5c89e4eSSatish Balay }
258e5c89e4eSSatish Balay 
259e5c89e4eSSatish Balay /*
260e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
261e5c89e4eSSatish Balay 
262e5c89e4eSSatish Balay    Input Parameters:
263e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
264e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
265608c71bfSMatthew G. Knepley .   filename  - file name where used.  Use __FILE__ for this
266e5c89e4eSSatish Balay  */
267608c71bfSMatthew G. Knepley PetscErrorCode  PetscTrFreeDefault(void *aa,int lineno,const char function[],const char filename[])
268e5c89e4eSSatish Balay {
269e5c89e4eSSatish Balay   char           *a = (char*)aa;
270e5c89e4eSSatish Balay   TRSPACE        *head;
271e5c89e4eSSatish Balay   char           *ahead;
272608c71bfSMatthew G. Knepley   size_t         asize;
273e5c89e4eSSatish Balay   PetscErrorCode ierr;
2740700a824SBarry Smith   PetscClassId   *nend;
275e5c89e4eSSatish Balay 
276e5c89e4eSSatish Balay   PetscFunctionBegin;
277e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
27849d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
279e5c89e4eSSatish Balay 
280608c71bfSMatthew G. Knepley   ierr = PetscMallocValidate(lineno,function,filename);CHKERRQ(ierr);
281e5c89e4eSSatish Balay 
282e5c89e4eSSatish Balay   ahead = a;
283e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
284e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
285e5c89e4eSSatish Balay 
2860700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
287ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
288e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
289e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
290e5c89e4eSSatish Balay   }
2910700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2920700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
293e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
294ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
295e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
296e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
297ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
298e5c89e4eSSatish Balay       } else {
299ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
300e5c89e4eSSatish Balay       }
301e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
302e5c89e4eSSatish Balay     } else {
303e5c89e4eSSatish Balay       /* Damaged tail */
304ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
305e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
306ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
307e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
308e5c89e4eSSatish Balay     }
309e5c89e4eSSatish Balay   }
310608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
311608c71bfSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null");CHKERRQ(ierr);
312608c71bfSMatthew G. Knepley   }
313e5c89e4eSSatish Balay   /* Mark the location freed */
314e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
315e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
316608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
317608c71bfSMatthew G. Knepley     head->lineno       = lineno;
318608c71bfSMatthew G. Knepley     head->filename     = filename;
319e5c89e4eSSatish Balay     head->functionname = function;
320e5c89e4eSSatish Balay   } else {
321e5c89e4eSSatish Balay     head->lineno = -head->lineno;
322e5c89e4eSSatish Balay   }
323608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
324*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(TRallocated < asize,PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
325608c71bfSMatthew G. Knepley   TRallocated -= asize;
326e5c89e4eSSatish Balay   TRfrags--;
327e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
328e5c89e4eSSatish Balay   else TRhead = head->next;
329e5c89e4eSSatish Balay 
330e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
331608c71bfSMatthew G. Knepley   ierr = PetscFreeAlign(a,lineno,function,filename);CHKERRQ(ierr);
332e5c89e4eSSatish Balay   PetscFunctionReturn(0);
333e5c89e4eSSatish Balay }
334e5c89e4eSSatish Balay 
3353221ece2SMatthew G. Knepley /*
3363221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3373221ece2SMatthew G. Knepley 
3383221ece2SMatthew G. Knepley   Input Parameters:
3393221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3403221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3413221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
34292f119d6SBarry Smith - result - original memory
3433221ece2SMatthew G. Knepley 
3443221ece2SMatthew G. Knepley   Output Parameter:
3453221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3463221ece2SMatthew G. Knepley 
3473221ece2SMatthew G. Knepley   Level: developer
3483221ece2SMatthew G. Knepley 
3493221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3503221ece2SMatthew G. Knepley */
3513221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3523221ece2SMatthew G. Knepley {
3533221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3543221ece2SMatthew G. Knepley   TRSPACE        *head;
3553221ece2SMatthew G. Knepley   char           *ahead, *inew;
3563221ece2SMatthew G. Knepley   PetscClassId   *nend;
3573221ece2SMatthew G. Knepley   size_t         nsize;
3583221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3593221ece2SMatthew G. Knepley 
3603221ece2SMatthew G. Knepley   PetscFunctionBegin;
36192f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
362c22f1541SToby Isaac   if (!len) {
363c22f1541SToby Isaac     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
364c22f1541SToby Isaac     *result = NULL;
365c22f1541SToby Isaac     PetscFunctionReturn(0);
366c22f1541SToby Isaac   }
36792f119d6SBarry Smith   /* If the orginal space was NULL just use the regular malloc() */
368f590eff4SLisandro Dalcin   if (!*result) {
369071fcb05SBarry Smith     ierr = PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);CHKERRQ(ierr);
370f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
371f590eff4SLisandro Dalcin   }
3723221ece2SMatthew G. Knepley 
37338548759SBarry Smith   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
3743221ece2SMatthew G. Knepley 
3753221ece2SMatthew G. Knepley   ahead = a;
3763221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3773221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3783221ece2SMatthew G. Knepley   inew  = a;
3793221ece2SMatthew G. Knepley 
3803221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
381ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
3823221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3833221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3843221ece2SMatthew G. Knepley   }
3853221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3863221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3873221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
388ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
3893221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3903221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
391ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
3923221ece2SMatthew G. Knepley       } else {
393ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
3943221ece2SMatthew G. Knepley       }
3953221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3963221ece2SMatthew G. Knepley     } else {
3973221ece2SMatthew G. Knepley       /* Damaged tail */
398ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
3993221ece2SMatthew 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);
400ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
4013221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
4023221ece2SMatthew G. Knepley     }
4033221ece2SMatthew G. Knepley   }
4043221ece2SMatthew G. Knepley 
40592f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
406608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
4073221ece2SMatthew G. Knepley   TRfrags--;
4083221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4093221ece2SMatthew G. Knepley   else TRhead = head->next;
4103221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4113221ece2SMatthew G. Knepley 
4123221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
4133221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
4143221ece2SMatthew G. Knepley 
4153221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
4163221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4173221ece2SMatthew G. Knepley 
4183221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4193221ece2SMatthew G. Knepley   head->next   = TRhead;
4203221ece2SMatthew G. Knepley   TRhead       = head;
4213221ece2SMatthew G. Knepley   head->prev   = NULL;
4223221ece2SMatthew G. Knepley   head->size   = nsize;
423608c71bfSMatthew G. Knepley   head->rsize  = len;
424e269983cSBarry Smith   head->id     = TRid++;
4253221ece2SMatthew G. Knepley   head->lineno = lineno;
4263221ece2SMatthew G. Knepley 
4273221ece2SMatthew G. Knepley   head->filename                 = filename;
4283221ece2SMatthew G. Knepley   head->functionname             = function;
4293221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4303221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4313221ece2SMatthew G. Knepley 
432608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4333221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
434e3ed9ee7SBarry Smith   if (PetscLogMemory) {
435e3ed9ee7SBarry Smith     PetscInt i;
436e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
437e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
438e3ed9ee7SBarry Smith     }
439e3ed9ee7SBarry Smith   }
4403221ece2SMatthew G. Knepley   TRfrags++;
4413221ece2SMatthew G. Knepley 
4423221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
44327104ee2SJacob Faibussowitsch   ierr = PetscStackCopy(&petscstack,&head->stack);CHKERRQ(ierr);
4443221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4453221ece2SMatthew G. Knepley   head->stack.line[head->stack.currentsize-2] = lineno;
4463221ece2SMatthew G. Knepley #endif
4473221ece2SMatthew G. Knepley 
4483221ece2SMatthew G. Knepley   /*
44992f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
45092f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4513221ece2SMatthew G. Knepley   */
4523221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4533221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4543221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
455*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!PetscLogMallocLength,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4563221ece2SMatthew G. Knepley 
4573221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
458*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!PetscLogMallocFile,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4593221ece2SMatthew G. Knepley 
4603221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
461*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!PetscLogMallocFunction,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4623221ece2SMatthew G. Knepley     }
4633221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4643221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4653221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4663221ece2SMatthew G. Knepley   }
4673221ece2SMatthew G. Knepley   *result = (void*)inew;
4683221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4693221ece2SMatthew G. Knepley }
4703221ece2SMatthew G. Knepley 
471fe7fb379SMatthew Knepley /*@C
47292f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
473e5c89e4eSSatish Balay 
474e5c89e4eSSatish Balay     Collective on PetscViewer
475e5c89e4eSSatish Balay 
476d8d19677SJose E. Roman     Input Parameters:
477e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
478e5c89e4eSSatish Balay -    message - string printed before values
479e5c89e4eSSatish Balay 
4800841954dSBarry Smith     Options Database:
48192f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
4820841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4830841954dSBarry Smith 
484e5c89e4eSSatish Balay     Level: intermediate
485e5c89e4eSSatish Balay 
48692f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
487e5c89e4eSSatish Balay  @*/
4880841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
489e5c89e4eSSatish Balay {
4900841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4910841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
492e5c89e4eSSatish Balay   PetscErrorCode ierr;
493e5c89e4eSSatish Balay   MPI_Comm       comm;
494e5c89e4eSSatish Balay 
495e5c89e4eSSatish Balay   PetscFunctionBegin;
496e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
497e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
4980841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
499e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
500e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
501e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
502e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
5033ca90d2dSJacob Faibussowitsch   ierr = PetscViewerASCIIPrintf(viewer,"%s",message);CHKERRQ(ierr);
504e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
505ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
506ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
507ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5080841954dSBarry 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);
509ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
510ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
511ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5120841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
513ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
514ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
515ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5160841954dSBarry 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);
517ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
518ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
519ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5200841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
521e5c89e4eSSatish Balay   } else if (resident && residentmax) {
522ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
523ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
524ffc4695bSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5250841954dSBarry 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);
526ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
527ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
528ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5290841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
530e5c89e4eSSatish Balay   } else if (resident && allocated) {
531ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
532ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
533ffc4695bSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5340841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
535ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
536ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
537ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5380841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5390841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
540e5c89e4eSSatish Balay   } else if (allocated) {
541ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRMPI(ierr);
542ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRMPI(ierr);
543ffc4695bSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRMPI(ierr);
5440841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5450841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5460841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
547e5c89e4eSSatish Balay   } else {
54892f119d6SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
549e5c89e4eSSatish Balay   }
550e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
551e5c89e4eSSatish Balay   PetscFunctionReturn(0);
552e5c89e4eSSatish Balay }
553e5c89e4eSSatish Balay 
55446eb3923SBarry Smith /*@
555e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay     Not Collective
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay     Output Parameters:
560e5c89e4eSSatish Balay .   space - number of bytes currently allocated
561e5c89e4eSSatish Balay 
562e5c89e4eSSatish Balay     Level: intermediate
563e5c89e4eSSatish Balay 
564540e20f2SPierre Jolivet .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
565e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
566e5c89e4eSSatish Balay  @*/
5677087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
568e5c89e4eSSatish Balay {
569e5c89e4eSSatish Balay   PetscFunctionBegin;
570e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
571e5c89e4eSSatish Balay   PetscFunctionReturn(0);
572e5c89e4eSSatish Balay }
573e5c89e4eSSatish Balay 
574dc37d89fSBarry Smith /*@
575e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
576e5c89e4eSSatish Balay         during this run.
577e5c89e4eSSatish Balay 
578e5c89e4eSSatish Balay     Not Collective
579e5c89e4eSSatish Balay 
580e5c89e4eSSatish Balay     Output Parameters:
581e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
582e5c89e4eSSatish Balay 
583e5c89e4eSSatish Balay     Level: intermediate
584e5c89e4eSSatish Balay 
58592f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
586e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
587e5c89e4eSSatish Balay  @*/
5887087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
589e5c89e4eSSatish Balay {
590e5c89e4eSSatish Balay   PetscFunctionBegin;
591e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
592e5c89e4eSSatish Balay   PetscFunctionReturn(0);
593e5c89e4eSSatish Balay }
594e5c89e4eSSatish Balay 
595e3ed9ee7SBarry Smith /*@
596e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
597e3ed9ee7SBarry Smith 
598e3ed9ee7SBarry Smith     Not Collective
599e3ed9ee7SBarry Smith 
600e3ed9ee7SBarry Smith     Input Parameter:
601e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
602e3ed9ee7SBarry Smith 
603e3ed9ee7SBarry Smith     Level: developer
604e3ed9ee7SBarry Smith 
60592f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
606e3ed9ee7SBarry Smith           PetscMallocPopMaximumUsage()
607e3ed9ee7SBarry Smith  @*/
608e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPushMaximumUsage(int event)
609e3ed9ee7SBarry Smith {
610e3ed9ee7SBarry Smith   PetscFunctionBegin;
611e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
612e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
613e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems-1] = event;
614e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
615e3ed9ee7SBarry Smith }
616e3ed9ee7SBarry Smith 
617e3ed9ee7SBarry Smith /*@
618e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
619e3ed9ee7SBarry Smith 
620e3ed9ee7SBarry Smith     Not Collective
621e3ed9ee7SBarry Smith 
622e3ed9ee7SBarry Smith     Input Parameter:
623e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
624e3ed9ee7SBarry Smith 
625e3ed9ee7SBarry Smith     Output Parameter:
626e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
627e3ed9ee7SBarry Smith 
628e3ed9ee7SBarry Smith     Level: developer
629e3ed9ee7SBarry Smith 
63092f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
631e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
632e3ed9ee7SBarry Smith  @*/
633e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
634e3ed9ee7SBarry Smith {
635e3ed9ee7SBarry Smith   PetscFunctionBegin;
636e3ed9ee7SBarry Smith   *mu = 0;
637e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
638*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(TRMaxMemsEvents[NumTRMaxMems] != event,PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
639e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
640e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
641e3ed9ee7SBarry Smith }
642e3ed9ee7SBarry Smith 
643a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
644a64a8e02SBarry Smith /*@C
645a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
646a64a8e02SBarry Smith 
647a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
648a64a8e02SBarry Smith 
649a64a8e02SBarry Smith    Input Parameter:
650a64a8e02SBarry Smith .    ptr - the memory location
651a64a8e02SBarry Smith 
652fd292e60Sprj-    Output Parameter:
653a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
654a64a8e02SBarry Smith 
655a64a8e02SBarry Smith    Level: intermediate
656a64a8e02SBarry Smith 
65792f119d6SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView()
658a64a8e02SBarry Smith @*/
659a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
660a64a8e02SBarry Smith {
661a64a8e02SBarry Smith   TRSPACE *head;
662a64a8e02SBarry Smith 
663a64a8e02SBarry Smith   PetscFunctionBegin;
664a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
665a64a8e02SBarry Smith   *stack = &head->stack;
666a64a8e02SBarry Smith   PetscFunctionReturn(0);
667a64a8e02SBarry Smith }
66876386721SLisandro Dalcin #else
66976386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
67076386721SLisandro Dalcin {
67176386721SLisandro Dalcin   PetscFunctionBegin;
672f0ba7cfcSLisandro Dalcin   *stack = NULL;
67376386721SLisandro Dalcin   PetscFunctionReturn(0);
67476386721SLisandro Dalcin }
675a64a8e02SBarry Smith #endif
676a64a8e02SBarry Smith 
677e5c89e4eSSatish Balay /*@C
67892f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
679e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
680e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
681e5c89e4eSSatish Balay    allocated.
682e5c89e4eSSatish Balay 
68392f119d6SBarry Smith    Not Collective
684e5c89e4eSSatish Balay 
685e5c89e4eSSatish Balay    Input Parameter:
686e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
687e5c89e4eSSatish Balay 
688e5c89e4eSSatish Balay    Options Database Key:
68992f119d6SBarry Smith .  -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
690e5c89e4eSSatish Balay 
691e5c89e4eSSatish Balay    Level: intermediate
692e5c89e4eSSatish Balay 
693e5c89e4eSSatish Balay    Fortran Note:
694e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
695e5c89e4eSSatish Balay    The fp defaults to stdout.
696e5c89e4eSSatish Balay 
69795452b02SPatrick Sanan    Notes:
69892f119d6SBarry Smith      Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
699e5c89e4eSSatish Balay 
70092f119d6SBarry Smith      When called in PetscFinalize() dumps only the allocations that have not been properly freed
70192f119d6SBarry Smith 
70292f119d6SBarry Smith      PetscMallocView() prints a list of all memory ever allocated
70392f119d6SBarry Smith 
704f0b7f91aSBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
705e5c89e4eSSatish Balay @*/
7067087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
707e5c89e4eSSatish Balay {
708e5c89e4eSSatish Balay   TRSPACE        *head;
709e3ed9ee7SBarry Smith   size_t         libAlloc = 0;
710e5c89e4eSSatish Balay   PetscErrorCode ierr;
711e5c89e4eSSatish Balay   PetscMPIInt    rank;
712e5c89e4eSSatish Balay 
713e5c89e4eSSatish Balay   PetscFunctionBegin;
714ffc4695bSBarry Smith   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRMPI(ierr);
715da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
716e5c89e4eSSatish Balay   head = TRhead;
717e5c89e4eSSatish Balay   while (head) {
718608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7195486ca60SMatthew G. Knepley     head = head->next;
7205486ca60SMatthew G. Knepley   }
7215486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
7225486ca60SMatthew G. Knepley   head = TRhead;
7235486ca60SMatthew G. Knepley   while (head) {
7245486ca60SMatthew G. Knepley     PetscBool isLib;
7255486ca60SMatthew G. Knepley 
7265486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
7275486ca60SMatthew G. Knepley     if (!isLib) {
728ccd65f63SJunchao Zhang       fprintf(fp,"[%2d] %.0f bytes %s() at %s:%d\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->filename,head->lineno);
7298bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
730e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
731e5c89e4eSSatish Balay #endif
7325486ca60SMatthew G. Knepley     }
733e5c89e4eSSatish Balay     head = head->next;
734e5c89e4eSSatish Balay   }
735e5c89e4eSSatish Balay   PetscFunctionReturn(0);
736e5c89e4eSSatish Balay }
737e5c89e4eSSatish Balay 
738dc37d89fSBarry Smith /*@
73992f119d6SBarry Smith     PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
740574034a9SJed Brown 
741574034a9SJed Brown     Not Collective
742574034a9SJed Brown 
7434165533cSJose E. Roman     Input Parameter:
744574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
745574034a9SJed Brown 
746574034a9SJed Brown     Options Database Key:
74792f119d6SBarry Smith +  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
7488b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7498b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
750574034a9SJed Brown 
751574034a9SJed Brown     Level: advanced
752574034a9SJed Brown 
75392f119d6SBarry Smith     Notes: Must be called after PetscMallocSetDebug()
75492f119d6SBarry Smith 
75592f119d6SBarry Smith     Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
75692f119d6SBarry Smith 
757f0b7f91aSBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
758574034a9SJed Brown @*/
75992f119d6SBarry Smith PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
760574034a9SJed Brown {
761574034a9SJed Brown   PetscErrorCode ierr;
762574034a9SJed Brown 
763574034a9SJed Brown   PetscFunctionBegin;
76492f119d6SBarry Smith   PetscLogMalloc = 0;
76592f119d6SBarry Smith   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
766574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
767574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
768574034a9SJed Brown   PetscFunctionReturn(0);
769574034a9SJed Brown }
770574034a9SJed Brown 
771dc37d89fSBarry Smith /*@
77292f119d6SBarry Smith     PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
77318a2528dSJed Brown 
77418a2528dSJed Brown     Not Collective
77518a2528dSJed Brown 
7764165533cSJose E. Roman     Output Parameter
77718a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
77818a2528dSJed Brown 
77918a2528dSJed Brown     Options Database Key:
78092f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView()
78118a2528dSJed Brown 
78218a2528dSJed Brown     Level: advanced
78318a2528dSJed Brown 
784608c71bfSMatthew G. Knepley .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
78518a2528dSJed Brown @*/
78692f119d6SBarry Smith PetscErrorCode PetscMallocViewGet(PetscBool *logging)
78718a2528dSJed Brown {
78818a2528dSJed Brown 
78918a2528dSJed Brown   PetscFunctionBegin;
79018a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
79118a2528dSJed Brown   PetscFunctionReturn(0);
79218a2528dSJed Brown }
79318a2528dSJed Brown 
794608c71bfSMatthew G. Knepley /*@
795608c71bfSMatthew G. Knepley   PetscMallocTraceSet - Trace all calls to PetscMalloc()
796608c71bfSMatthew G. Knepley 
797608c71bfSMatthew G. Knepley   Not Collective
798608c71bfSMatthew G. Knepley 
7994165533cSJose E. Roman   Input Parameters:
800608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout
801608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
802608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
803608c71bfSMatthew G. Knepley 
804608c71bfSMatthew G. Knepley   Note:
805608c71bfSMatthew G. Knepley   The viewer should not be collective.
806608c71bfSMatthew G. Knepley 
807608c71bfSMatthew G. Knepley   Level: advanced
808608c71bfSMatthew G. Knepley 
809608c71bfSMatthew G. Knepley .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
810608c71bfSMatthew G. Knepley @*/
811608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
812608c71bfSMatthew G. Knepley {
813608c71bfSMatthew G. Knepley   PetscErrorCode ierr;
814608c71bfSMatthew G. Knepley 
815608c71bfSMatthew G. Knepley   PetscFunctionBegin;
816608c71bfSMatthew G. Knepley   if (!active) {PetscLogMallocTrace = -1; PetscFunctionReturn(0);}
817608c71bfSMatthew G. Knepley   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
818608c71bfSMatthew G. Knepley   PetscLogMallocTrace = 0;
819608c71bfSMatthew G. Knepley   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
820608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
821608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t) logmin;
822608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
823608c71bfSMatthew G. Knepley }
824608c71bfSMatthew G. Knepley 
825608c71bfSMatthew G. Knepley /*@
826608c71bfSMatthew G. Knepley   PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
827608c71bfSMatthew G. Knepley 
828608c71bfSMatthew G. Knepley   Not Collective
829608c71bfSMatthew G. Knepley 
8304165533cSJose E. Roman   Output Parameter:
831608c71bfSMatthew G. Knepley . logging - PETSC_TRUE if logging is active
832608c71bfSMatthew G. Knepley 
833608c71bfSMatthew G. Knepley   Options Database Key:
834608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView()
835608c71bfSMatthew G. Knepley 
836608c71bfSMatthew G. Knepley   Level: advanced
837608c71bfSMatthew G. Knepley 
838608c71bfSMatthew G. Knepley .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
839608c71bfSMatthew G. Knepley @*/
840608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
841608c71bfSMatthew G. Knepley {
842608c71bfSMatthew G. Knepley 
843608c71bfSMatthew G. Knepley   PetscFunctionBegin;
844608c71bfSMatthew G. Knepley   *logging = (PetscBool) (PetscLogMallocTrace >= 0);
845608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
846608c71bfSMatthew G. Knepley }
847608c71bfSMatthew G. Knepley 
848e5c89e4eSSatish Balay /*@C
84992f119d6SBarry Smith     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
85021b680ceSJed Brown        PetscMemoryGetMaximumUsage()
851e5c89e4eSSatish Balay 
85292f119d6SBarry Smith     Not Collective
853e5c89e4eSSatish Balay 
854e5c89e4eSSatish Balay     Input Parameter:
8550298fd71SBarry Smith .   fp - file pointer; or NULL
856e5c89e4eSSatish Balay 
857e5c89e4eSSatish Balay     Options Database Key:
85892f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
859e5c89e4eSSatish Balay 
860e5c89e4eSSatish Balay     Level: advanced
861e5c89e4eSSatish Balay 
862e5c89e4eSSatish Balay    Fortran Note:
86392f119d6SBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
864e5c89e4eSSatish Balay    The fp defaults to stdout.
865e5c89e4eSSatish Balay 
86692f119d6SBarry Smith    Notes:
86792f119d6SBarry Smith      PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
86892f119d6SBarry Smith 
86992f119d6SBarry Smith      PetscMemoryView() gives a brief summary of current memory usage
87092f119d6SBarry Smith 
87192f119d6SBarry Smith .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
872e5c89e4eSSatish Balay @*/
87392f119d6SBarry Smith PetscErrorCode  PetscMallocView(FILE *fp)
874e5c89e4eSSatish Balay {
87592f119d6SBarry Smith   PetscInt       i,j,n,*perm;
876e5c89e4eSSatish Balay   size_t         *shortlength;
877f56c2debSBarry Smith   int            *shortcount,err;
87892f119d6SBarry Smith   PetscMPIInt    rank;
879ace3abfcSBarry Smith   PetscBool      match;
880e5c89e4eSSatish Balay   const char     **shortfunction;
881e5c89e4eSSatish Balay   PetscLogDouble rss;
882e5c89e4eSSatish Balay   PetscErrorCode ierr;
883e5c89e4eSSatish Balay 
884e5c89e4eSSatish Balay   PetscFunctionBegin;
885ffc4695bSBarry Smith   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRMPI(ierr);
886f56c2debSBarry Smith   err = fflush(fp);
887*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
888f56c2debSBarry Smith 
889*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(PetscLogMalloc < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocView() called without call to PetscMallocViewSet() this is often due to\n                      setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
890768aa557SSatish Balay 
891da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
892f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
893e5c89e4eSSatish Balay   if (rss) {
89492f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
895e5c89e4eSSatish Balay   } else {
89692f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
897e5c89e4eSSatish Balay   }
898*2c71b3e2SJacob Faibussowitsch   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));PetscCheckFalse(!shortcount,PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
899*2c71b3e2SJacob Faibussowitsch   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));PetscCheckFalse(!shortlength,PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
900*2c71b3e2SJacob Faibussowitsch   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));PetscCheckFalse(!shortfunction,PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
90197b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
902e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
903e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
904e5c89e4eSSatish Balay       if (match) {
905e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
90659ffdab8SBarry Smith         shortcount[j]++;
907e5c89e4eSSatish Balay         goto foundit;
908e5c89e4eSSatish Balay       }
909e5c89e4eSSatish Balay     }
910e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
911e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
91259ffdab8SBarry Smith     shortcount[n]    = 1;
913e5c89e4eSSatish Balay     n++;
914e5c89e4eSSatish Balay foundit:;
915e5c89e4eSSatish Balay   }
916e5c89e4eSSatish Balay 
917*2c71b3e2SJacob Faibussowitsch   perm = (PetscInt*)malloc(n*sizeof(PetscInt));PetscCheckFalse(!perm,PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
918e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
919e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
920e5c89e4eSSatish Balay 
92192f119d6SBarry Smith   (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
922e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
92392f119d6SBarry Smith     (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
924e5c89e4eSSatish Balay   }
925e5c89e4eSSatish Balay   free(perm);
926e5c89e4eSSatish Balay   free(shortlength);
92759ffdab8SBarry Smith   free(shortcount);
928e5c89e4eSSatish Balay   free((char**)shortfunction);
929f56c2debSBarry Smith   err = fflush(fp);
930*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
931e5c89e4eSSatish Balay   PetscFunctionReturn(0);
932e5c89e4eSSatish Balay }
933e5c89e4eSSatish Balay 
934e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
935e5c89e4eSSatish Balay 
936dc37d89fSBarry Smith /*@
93792f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
938e5c89e4eSSatish Balay 
939e5c89e4eSSatish Balay     Not Collective
940e5c89e4eSSatish Balay 
941d8d19677SJose E. Roman     Input Parameters:
94292f119d6SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
9432d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
944e5c89e4eSSatish Balay 
94592f119d6SBarry Smith     Options Database:
94679dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
94792f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
94879dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
94992f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
95079dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
95179dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
952e5c89e4eSSatish Balay 
95392f119d6SBarry Smith    Level: developer
95492f119d6SBarry Smith 
95592f119d6SBarry Smith     Notes: This is called in PetscInitialize() and should not be called elsewhere
95692f119d6SBarry Smith 
95792f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
958e5c89e4eSSatish Balay @*/
95992f119d6SBarry Smith PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
960e5c89e4eSSatish Balay {
96192f119d6SBarry Smith   PetscErrorCode ierr;
96292f119d6SBarry Smith 
963e5c89e4eSSatish Balay   PetscFunctionBegin;
964*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(PetscTrMalloc == PetscTrMallocDefault,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call this routine more than once, it can only be called in PetscInitialize()");
96592f119d6SBarry Smith   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault);CHKERRQ(ierr);
96692f119d6SBarry Smith 
96792f119d6SBarry Smith   TRallocated         = 0;
96892f119d6SBarry Smith   TRfrags             = 0;
96992f119d6SBarry Smith   TRhead              = NULL;
97092f119d6SBarry Smith   TRid                = 0;
97192f119d6SBarry Smith   TRdebugLevel        = eachcall;
97292f119d6SBarry Smith   TRMaxMem            = 0;
97392f119d6SBarry Smith   PetscLogMallocMax   = 10000;
97492f119d6SBarry Smith   PetscLogMalloc      = -1;
9752d4ee042Sprj-   TRdebugIinitializenan = initializenan;
976e5c89e4eSSatish Balay   PetscFunctionReturn(0);
977e5c89e4eSSatish Balay }
9780acecf5bSBarry Smith 
979dc37d89fSBarry Smith /*@
98092f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9810acecf5bSBarry Smith 
9820acecf5bSBarry Smith     Not Collective
9830acecf5bSBarry Smith 
98492f119d6SBarry Smith     Output Parameters:
98592f119d6SBarry Smith +    basic - doing basic debugging
98692f119d6SBarry Smith .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
98779dccf82SBarry Smith -    initializenan - initializes memory with NaN
9880acecf5bSBarry Smith 
9890acecf5bSBarry Smith    Level: intermediate
9900acecf5bSBarry Smith 
99192f119d6SBarry Smith    Notes:
99279dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
9930acecf5bSBarry Smith 
99492f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
9950acecf5bSBarry Smith @*/
99692f119d6SBarry Smith PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
9970acecf5bSBarry Smith {
9980acecf5bSBarry Smith   PetscFunctionBegin;
99979dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
100079dccf82SBarry Smith   if (eachcall) *eachcall           = TRdebugLevel;
10012d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
10020acecf5bSBarry Smith   PetscFunctionReturn(0);
10030acecf5bSBarry Smith }
1004608c71bfSMatthew G. Knepley 
1005608c71bfSMatthew G. Knepley /*@
1006608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
1007608c71bfSMatthew G. Knepley 
1008608c71bfSMatthew G. Knepley   Not Collective
1009608c71bfSMatthew G. Knepley 
1010608c71bfSMatthew G. Knepley   Input Parameter:
1011608c71bfSMatthew G. Knepley . flg - PETSC_TRUE to log the requested memory size
1012608c71bfSMatthew G. Knepley 
1013608c71bfSMatthew G. Knepley   Options Database:
1014608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1015608c71bfSMatthew G. Knepley 
1016608c71bfSMatthew G. Knepley   Level: developer
1017608c71bfSMatthew G. Knepley 
1018608c71bfSMatthew G. Knepley .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
1019608c71bfSMatthew G. Knepley @*/
1020608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1021608c71bfSMatthew G. Knepley {
1022608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1023608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
1024608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1025608c71bfSMatthew G. Knepley }
1026608c71bfSMatthew G. Knepley 
1027608c71bfSMatthew G. Knepley /*@
1028608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1029608c71bfSMatthew G. Knepley 
1030608c71bfSMatthew G. Knepley   Not Collective
1031608c71bfSMatthew G. Knepley 
1032608c71bfSMatthew G. Knepley   Output Parameter:
1033608c71bfSMatthew G. Knepley . flg - PETSC_TRUE if we log the requested memory size
1034608c71bfSMatthew G. Knepley 
1035608c71bfSMatthew G. Knepley   Level: developer
1036608c71bfSMatthew G. Knepley 
1037608c71bfSMatthew G. Knepley .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1038608c71bfSMatthew G. Knepley @*/
1039608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1040608c71bfSMatthew G. Knepley {
1041608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1042608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
1043608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1044608c71bfSMatthew G. Knepley }
1045