xref: /petsc/src/sys/memory/mtr.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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);
1835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew));
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)
2135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStackCopy(&petscstack,&head->stack));
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*28b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
241a297a907SKarl Rupp 
242a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
243*28b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
244a297a907SKarl Rupp 
245a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
246*28b400f6SJacob Faibussowitsch       PetscCheck(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) {
2535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer,"Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null"));
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;
2730700a824SBarry Smith   PetscClassId   *nend;
274e5c89e4eSSatish Balay 
275e5c89e4eSSatish Balay   PetscFunctionBegin;
276e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
27749d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
278e5c89e4eSSatish Balay 
2795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMallocValidate(lineno,function,filename));
280e5c89e4eSSatish Balay 
281e5c89e4eSSatish Balay   ahead = a;
282e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
283e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
284e5c89e4eSSatish Balay 
2850700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
286ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
287e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
288e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
289e5c89e4eSSatish Balay   }
2900700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2910700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
292e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
293ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
294e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
295e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
296ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
297e5c89e4eSSatish Balay       } else {
298ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
299e5c89e4eSSatish Balay       }
300e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
301e5c89e4eSSatish Balay     } else {
302e5c89e4eSSatish Balay       /* Damaged tail */
303ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n",function,filename,lineno);
304e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
305ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
306e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
307e5c89e4eSSatish Balay     }
308e5c89e4eSSatish Balay   }
309608c71bfSMatthew G. Knepley   if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) {
3105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free  %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null"));
311608c71bfSMatthew G. Knepley   }
312e5c89e4eSSatish Balay   /* Mark the location freed */
313e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
314e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
315608c71bfSMatthew G. Knepley   if (lineno > 0 && lineno < 50000) {
316608c71bfSMatthew G. Knepley     head->lineno       = lineno;
317608c71bfSMatthew G. Knepley     head->filename     = filename;
318e5c89e4eSSatish Balay     head->functionname = function;
319e5c89e4eSSatish Balay   } else {
320e5c89e4eSSatish Balay     head->lineno = -head->lineno;
321e5c89e4eSSatish Balay   }
322608c71bfSMatthew G. Knepley   asize = TRrequestedSize ? head->rsize : head->size;
3232c71b3e2SJacob Faibussowitsch   PetscCheckFalse(TRallocated < asize,PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
324608c71bfSMatthew G. Knepley   TRallocated -= asize;
325e5c89e4eSSatish Balay   TRfrags--;
326e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
327e5c89e4eSSatish Balay   else TRhead = head->next;
328e5c89e4eSSatish Balay 
329e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
3305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFreeAlign(a,lineno,function,filename));
331e5c89e4eSSatish Balay   PetscFunctionReturn(0);
332e5c89e4eSSatish Balay }
333e5c89e4eSSatish Balay 
3343221ece2SMatthew G. Knepley /*
3353221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3363221ece2SMatthew G. Knepley 
3373221ece2SMatthew G. Knepley   Input Parameters:
3383221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3393221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3403221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
34192f119d6SBarry Smith - result - original memory
3423221ece2SMatthew G. Knepley 
3433221ece2SMatthew G. Knepley   Output Parameter:
3443221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3453221ece2SMatthew G. Knepley 
3463221ece2SMatthew G. Knepley   Level: developer
3473221ece2SMatthew G. Knepley 
3483221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3493221ece2SMatthew G. Knepley */
3503221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3513221ece2SMatthew G. Knepley {
3523221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3533221ece2SMatthew G. Knepley   TRSPACE        *head;
3543221ece2SMatthew G. Knepley   char           *ahead, *inew;
3553221ece2SMatthew G. Knepley   PetscClassId   *nend;
3563221ece2SMatthew G. Knepley   size_t         nsize;
3573221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3583221ece2SMatthew G. Knepley 
3593221ece2SMatthew G. Knepley   PetscFunctionBegin;
36092f119d6SBarry Smith   /* Realloc requests zero space so just free the current space */
361c22f1541SToby Isaac   if (!len) {
3625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTrFreeDefault(*result,lineno,function,filename));
363c22f1541SToby Isaac     *result = NULL;
364c22f1541SToby Isaac     PetscFunctionReturn(0);
365c22f1541SToby Isaac   }
36692f119d6SBarry Smith   /* If the orginal space was NULL just use the regular malloc() */
367f590eff4SLisandro Dalcin   if (!*result) {
3685f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result));
369f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
370f590eff4SLisandro Dalcin   }
3713221ece2SMatthew G. Knepley 
37238548759SBarry Smith   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
3733221ece2SMatthew G. Knepley 
3743221ece2SMatthew G. Knepley   ahead = a;
3753221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3763221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3773221ece2SMatthew G. Knepley   inew  = a;
3783221ece2SMatthew G. Knepley 
3793221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
380ccd65f63SJunchao Zhang     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
3813221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3823221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3833221ece2SMatthew G. Knepley   }
3843221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3853221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3863221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
387ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
3883221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3893221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
390ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
3913221ece2SMatthew G. Knepley       } else {
392ccd65f63SJunchao Zhang         (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,-head->lineno);
3933221ece2SMatthew G. Knepley       }
3943221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3953221ece2SMatthew G. Knepley     } else {
3963221ece2SMatthew G. Knepley       /* Damaged tail */
397ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n",function,filename,lineno);
3983221ece2SMatthew 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);
399ccd65f63SJunchao Zhang       (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n",head->functionname,head->filename,head->lineno);
4003221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
4013221ece2SMatthew G. Knepley     }
4023221ece2SMatthew G. Knepley   }
4033221ece2SMatthew G. Knepley 
40492f119d6SBarry Smith   /* remove original reference to the memory allocated from the PETSc debugging heap */
405608c71bfSMatthew G. Knepley   TRallocated -= TRrequestedSize ? head->rsize : head->size;
4063221ece2SMatthew G. Knepley   TRfrags--;
4073221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4083221ece2SMatthew G. Knepley   else TRhead = head->next;
4093221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4103221ece2SMatthew G. Knepley 
4113221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
4125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew));
4133221ece2SMatthew G. Knepley 
4143221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
4153221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4163221ece2SMatthew G. Knepley 
4173221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4183221ece2SMatthew G. Knepley   head->next   = TRhead;
4193221ece2SMatthew G. Knepley   TRhead       = head;
4203221ece2SMatthew G. Knepley   head->prev   = NULL;
4213221ece2SMatthew G. Knepley   head->size   = nsize;
422608c71bfSMatthew G. Knepley   head->rsize  = len;
423e269983cSBarry Smith   head->id     = TRid++;
4243221ece2SMatthew G. Knepley   head->lineno = lineno;
4253221ece2SMatthew G. Knepley 
4263221ece2SMatthew G. Knepley   head->filename                 = filename;
4273221ece2SMatthew G. Knepley   head->functionname             = function;
4283221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4293221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4303221ece2SMatthew G. Knepley 
431608c71bfSMatthew G. Knepley   TRallocated += TRrequestedSize ? head->rsize : head->size;
4323221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
433e3ed9ee7SBarry Smith   if (PetscLogMemory) {
434e3ed9ee7SBarry Smith     PetscInt i;
435e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
436e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
437e3ed9ee7SBarry Smith     }
438e3ed9ee7SBarry Smith   }
4393221ece2SMatthew G. Knepley   TRfrags++;
4403221ece2SMatthew G. Knepley 
4413221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStackCopy(&petscstack,&head->stack));
4433221ece2SMatthew G. Knepley   /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4443221ece2SMatthew G. Knepley   head->stack.line[head->stack.currentsize-2] = lineno;
4453221ece2SMatthew G. Knepley #endif
4463221ece2SMatthew G. Knepley 
4473221ece2SMatthew G. Knepley   /*
44892f119d6SBarry Smith          Allow logging of all mallocs made. This adds a new entry to the list of allocated memory
44992f119d6SBarry Smith          and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView()
4503221ece2SMatthew G. Knepley   */
4513221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4523221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4533221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
454*28b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocLength,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4553221ece2SMatthew G. Knepley 
4563221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
457*28b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFile,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4583221ece2SMatthew G. Knepley 
4593221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
460*28b400f6SJacob Faibussowitsch       PetscCheck(PetscLogMallocFunction,PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4613221ece2SMatthew G. Knepley     }
4623221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4633221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4643221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4653221ece2SMatthew G. Knepley   }
4663221ece2SMatthew G. Knepley   *result = (void*)inew;
4673221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4683221ece2SMatthew G. Knepley }
4693221ece2SMatthew G. Knepley 
470fe7fb379SMatthew Knepley /*@C
47192f119d6SBarry Smith     PetscMemoryView - Shows the amount of memory currently being used in a communicator.
472e5c89e4eSSatish Balay 
473e5c89e4eSSatish Balay     Collective on PetscViewer
474e5c89e4eSSatish Balay 
475d8d19677SJose E. Roman     Input Parameters:
476e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
477e5c89e4eSSatish Balay -    message - string printed before values
478e5c89e4eSSatish Balay 
4790841954dSBarry Smith     Options Database:
48092f119d6SBarry Smith +    -malloc_debug - have PETSc track how much memory it has allocated
4810841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4820841954dSBarry Smith 
483e5c89e4eSSatish Balay     Level: intermediate
484e5c89e4eSSatish Balay 
48592f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage(), PetscMallocView()
486e5c89e4eSSatish Balay  @*/
4870841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
488e5c89e4eSSatish Balay {
4890841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4900841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
491e5c89e4eSSatish Balay   MPI_Comm       comm;
492e5c89e4eSSatish Balay 
493e5c89e4eSSatish Balay   PetscFunctionBegin;
494e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
4955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMallocGetCurrentUsage(&allocated));
4965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMallocGetMaximumUsage(&allocatedmax));
4975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemoryGetCurrentUsage(&resident));
4985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemoryGetMaximumUsage(&residentmax));
499e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
5005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)viewer,&comm));
5015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIPrintf(viewer,"%s",message));
502e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
5035f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5045f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5055f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax));
5075f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5085f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5095f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident));
5115f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5125f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5135f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5145f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n",gallocatedmax,maxgallocatedmax,mingallocatedmax));
5155f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5165f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5175f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated));
519e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5205f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5215f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5225f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5235f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Maximum (over computational time) process memory:        total %5.4e max %5.4e min %5.4e\n",gresidentmax,maxgresidentmax,mingresidentmax));
5245f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5255f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5265f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5275f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident));
528e5c89e4eSSatish Balay   } else if (resident && allocated) {
5295f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5305f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5315f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident));
5335f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5345f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5355f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated));
5375f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n"));
538e5c89e4eSSatish Balay   } else if (allocated) {
5395f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm));
5405f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm));
5415f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm));
5425f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated));
5435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n"));
5445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n"));
545e5c89e4eSSatish Balay   } else {
5465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n"));
547e5c89e4eSSatish Balay   }
5485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFlush(viewer));
549e5c89e4eSSatish Balay   PetscFunctionReturn(0);
550e5c89e4eSSatish Balay }
551e5c89e4eSSatish Balay 
55246eb3923SBarry Smith /*@
553e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay     Not Collective
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay     Output Parameters:
558e5c89e4eSSatish Balay .   space - number of bytes currently allocated
559e5c89e4eSSatish Balay 
560e5c89e4eSSatish Balay     Level: intermediate
561e5c89e4eSSatish Balay 
562540e20f2SPierre Jolivet .seealso: PetscMallocDump(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
563e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
564e5c89e4eSSatish Balay  @*/
5657087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
566e5c89e4eSSatish Balay {
567e5c89e4eSSatish Balay   PetscFunctionBegin;
568e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
569e5c89e4eSSatish Balay   PetscFunctionReturn(0);
570e5c89e4eSSatish Balay }
571e5c89e4eSSatish Balay 
572dc37d89fSBarry Smith /*@
573e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
574e5c89e4eSSatish Balay         during this run.
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay     Not Collective
577e5c89e4eSSatish Balay 
578e5c89e4eSSatish Balay     Output Parameters:
579e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
580e5c89e4eSSatish Balay 
581e5c89e4eSSatish Balay     Level: intermediate
582e5c89e4eSSatish Balay 
58392f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
584e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
585e5c89e4eSSatish Balay  @*/
5867087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
587e5c89e4eSSatish Balay {
588e5c89e4eSSatish Balay   PetscFunctionBegin;
589e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
590e5c89e4eSSatish Balay   PetscFunctionReturn(0);
591e5c89e4eSSatish Balay }
592e5c89e4eSSatish Balay 
593e3ed9ee7SBarry Smith /*@
594e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
595e3ed9ee7SBarry Smith 
596e3ed9ee7SBarry Smith     Not Collective
597e3ed9ee7SBarry Smith 
598e3ed9ee7SBarry Smith     Input Parameter:
599e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
600e3ed9ee7SBarry Smith 
601e3ed9ee7SBarry Smith     Level: developer
602e3ed9ee7SBarry Smith 
60392f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
604e3ed9ee7SBarry Smith           PetscMallocPopMaximumUsage()
605e3ed9ee7SBarry Smith  @*/
606e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPushMaximumUsage(int event)
607e3ed9ee7SBarry Smith {
608e3ed9ee7SBarry Smith   PetscFunctionBegin;
609e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
610e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
611e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems-1] = event;
612e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
613e3ed9ee7SBarry Smith }
614e3ed9ee7SBarry Smith 
615e3ed9ee7SBarry Smith /*@
616e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
617e3ed9ee7SBarry Smith 
618e3ed9ee7SBarry Smith     Not Collective
619e3ed9ee7SBarry Smith 
620e3ed9ee7SBarry Smith     Input Parameter:
621e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
622e3ed9ee7SBarry Smith 
623e3ed9ee7SBarry Smith     Output Parameter:
624e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
625e3ed9ee7SBarry Smith 
626e3ed9ee7SBarry Smith     Level: developer
627e3ed9ee7SBarry Smith 
62892f119d6SBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
629e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
630e3ed9ee7SBarry Smith  @*/
631e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
632e3ed9ee7SBarry Smith {
633e3ed9ee7SBarry Smith   PetscFunctionBegin;
634e3ed9ee7SBarry Smith   *mu = 0;
635e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
6362c71b3e2SJacob Faibussowitsch   PetscCheckFalse(TRMaxMemsEvents[NumTRMaxMems] != event,PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
637e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
638e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
639e3ed9ee7SBarry Smith }
640e3ed9ee7SBarry Smith 
641a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
642a64a8e02SBarry Smith /*@C
643a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
644a64a8e02SBarry Smith 
645a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
646a64a8e02SBarry Smith 
647a64a8e02SBarry Smith    Input Parameter:
648a64a8e02SBarry Smith .    ptr - the memory location
649a64a8e02SBarry Smith 
650fd292e60Sprj-    Output Parameter:
651a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
652a64a8e02SBarry Smith 
653a64a8e02SBarry Smith    Level: intermediate
654a64a8e02SBarry Smith 
65592f119d6SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView()
656a64a8e02SBarry Smith @*/
657a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
658a64a8e02SBarry Smith {
659a64a8e02SBarry Smith   TRSPACE *head;
660a64a8e02SBarry Smith 
661a64a8e02SBarry Smith   PetscFunctionBegin;
662a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
663a64a8e02SBarry Smith   *stack = &head->stack;
664a64a8e02SBarry Smith   PetscFunctionReturn(0);
665a64a8e02SBarry Smith }
66676386721SLisandro Dalcin #else
66776386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
66876386721SLisandro Dalcin {
66976386721SLisandro Dalcin   PetscFunctionBegin;
670f0ba7cfcSLisandro Dalcin   *stack = NULL;
67176386721SLisandro Dalcin   PetscFunctionReturn(0);
67276386721SLisandro Dalcin }
673a64a8e02SBarry Smith #endif
674a64a8e02SBarry Smith 
675e5c89e4eSSatish Balay /*@C
67692f119d6SBarry Smith    PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information
677e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
678e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
679e5c89e4eSSatish Balay    allocated.
680e5c89e4eSSatish Balay 
68192f119d6SBarry Smith    Not Collective
682e5c89e4eSSatish Balay 
683e5c89e4eSSatish Balay    Input Parameter:
684e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
685e5c89e4eSSatish Balay 
686e5c89e4eSSatish Balay    Options Database Key:
68792f119d6SBarry Smith .  -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize()
688e5c89e4eSSatish Balay 
689e5c89e4eSSatish Balay    Level: intermediate
690e5c89e4eSSatish Balay 
691e5c89e4eSSatish Balay    Fortran Note:
692e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
693e5c89e4eSSatish Balay    The fp defaults to stdout.
694e5c89e4eSSatish Balay 
69595452b02SPatrick Sanan    Notes:
69692f119d6SBarry Smith      Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed.
697e5c89e4eSSatish Balay 
69892f119d6SBarry Smith      When called in PetscFinalize() dumps only the allocations that have not been properly freed
69992f119d6SBarry Smith 
70092f119d6SBarry Smith      PetscMallocView() prints a list of all memory ever allocated
70192f119d6SBarry Smith 
702f0b7f91aSBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocView(), PetscMallocViewSet(), PetscMallocValidate()
703e5c89e4eSSatish Balay @*/
7047087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
705e5c89e4eSSatish Balay {
706e5c89e4eSSatish Balay   TRSPACE        *head;
707e3ed9ee7SBarry Smith   size_t         libAlloc = 0;
708e5c89e4eSSatish Balay   PetscMPIInt    rank;
709e5c89e4eSSatish Balay 
710e5c89e4eSSatish Balay   PetscFunctionBegin;
7115f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(MPI_COMM_WORLD,&rank));
712da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
713e5c89e4eSSatish Balay   head = TRhead;
714e5c89e4eSSatish Balay   while (head) {
715608c71bfSMatthew G. Knepley     libAlloc += TRrequestedSize ? head->rsize : head->size;
7165486ca60SMatthew G. Knepley     head = head->next;
7175486ca60SMatthew G. Knepley   }
7185486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
7195486ca60SMatthew G. Knepley   head = TRhead;
7205486ca60SMatthew G. Knepley   while (head) {
7215486ca60SMatthew G. Knepley     PetscBool isLib;
7225486ca60SMatthew G. Knepley 
7235f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib));
7245486ca60SMatthew G. Knepley     if (!isLib) {
725ccd65f63SJunchao Zhang       fprintf(fp,"[%2d] %.0f bytes %s() at %s:%d\n",rank,(PetscLogDouble) (TRrequestedSize ? head->rsize : head->size),head->functionname,head->filename,head->lineno);
7268bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
7275f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStackPrint(&head->stack,fp));
728e5c89e4eSSatish Balay #endif
7295486ca60SMatthew G. Knepley     }
730e5c89e4eSSatish Balay     head = head->next;
731e5c89e4eSSatish Balay   }
732e5c89e4eSSatish Balay   PetscFunctionReturn(0);
733e5c89e4eSSatish Balay }
734e5c89e4eSSatish Balay 
735dc37d89fSBarry Smith /*@
73692f119d6SBarry Smith     PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view
737574034a9SJed Brown 
738574034a9SJed Brown     Not Collective
739574034a9SJed Brown 
7404165533cSJose E. Roman     Input Parameter:
741574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
742574034a9SJed Brown 
743574034a9SJed Brown     Options Database Key:
74492f119d6SBarry Smith +  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
7458b254c29SBarry Smith .  -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used
7468b254c29SBarry Smith -  -log_view_memory - view the memory usage also with the -log_view option
747574034a9SJed Brown 
748574034a9SJed Brown     Level: advanced
749574034a9SJed Brown 
75092f119d6SBarry Smith     Notes: Must be called after PetscMallocSetDebug()
75192f119d6SBarry Smith 
75292f119d6SBarry Smith     Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available
75392f119d6SBarry Smith 
754f0b7f91aSBarry Smith .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocViewSet(), PetscMallocTraceSet(), PetscMallocValidate()
755574034a9SJed Brown @*/
75692f119d6SBarry Smith PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin)
757574034a9SJed Brown {
758574034a9SJed Brown   PetscFunctionBegin;
75992f119d6SBarry Smith   PetscLogMalloc = 0;
7605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemorySetGetMaximumUsage());
761574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
762574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
763574034a9SJed Brown   PetscFunctionReturn(0);
764574034a9SJed Brown }
765574034a9SJed Brown 
766dc37d89fSBarry Smith /*@
76792f119d6SBarry Smith     PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged
76818a2528dSJed Brown 
76918a2528dSJed Brown     Not Collective
77018a2528dSJed Brown 
7714165533cSJose E. Roman     Output Parameter
77218a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
77318a2528dSJed Brown 
77418a2528dSJed Brown     Options Database Key:
77592f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView()
77618a2528dSJed Brown 
77718a2528dSJed Brown     Level: advanced
77818a2528dSJed Brown 
779608c71bfSMatthew G. Knepley .seealso: PetscMallocDump(), PetscMallocView(), PetscMallocTraceGet()
78018a2528dSJed Brown @*/
78192f119d6SBarry Smith PetscErrorCode PetscMallocViewGet(PetscBool *logging)
78218a2528dSJed Brown {
78318a2528dSJed Brown   PetscFunctionBegin;
78418a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
78518a2528dSJed Brown   PetscFunctionReturn(0);
78618a2528dSJed Brown }
78718a2528dSJed Brown 
788608c71bfSMatthew G. Knepley /*@
789608c71bfSMatthew G. Knepley   PetscMallocTraceSet - Trace all calls to PetscMalloc()
790608c71bfSMatthew G. Knepley 
791608c71bfSMatthew G. Knepley   Not Collective
792608c71bfSMatthew G. Knepley 
7934165533cSJose E. Roman   Input Parameters:
794608c71bfSMatthew G. Knepley + viewer - The viewer to use for tracing, or NULL to use stdout
795608c71bfSMatthew G. Knepley . active - Flag to activate or deactivate tracing
796608c71bfSMatthew G. Knepley - logmin - The smallest memory size that will be logged
797608c71bfSMatthew G. Knepley 
798608c71bfSMatthew G. Knepley   Note:
799608c71bfSMatthew G. Knepley   The viewer should not be collective.
800608c71bfSMatthew G. Knepley 
801608c71bfSMatthew G. Knepley   Level: advanced
802608c71bfSMatthew G. Knepley 
803608c71bfSMatthew G. Knepley .seealso: PetscMallocTraceGet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
804608c71bfSMatthew G. Knepley @*/
805608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin)
806608c71bfSMatthew G. Knepley {
807608c71bfSMatthew G. Knepley   PetscFunctionBegin;
808608c71bfSMatthew G. Knepley   if (!active) {PetscLogMallocTrace = -1; PetscFunctionReturn(0);}
809608c71bfSMatthew G. Knepley   PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer;
810608c71bfSMatthew G. Knepley   PetscLogMallocTrace = 0;
8115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemorySetGetMaximumUsage());
812608c71bfSMatthew G. Knepley   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
813608c71bfSMatthew G. Knepley   PetscLogMallocTraceThreshold = (size_t) logmin;
814608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
815608c71bfSMatthew G. Knepley }
816608c71bfSMatthew G. Knepley 
817608c71bfSMatthew G. Knepley /*@
818608c71bfSMatthew G. Knepley   PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced
819608c71bfSMatthew G. Knepley 
820608c71bfSMatthew G. Knepley   Not Collective
821608c71bfSMatthew G. Knepley 
8224165533cSJose E. Roman   Output Parameter:
823608c71bfSMatthew G. Knepley . logging - PETSC_TRUE if logging is active
824608c71bfSMatthew G. Knepley 
825608c71bfSMatthew G. Knepley   Options Database Key:
826608c71bfSMatthew G. Knepley . -malloc_view <optional filename> - Activates PetscMallocView()
827608c71bfSMatthew G. Knepley 
828608c71bfSMatthew G. Knepley   Level: advanced
829608c71bfSMatthew G. Knepley 
830608c71bfSMatthew G. Knepley .seealso: PetscMallocTraceSet(), PetscMallocViewGet(), PetscMallocDump(), PetscMallocView()
831608c71bfSMatthew G. Knepley @*/
832608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocTraceGet(PetscBool *logging)
833608c71bfSMatthew G. Knepley {
834608c71bfSMatthew G. Knepley   PetscFunctionBegin;
835608c71bfSMatthew G. Knepley   *logging = (PetscBool) (PetscLogMallocTrace >= 0);
836608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
837608c71bfSMatthew G. Knepley }
838608c71bfSMatthew G. Knepley 
839e5c89e4eSSatish Balay /*@C
84092f119d6SBarry Smith     PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls
84121b680ceSJed Brown        PetscMemoryGetMaximumUsage()
842e5c89e4eSSatish Balay 
84392f119d6SBarry Smith     Not Collective
844e5c89e4eSSatish Balay 
845e5c89e4eSSatish Balay     Input Parameter:
8460298fd71SBarry Smith .   fp - file pointer; or NULL
847e5c89e4eSSatish Balay 
848e5c89e4eSSatish Balay     Options Database Key:
84992f119d6SBarry Smith .  -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize()
850e5c89e4eSSatish Balay 
851e5c89e4eSSatish Balay     Level: advanced
852e5c89e4eSSatish Balay 
853e5c89e4eSSatish Balay    Fortran Note:
85492f119d6SBarry Smith    The calling sequence in Fortran is PetscMallocView(integer ierr)
855e5c89e4eSSatish Balay    The fp defaults to stdout.
856e5c89e4eSSatish Balay 
85792f119d6SBarry Smith    Notes:
85892f119d6SBarry Smith      PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated
85992f119d6SBarry Smith 
86092f119d6SBarry Smith      PetscMemoryView() gives a brief summary of current memory usage
86192f119d6SBarry Smith 
86292f119d6SBarry Smith .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocViewSet(), PetscMemoryView()
863e5c89e4eSSatish Balay @*/
86492f119d6SBarry Smith PetscErrorCode  PetscMallocView(FILE *fp)
865e5c89e4eSSatish Balay {
86692f119d6SBarry Smith   PetscInt       i,j,n,*perm;
867e5c89e4eSSatish Balay   size_t         *shortlength;
868f56c2debSBarry Smith   int            *shortcount,err;
86992f119d6SBarry Smith   PetscMPIInt    rank;
870ace3abfcSBarry Smith   PetscBool      match;
871e5c89e4eSSatish Balay   const char     **shortfunction;
872e5c89e4eSSatish Balay   PetscLogDouble rss;
873e5c89e4eSSatish Balay 
874e5c89e4eSSatish Balay   PetscFunctionBegin;
8755f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(MPI_COMM_WORLD,&rank));
876f56c2debSBarry Smith   err = fflush(fp);
877*28b400f6SJacob Faibussowitsch   PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
878f56c2debSBarry Smith 
8792c71b3e2SJacob 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()");
880768aa557SSatish Balay 
881da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
8825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemoryGetMaximumUsage(&rss));
883e5c89e4eSSatish Balay   if (rss) {
88492f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
885e5c89e4eSSatish Balay   } else {
88692f119d6SBarry Smith     (void) fprintf(fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
887e5c89e4eSSatish Balay   }
888*28b400f6SJacob Faibussowitsch   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));PetscCheck(shortcount,PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
889*28b400f6SJacob Faibussowitsch   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));PetscCheck(shortlength,PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
890*28b400f6SJacob Faibussowitsch   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));PetscCheck(shortfunction,PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
89197b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
892e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
8935f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match));
894e5c89e4eSSatish Balay       if (match) {
895e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
89659ffdab8SBarry Smith         shortcount[j]++;
897e5c89e4eSSatish Balay         goto foundit;
898e5c89e4eSSatish Balay       }
899e5c89e4eSSatish Balay     }
900e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
901e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
90259ffdab8SBarry Smith     shortcount[n]    = 1;
903e5c89e4eSSatish Balay     n++;
904e5c89e4eSSatish Balay foundit:;
905e5c89e4eSSatish Balay   }
906e5c89e4eSSatish Balay 
907*28b400f6SJacob Faibussowitsch   perm = (PetscInt*)malloc(n*sizeof(PetscInt));PetscCheck(perm,PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
908e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
9095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSortStrWithPermutation(n,(const char**)shortfunction,perm));
910e5c89e4eSSatish Balay 
91192f119d6SBarry Smith   (void) fprintf(fp,"[%d] Memory usage sorted by function\n",rank);
912e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
91392f119d6SBarry Smith     (void) fprintf(fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
914e5c89e4eSSatish Balay   }
915e5c89e4eSSatish Balay   free(perm);
916e5c89e4eSSatish Balay   free(shortlength);
91759ffdab8SBarry Smith   free(shortcount);
918e5c89e4eSSatish Balay   free((char**)shortfunction);
919f56c2debSBarry Smith   err = fflush(fp);
920*28b400f6SJacob Faibussowitsch   PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
921e5c89e4eSSatish Balay   PetscFunctionReturn(0);
922e5c89e4eSSatish Balay }
923e5c89e4eSSatish Balay 
924e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
925e5c89e4eSSatish Balay 
926dc37d89fSBarry Smith /*@
92792f119d6SBarry Smith     PetscMallocSetDebug - Set's PETSc memory debugging
928e5c89e4eSSatish Balay 
929e5c89e4eSSatish Balay     Not Collective
930e5c89e4eSSatish Balay 
931d8d19677SJose E. Roman     Input Parameters:
93292f119d6SBarry Smith +   eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree()
9332d4ee042Sprj- -   initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays
934e5c89e4eSSatish Balay 
93592f119d6SBarry Smith     Options Database:
93679dccf82SBarry Smith +   -malloc_debug <true or false> - turns on or off debugging
93792f119d6SBarry Smith .   -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored
93879dccf82SBarry Smith .   -malloc_view_threshold t - log only allocations larger than t
93992f119d6SBarry Smith .   -malloc_dump <filename> - print a list of all memory that has not been freed
94079dccf82SBarry Smith .   -malloc no - (deprecated) same as -malloc_debug no
94179dccf82SBarry Smith -   -malloc_log - (deprecated) same as -malloc_view
942e5c89e4eSSatish Balay 
94392f119d6SBarry Smith    Level: developer
94492f119d6SBarry Smith 
94592f119d6SBarry Smith     Notes: This is called in PetscInitialize() and should not be called elsewhere
94692f119d6SBarry Smith 
94792f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocGetDebug()
948e5c89e4eSSatish Balay @*/
94992f119d6SBarry Smith PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan)
950e5c89e4eSSatish Balay {
951e5c89e4eSSatish Balay   PetscFunctionBegin;
9522c71b3e2SJacob 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()");
9535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault,PetscTrReallocDefault));
95492f119d6SBarry Smith 
95592f119d6SBarry Smith   TRallocated         = 0;
95692f119d6SBarry Smith   TRfrags             = 0;
95792f119d6SBarry Smith   TRhead              = NULL;
95892f119d6SBarry Smith   TRid                = 0;
95992f119d6SBarry Smith   TRdebugLevel        = eachcall;
96092f119d6SBarry Smith   TRMaxMem            = 0;
96192f119d6SBarry Smith   PetscLogMallocMax   = 10000;
96292f119d6SBarry Smith   PetscLogMalloc      = -1;
9632d4ee042Sprj-   TRdebugIinitializenan = initializenan;
964e5c89e4eSSatish Balay   PetscFunctionReturn(0);
965e5c89e4eSSatish Balay }
9660acecf5bSBarry Smith 
967dc37d89fSBarry Smith /*@
96892f119d6SBarry Smith     PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing.
9690acecf5bSBarry Smith 
9700acecf5bSBarry Smith     Not Collective
9710acecf5bSBarry Smith 
97292f119d6SBarry Smith     Output Parameters:
97392f119d6SBarry Smith +    basic - doing basic debugging
97492f119d6SBarry Smith .    eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree()
97579dccf82SBarry Smith -    initializenan - initializes memory with NaN
9760acecf5bSBarry Smith 
9770acecf5bSBarry Smith    Level: intermediate
9780acecf5bSBarry Smith 
97992f119d6SBarry Smith    Notes:
98079dccf82SBarry Smith      By default, the debug version always does some debugging unless you run with -malloc_debug no
9810acecf5bSBarry Smith 
98292f119d6SBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate(), PetscMallocSetDebug()
9830acecf5bSBarry Smith @*/
98492f119d6SBarry Smith PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan)
9850acecf5bSBarry Smith {
9860acecf5bSBarry Smith   PetscFunctionBegin;
98779dccf82SBarry Smith   if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE;
98879dccf82SBarry Smith   if (eachcall) *eachcall           = TRdebugLevel;
9892d4ee042Sprj-   if (initializenan) *initializenan = TRdebugIinitializenan;
9900acecf5bSBarry Smith   PetscFunctionReturn(0);
9910acecf5bSBarry Smith }
992608c71bfSMatthew G. Knepley 
993608c71bfSMatthew G. Knepley /*@
994608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size
995608c71bfSMatthew G. Knepley 
996608c71bfSMatthew G. Knepley   Not Collective
997608c71bfSMatthew G. Knepley 
998608c71bfSMatthew G. Knepley   Input Parameter:
999608c71bfSMatthew G. Knepley . flg - PETSC_TRUE to log the requested memory size
1000608c71bfSMatthew G. Knepley 
1001608c71bfSMatthew G. Knepley   Options Database:
1002608c71bfSMatthew G. Knepley . -malloc_requested_size <bool> - Sets this flag
1003608c71bfSMatthew G. Knepley 
1004608c71bfSMatthew G. Knepley   Level: developer
1005608c71bfSMatthew G. Knepley 
1006608c71bfSMatthew G. Knepley .seealso: PetscMallocLogRequestedSizeGet(), PetscMallocViewSet()
1007608c71bfSMatthew G. Knepley @*/
1008608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg)
1009608c71bfSMatthew G. Knepley {
1010608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1011608c71bfSMatthew G. Knepley   TRrequestedSize = flg;
1012608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1013608c71bfSMatthew G. Knepley }
1014608c71bfSMatthew G. Knepley 
1015608c71bfSMatthew G. Knepley /*@
1016608c71bfSMatthew G. Knepley   PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size
1017608c71bfSMatthew G. Knepley 
1018608c71bfSMatthew G. Knepley   Not Collective
1019608c71bfSMatthew G. Knepley 
1020608c71bfSMatthew G. Knepley   Output Parameter:
1021608c71bfSMatthew G. Knepley . flg - PETSC_TRUE if we log the requested memory size
1022608c71bfSMatthew G. Knepley 
1023608c71bfSMatthew G. Knepley   Level: developer
1024608c71bfSMatthew G. Knepley 
1025608c71bfSMatthew G. Knepley .seealso: PetscMallocLogRequestedSizeSetinalSizeSet(), PetscMallocViewSet()
1026608c71bfSMatthew G. Knepley @*/
1027608c71bfSMatthew G. Knepley PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg)
1028608c71bfSMatthew G. Knepley {
1029608c71bfSMatthew G. Knepley   PetscFunctionBegin;
1030608c71bfSMatthew G. Knepley   *flg = TRrequestedSize;
1031608c71bfSMatthew G. Knepley   PetscFunctionReturn(0);
1032608c71bfSMatthew G. Knepley }
1033