xref: /petsc/src/sys/memory/mtr.c (revision e3ed9ee741a88589f5afab2bd2b2738386c1608b)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay      Interface to malloc() and free(). This code allows for
4e5c89e4eSSatish Balay   logging of memory usage and some error checking
5e5c89e4eSSatish Balay */
6c6db04a5SJed Brown #include <petscsys.h>           /*I "petscsys.h" I*/
7665c2dedSJed Brown #include <petscviewer.h>
8e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
9e5c89e4eSSatish Balay #include <malloc.h>
10e5c89e4eSSatish Balay #endif
11e5c89e4eSSatish Balay 
12e5c89e4eSSatish Balay 
13e5c89e4eSSatish Balay /*
14e5c89e4eSSatish Balay      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
15e5c89e4eSSatish Balay */
1695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,int,const char[],const char[],void**);
1795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]);
1895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**);
1995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],void**);
2095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]);
2195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrReallocDefault(size_t,int,const char[],const char[],void**);
22e5c89e4eSSatish Balay 
23e5c89e4eSSatish Balay 
240700a824SBarry Smith #define CLASSID_VALUE  ((PetscClassId) 0xf0e0d0c9)
250700a824SBarry Smith #define ALREADY_FREED  ((PetscClassId) 0x0f0e0d9c)
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay typedef struct _trSPACE {
28e5c89e4eSSatish Balay   size_t       size;
29e5c89e4eSSatish Balay   int          id;
30e5c89e4eSSatish Balay   int          lineno;
31e5c89e4eSSatish Balay   const char   *filename;
32e5c89e4eSSatish Balay   const char   *functionname;
330700a824SBarry Smith   PetscClassId classid;
348bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
35e5c89e4eSSatish Balay   PetscStack   stack;
36e5c89e4eSSatish Balay #endif
37e5c89e4eSSatish Balay   struct _trSPACE *next,*prev;
38e5c89e4eSSatish Balay } TRSPACE;
39e5c89e4eSSatish Balay 
4025b53cc9SJed Brown /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
4125b53cc9SJed Brown    It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN.
4225b53cc9SJed Brown */
43e5c89e4eSSatish Balay 
44a64a8e02SBarry Smith #define HEADER_BYTES  ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))
45e5c89e4eSSatish Balay 
46e5c89e4eSSatish Balay 
4725b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains
4825b53cc9SJed Brown    a minimum alignment of PETSC_MEMALIGN.
4925b53cc9SJed Brown */
50e5c89e4eSSatish Balay typedef union {
51e5c89e4eSSatish Balay   TRSPACE sp;
5225b53cc9SJed Brown   char    v[HEADER_BYTES];
53e5c89e4eSSatish Balay } TrSPACE;
54e5c89e4eSSatish Balay 
55*e3ed9ee7SBarry Smith #define MAXTRMAXMEMS 50
56e5c89e4eSSatish Balay static size_t    TRallocated  = 0;
57e5c89e4eSSatish Balay static int       TRfrags      = 0;
58f0ba7cfcSLisandro Dalcin static TRSPACE   *TRhead      = NULL;
59e5c89e4eSSatish Balay static int       TRid         = 0;
60ace3abfcSBarry Smith static PetscBool TRdebugLevel = PETSC_FALSE;
61e5c89e4eSSatish Balay static size_t    TRMaxMem     = 0;
62*e3ed9ee7SBarry Smith static int       NumTRMaxMems = 0;
63*e3ed9ee7SBarry Smith static size_t    TRMaxMems[MAXTRMAXMEMS];
64*e3ed9ee7SBarry Smith static int       TRMaxMemsEvents[MAXTRMAXMEMS];
65e5c89e4eSSatish Balay /*
66e5c89e4eSSatish Balay       Arrays to log information on all Mallocs
67e5c89e4eSSatish Balay */
68f0ba7cfcSLisandro Dalcin static int        PetscLogMallocMax       = 10000;
69f0ba7cfcSLisandro Dalcin static int        PetscLogMalloc          = -1;
70574034a9SJed Brown static size_t     PetscLogMallocThreshold = 0;
71e5c89e4eSSatish Balay static size_t     *PetscLogMallocLength;
72efca3c55SSatish Balay static const char **PetscLogMallocFile,**PetscLogMallocFunction;
73*e3ed9ee7SBarry Smith static PetscBool  PetscSetUseTrMallocCalled = PETSC_FALSE;
74e5c89e4eSSatish Balay 
7595c0884eSLisandro Dalcin PETSC_INTERN PetscErrorCode PetscSetUseTrMalloc_Private(void)
76b022a5c1SBarry Smith {
77b022a5c1SBarry Smith   PetscErrorCode ierr;
78b022a5c1SBarry Smith 
79b022a5c1SBarry Smith   PetscFunctionBegin;
80*e3ed9ee7SBarry Smith   if (PetscSetUseTrMallocCalled) PetscFunctionReturn(0);
81*e3ed9ee7SBarry Smith   PetscSetUseTrMallocCalled = PETSC_TRUE;
82b022a5c1SBarry Smith   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr);
833221ece2SMatthew G. Knepley   PetscTrRealloc = PetscTrReallocDefault;
84a297a907SKarl Rupp 
85b022a5c1SBarry Smith   TRallocated       = 0;
86b022a5c1SBarry Smith   TRfrags           = 0;
87f0ba7cfcSLisandro Dalcin   TRhead            = NULL;
88b022a5c1SBarry Smith   TRid              = 0;
89b022a5c1SBarry Smith   TRdebugLevel      = PETSC_FALSE;
90b022a5c1SBarry Smith   TRMaxMem          = 0;
91b022a5c1SBarry Smith   PetscLogMallocMax = 10000;
92b022a5c1SBarry Smith   PetscLogMalloc    = -1;
93b022a5c1SBarry Smith   PetscFunctionReturn(0);
94b022a5c1SBarry Smith }
95b022a5c1SBarry Smith 
96e5c89e4eSSatish Balay /*@C
97e5c89e4eSSatish Balay    PetscMallocValidate - Test the memory for corruption.  This can be used to
98e5c89e4eSSatish Balay    check for memory overwrites.
99e5c89e4eSSatish Balay 
100e5c89e4eSSatish Balay    Input Parameter:
101e5c89e4eSSatish Balay +  line - line number where call originated.
102e5c89e4eSSatish Balay .  function - name of function calling
103efca3c55SSatish Balay -  file - file where function is
104e5c89e4eSSatish Balay 
105e5c89e4eSSatish Balay    Return value:
106e5c89e4eSSatish Balay    The number of errors detected.
107e5c89e4eSSatish Balay 
108e5c89e4eSSatish Balay    Output Effect:
109e5c89e4eSSatish Balay    Error messages are written to stdout.
110e5c89e4eSSatish Balay 
111e5c89e4eSSatish Balay    Level: advanced
112e5c89e4eSSatish Balay 
113e5c89e4eSSatish Balay    Notes:
114e5c89e4eSSatish Balay     You should generally use CHKMEMQ as a short cut for calling this
115e5c89e4eSSatish Balay     routine.
116e5c89e4eSSatish Balay 
117efca3c55SSatish Balay     The line, function, file are given by the C preprocessor as
118e5c89e4eSSatish Balay 
119e5c89e4eSSatish Balay     The Fortran calling sequence is simply PetscMallocValidate(ierr)
120e5c89e4eSSatish Balay 
121e5c89e4eSSatish Balay    No output is generated if there are no problems detected.
122e5c89e4eSSatish Balay 
123e5c89e4eSSatish Balay .seealso: CHKMEMQ
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay @*/
126efca3c55SSatish Balay PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
127e5c89e4eSSatish Balay {
1286c093d5bSvictor   TRSPACE      *head,*lasthead;
129e5c89e4eSSatish Balay   char         *a;
1300700a824SBarry Smith   PetscClassId *nend;
131e5c89e4eSSatish Balay 
132e5c89e4eSSatish Balay   PetscFunctionBegin;
1336c093d5bSvictor   head = TRhead; lasthead = NULL;
134e5c89e4eSSatish Balay   while (head) {
1350700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
136efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s\n",function,line,file);
137e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
138e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
139efca3c55SSatish Balay       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
140e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
141e5c89e4eSSatish Balay     }
142e5c89e4eSSatish Balay     a    = (char*)(((TrSPACE*)head) + 1);
1430700a824SBarry Smith     nend = (PetscClassId*)(a + head->size);
1440700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
145efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
146e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
147e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
148e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
149e5c89e4eSSatish Balay       } else {
150e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
151efca3c55SSatish Balay         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
152e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
153e5c89e4eSSatish Balay       }
154e5c89e4eSSatish Balay     }
1556c093d5bSvictor     lasthead = head;
156e5c89e4eSSatish Balay     head     = head->next;
157e5c89e4eSSatish Balay   }
158e5c89e4eSSatish Balay   PetscFunctionReturn(0);
159e5c89e4eSSatish Balay }
160e5c89e4eSSatish Balay 
161e5c89e4eSSatish Balay /*
162e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
163e5c89e4eSSatish Balay 
164e5c89e4eSSatish Balay     Input Parameters:
165e5c89e4eSSatish Balay +   a   - number of bytes to allocate
166e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
167efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
168e5c89e4eSSatish Balay 
169e5c89e4eSSatish Balay     Returns:
170e5c89e4eSSatish Balay     double aligned pointer to requested storage, or null if not
171e5c89e4eSSatish Balay     available.
172e5c89e4eSSatish Balay  */
173efca3c55SSatish Balay PetscErrorCode  PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],void **result)
174e5c89e4eSSatish Balay {
175e5c89e4eSSatish Balay   TRSPACE        *head;
176e5c89e4eSSatish Balay   char           *inew;
177e5c89e4eSSatish Balay   size_t         nsize;
178e5c89e4eSSatish Balay   PetscErrorCode ierr;
179e5c89e4eSSatish Balay 
180e5c89e4eSSatish Balay   PetscFunctionBegin;
181f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
182f0ba7cfcSLisandro Dalcin   if (!a) { *result = NULL; PetscFunctionReturn(0); }
183f0ba7cfcSLisandro Dalcin 
184e5c89e4eSSatish Balay   if (TRdebugLevel) {
185efca3c55SSatish Balay     ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
186e5c89e4eSSatish Balay   }
187e5c89e4eSSatish Balay 
18825b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
189efca3c55SSatish Balay   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
190e5c89e4eSSatish Balay 
191*e3ed9ee7SBarry Smith   if (PetscLogMemory) {
192*e3ed9ee7SBarry Smith     /* zero the memory to force the value of PetscMemoryGetCurrentUsage() to accurately reflect allocated memory */
193*e3ed9ee7SBarry Smith     ierr = PetscMemzero(inew,nsize+sizeof(TrSPACE)+sizeof(PetscClassId));CHKERRQ(ierr);
194*e3ed9ee7SBarry Smith   }
195*e3ed9ee7SBarry Smith 
196e5c89e4eSSatish Balay   head  = (TRSPACE*)inew;
197e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
198e5c89e4eSSatish Balay 
199e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
200e5c89e4eSSatish Balay   head->next   = TRhead;
201e5c89e4eSSatish Balay   TRhead       = head;
202f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
203e5c89e4eSSatish Balay   head->size   = nsize;
204e5c89e4eSSatish Balay   head->id     = TRid;
205e5c89e4eSSatish Balay   head->lineno = lineno;
206e5c89e4eSSatish Balay 
207e5c89e4eSSatish Balay   head->filename                 = filename;
208e5c89e4eSSatish Balay   head->functionname             = function;
2090700a824SBarry Smith   head->classid                  = CLASSID_VALUE;
2100700a824SBarry Smith   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
211e5c89e4eSSatish Balay 
212e5c89e4eSSatish Balay   TRallocated += nsize;
213a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
214*e3ed9ee7SBarry Smith   if (PetscLogMemory) {
215*e3ed9ee7SBarry Smith     PetscInt i;
216*e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
217*e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
218*e3ed9ee7SBarry Smith     }
219*e3ed9ee7SBarry Smith   }
220e5c89e4eSSatish Balay   TRfrags++;
221e5c89e4eSSatish Balay 
2228bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
22376386721SLisandro Dalcin   if (PetscStackActive()) {
2245c25fcd7SBarry Smith     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
2252c9581d2SBarry Smith     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2262c9581d2SBarry Smith     head->stack.line[head->stack.currentsize-2] = lineno;
2279de0f6ecSBarry Smith   } else {
2289de0f6ecSBarry Smith     head->stack.currentsize = 0;
22976386721SLisandro Dalcin   }
230e5c89e4eSSatish Balay #endif
231e5c89e4eSSatish Balay 
232e5c89e4eSSatish Balay   /*
233e5c89e4eSSatish Balay          Allow logging of all mallocs made
234e5c89e4eSSatish Balay   */
235574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
236e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
237e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
238e32f2f54SBarry Smith       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
239a297a907SKarl Rupp 
240a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
241e32f2f54SBarry Smith       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
242a297a907SKarl Rupp 
243a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
244e32f2f54SBarry Smith       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
245e5c89e4eSSatish Balay     }
246e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
247e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
248e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
249e5c89e4eSSatish Balay   }
250e5c89e4eSSatish Balay   *result = (void*)inew;
251e5c89e4eSSatish Balay   PetscFunctionReturn(0);
252e5c89e4eSSatish Balay }
253e5c89e4eSSatish Balay 
254e5c89e4eSSatish Balay 
255e5c89e4eSSatish Balay /*
256e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay    Input Parameters:
259e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
260e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
261e5c89e4eSSatish Balay .   file  - file name where used.  Use __FILE__ for this
262e5c89e4eSSatish Balay  */
263efca3c55SSatish Balay PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
264e5c89e4eSSatish Balay {
265e5c89e4eSSatish Balay   char           *a = (char*)aa;
266e5c89e4eSSatish Balay   TRSPACE        *head;
267e5c89e4eSSatish Balay   char           *ahead;
268e5c89e4eSSatish Balay   PetscErrorCode ierr;
2690700a824SBarry Smith   PetscClassId   *nend;
270e5c89e4eSSatish Balay 
271e5c89e4eSSatish Balay   PetscFunctionBegin;
272e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
27349d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
274e5c89e4eSSatish Balay 
275e5c89e4eSSatish Balay   if (TRdebugLevel) {
276efca3c55SSatish Balay     ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr);
277e5c89e4eSSatish Balay   }
278e5c89e4eSSatish Balay 
279e5c89e4eSSatish Balay   ahead = a;
280e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
281e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
282e5c89e4eSSatish Balay 
2830700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
284efca3c55SSatish Balay     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
285e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
286e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
287e5c89e4eSSatish Balay   }
2880700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2890700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
290e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
291efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
292e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
293e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
294efca3c55SSatish Balay         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
295e5c89e4eSSatish Balay       } else {
296efca3c55SSatish Balay         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
297e5c89e4eSSatish Balay       }
298e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
299e5c89e4eSSatish Balay     } else {
300e5c89e4eSSatish Balay       /* Damaged tail */
301efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
302e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
303efca3c55SSatish Balay       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
304e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
305e5c89e4eSSatish Balay     }
306e5c89e4eSSatish Balay   }
307e5c89e4eSSatish Balay   /* Mark the location freed */
308e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
309e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
310e5c89e4eSSatish Balay   if (line > 0 && line < 50000) {
311e5c89e4eSSatish Balay     head->lineno       = line;
312e5c89e4eSSatish Balay     head->filename     = file;
313e5c89e4eSSatish Balay     head->functionname = function;
314e5c89e4eSSatish Balay   } else {
315e5c89e4eSSatish Balay     head->lineno = -head->lineno;
316e5c89e4eSSatish Balay   }
317e5c89e4eSSatish Balay   /* zero out memory - helps to find some reuse of already freed memory */
318e5c89e4eSSatish Balay   ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr);
319e5c89e4eSSatish Balay 
320*e3ed9ee7SBarry Smith   if (TRallocated < head->size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
321e5c89e4eSSatish Balay   TRallocated -= head->size;
322e5c89e4eSSatish Balay   TRfrags--;
323e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
324e5c89e4eSSatish Balay   else TRhead = head->next;
325e5c89e4eSSatish Balay 
326e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
327efca3c55SSatish Balay   ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr);
328e5c89e4eSSatish Balay   PetscFunctionReturn(0);
329e5c89e4eSSatish Balay }
330e5c89e4eSSatish Balay 
331e5c89e4eSSatish Balay 
3323221ece2SMatthew G. Knepley 
3333221ece2SMatthew G. Knepley /*
3343221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3353221ece2SMatthew G. Knepley 
3363221ece2SMatthew G. Knepley   Input Parameters:
3373221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3383221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3393221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
3403221ece2SMatthew G. Knepley - result   - double aligned pointer to initial storage.
3413221ece2SMatthew G. Knepley 
3423221ece2SMatthew G. Knepley   Output Parameter:
3433221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3443221ece2SMatthew G. Knepley 
3453221ece2SMatthew G. Knepley   Level: developer
3463221ece2SMatthew G. Knepley 
3473221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3483221ece2SMatthew G. Knepley */
3493221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3503221ece2SMatthew G. Knepley {
3513221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3523221ece2SMatthew G. Knepley   TRSPACE        *head;
3533221ece2SMatthew G. Knepley   char           *ahead, *inew;
3543221ece2SMatthew G. Knepley   PetscClassId   *nend;
3553221ece2SMatthew G. Knepley   size_t         nsize;
3563221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3573221ece2SMatthew G. Knepley 
3583221ece2SMatthew G. Knepley   PetscFunctionBegin;
359c22f1541SToby Isaac   /* Realloc to zero = free */
360c22f1541SToby Isaac   if (!len) {
361c22f1541SToby Isaac     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
362c22f1541SToby Isaac     *result = NULL;
363c22f1541SToby Isaac     PetscFunctionReturn(0);
364c22f1541SToby Isaac   }
365f590eff4SLisandro Dalcin   /* Realloc with NULL = malloc */
366f590eff4SLisandro Dalcin   if (!*result) {
367f590eff4SLisandro Dalcin     ierr = PetscTrMallocDefault(len,lineno,function,filename,result);CHKERRQ(ierr);
368f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
369f590eff4SLisandro Dalcin   }
3703221ece2SMatthew G. Knepley 
3713221ece2SMatthew G. Knepley   if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);}
3723221ece2SMatthew G. Knepley 
3733221ece2SMatthew G. Knepley   ahead = a;
3743221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3753221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3763221ece2SMatthew G. Knepley   inew  = a;
3773221ece2SMatthew G. Knepley 
3783221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3793221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3803221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3813221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3823221ece2SMatthew G. Knepley   }
3833221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3843221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3853221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3863221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3873221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3883221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3893221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3903221ece2SMatthew G. Knepley       } else {
3913221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
3923221ece2SMatthew G. Knepley       }
3933221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3943221ece2SMatthew G. Knepley     } else {
3953221ece2SMatthew G. Knepley       /* Damaged tail */
3963221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3973221ece2SMatthew 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);
3983221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3993221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
4003221ece2SMatthew G. Knepley     }
4013221ece2SMatthew G. Knepley   }
4023221ece2SMatthew G. Knepley 
4033221ece2SMatthew G. Knepley   TRallocated -= head->size;
4043221ece2SMatthew G. Knepley   TRfrags--;
4053221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
4063221ece2SMatthew G. Knepley   else TRhead = head->next;
4073221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4083221ece2SMatthew G. Knepley 
4093221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
4103221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
4113221ece2SMatthew G. Knepley 
4123221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
4133221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4143221ece2SMatthew G. Knepley 
4153221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4163221ece2SMatthew G. Knepley   head->next   = TRhead;
4173221ece2SMatthew G. Knepley   TRhead       = head;
4183221ece2SMatthew G. Knepley   head->prev   = NULL;
4193221ece2SMatthew G. Knepley   head->size   = nsize;
4203221ece2SMatthew G. Knepley   head->id     = TRid;
4213221ece2SMatthew G. Knepley   head->lineno = lineno;
4223221ece2SMatthew G. Knepley 
4233221ece2SMatthew G. Knepley   head->filename                 = filename;
4243221ece2SMatthew G. Knepley   head->functionname             = function;
4253221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4263221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4273221ece2SMatthew G. Knepley 
4283221ece2SMatthew G. Knepley   TRallocated += nsize;
4293221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
430*e3ed9ee7SBarry Smith   if (PetscLogMemory) {
431*e3ed9ee7SBarry Smith     PetscInt i;
432*e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
433*e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
434*e3ed9ee7SBarry Smith     }
435*e3ed9ee7SBarry Smith   }
4363221ece2SMatthew G. Knepley   TRfrags++;
4373221ece2SMatthew G. Knepley 
4383221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4393221ece2SMatthew G. Knepley   if (PetscStackActive()) {
4403221ece2SMatthew G. Knepley     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
4413221ece2SMatthew G. Knepley     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4423221ece2SMatthew G. Knepley     head->stack.line[head->stack.currentsize-2] = lineno;
4433221ece2SMatthew G. Knepley   } else {
4443221ece2SMatthew G. Knepley     head->stack.currentsize = 0;
4453221ece2SMatthew G. Knepley   }
4463221ece2SMatthew G. Knepley #endif
4473221ece2SMatthew G. Knepley 
4483221ece2SMatthew G. Knepley   /*
4493221ece2SMatthew G. Knepley          Allow logging of all mallocs made
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));
4543221ece2SMatthew G. Knepley       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4553221ece2SMatthew G. Knepley 
4563221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4573221ece2SMatthew G. Knepley       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4583221ece2SMatthew G. Knepley 
4593221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4603221ece2SMatthew G. Knepley       if (!PetscLogMallocFunction) SETERRQ(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 
4703221ece2SMatthew G. Knepley 
471fe7fb379SMatthew Knepley /*@C
4720841954dSBarry Smith     PetscMemoryView - Shows the amount of memory currently being used
473e5c89e4eSSatish Balay         in a communicator.
474e5c89e4eSSatish Balay 
475e5c89e4eSSatish Balay     Collective on PetscViewer
476e5c89e4eSSatish Balay 
477e5c89e4eSSatish Balay     Input Parameter:
478e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
479e5c89e4eSSatish Balay -    message - string printed before values
480e5c89e4eSSatish Balay 
4810841954dSBarry Smith     Options Database:
4820841954dSBarry Smith +    -malloc - have PETSc track how much memory it has allocated
4830841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4840841954dSBarry Smith 
485e5c89e4eSSatish Balay     Level: intermediate
486e5c89e4eSSatish Balay 
487e5c89e4eSSatish Balay     Concepts: memory usage
488e5c89e4eSSatish Balay 
4890841954dSBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage()
490e5c89e4eSSatish Balay  @*/
4910841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
492e5c89e4eSSatish Balay {
4930841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4940841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
495e5c89e4eSSatish Balay   PetscErrorCode ierr;
496e5c89e4eSSatish Balay   MPI_Comm       comm;
497e5c89e4eSSatish Balay 
498e5c89e4eSSatish Balay   PetscFunctionBegin;
499e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
500e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
5010841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
502e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
503e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
504e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
505e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
506e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
507e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
5080841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5090841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5100841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5110841954dSBarry 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);
5120841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5130841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5140841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5150841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5160841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5170841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5180841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5190841954dSBarry 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);
5200841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5210841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5220841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5230841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
524e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5250841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5260841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5270841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5280841954dSBarry 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);
5290841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5300841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5310841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5320841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
533e5c89e4eSSatish Balay   } else if (resident && allocated) {
5340841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5350841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5360841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5370841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5380841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5390841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5400841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5410841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5420841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
543e5c89e4eSSatish Balay   } else if (allocated) {
5440841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5450841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5460841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5470841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5480841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5490841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
550e5c89e4eSSatish Balay   } else {
551e5c89e4eSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
552e5c89e4eSSatish Balay   }
553e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
554e5c89e4eSSatish Balay   PetscFunctionReturn(0);
555e5c89e4eSSatish Balay }
556e5c89e4eSSatish Balay 
55746eb3923SBarry Smith /*@
558e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
559e5c89e4eSSatish Balay 
560e5c89e4eSSatish Balay     Not Collective
561e5c89e4eSSatish Balay 
562e5c89e4eSSatish Balay     Output Parameters:
563e5c89e4eSSatish Balay .   space - number of bytes currently allocated
564e5c89e4eSSatish Balay 
565e5c89e4eSSatish Balay     Level: intermediate
566e5c89e4eSSatish Balay 
567e5c89e4eSSatish Balay     Concepts: memory usage
568e5c89e4eSSatish Balay 
569e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
570e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
571e5c89e4eSSatish Balay  @*/
5727087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
573e5c89e4eSSatish Balay {
574e5c89e4eSSatish Balay   PetscFunctionBegin;
575e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
576e5c89e4eSSatish Balay   PetscFunctionReturn(0);
577e5c89e4eSSatish Balay }
578e5c89e4eSSatish Balay 
579dc37d89fSBarry Smith /*@
580e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
581e5c89e4eSSatish Balay         during this run.
582e5c89e4eSSatish Balay 
583e5c89e4eSSatish Balay     Not Collective
584e5c89e4eSSatish Balay 
585e5c89e4eSSatish Balay     Output Parameters:
586e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
587e5c89e4eSSatish Balay 
588e5c89e4eSSatish Balay     Level: intermediate
589e5c89e4eSSatish Balay 
590e5c89e4eSSatish Balay     Concepts: memory usage
591e5c89e4eSSatish Balay 
592e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
593*e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
594e5c89e4eSSatish Balay  @*/
5957087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
596e5c89e4eSSatish Balay {
597e5c89e4eSSatish Balay   PetscFunctionBegin;
598e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
599e5c89e4eSSatish Balay   PetscFunctionReturn(0);
600e5c89e4eSSatish Balay }
601e5c89e4eSSatish Balay 
602*e3ed9ee7SBarry Smith /*@
603*e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
604*e3ed9ee7SBarry Smith 
605*e3ed9ee7SBarry Smith     Not Collective
606*e3ed9ee7SBarry Smith 
607*e3ed9ee7SBarry Smith     Input Parameter:
608*e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
609*e3ed9ee7SBarry Smith 
610*e3ed9ee7SBarry Smith     Level: developer
611*e3ed9ee7SBarry Smith 
612*e3ed9ee7SBarry Smith     Concepts: memory usage
613*e3ed9ee7SBarry Smith 
614*e3ed9ee7SBarry Smith .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
615*e3ed9ee7SBarry Smith           PetscMallocPopMaximumUsage()
616*e3ed9ee7SBarry Smith  @*/
617*e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPushMaximumUsage(int event)
618*e3ed9ee7SBarry Smith {
619*e3ed9ee7SBarry Smith   PetscFunctionBegin;
620*e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
621*e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
622*e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems-1] = event;
623*e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
624*e3ed9ee7SBarry Smith }
625*e3ed9ee7SBarry Smith 
626*e3ed9ee7SBarry Smith /*@
627*e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
628*e3ed9ee7SBarry Smith 
629*e3ed9ee7SBarry Smith     Not Collective
630*e3ed9ee7SBarry Smith 
631*e3ed9ee7SBarry Smith     Input Parameter:
632*e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
633*e3ed9ee7SBarry Smith 
634*e3ed9ee7SBarry Smith     Output Parameter:
635*e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
636*e3ed9ee7SBarry Smith 
637*e3ed9ee7SBarry Smith     Level: developer
638*e3ed9ee7SBarry Smith 
639*e3ed9ee7SBarry Smith     Concepts: memory usage
640*e3ed9ee7SBarry Smith 
641*e3ed9ee7SBarry Smith .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
642*e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
643*e3ed9ee7SBarry Smith  @*/
644*e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
645*e3ed9ee7SBarry Smith {
646*e3ed9ee7SBarry Smith   PetscFunctionBegin;
647*e3ed9ee7SBarry Smith   *mu = 0;
648*e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
649*e3ed9ee7SBarry Smith   if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
650*e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
651*e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
652*e3ed9ee7SBarry Smith }
653*e3ed9ee7SBarry Smith 
654a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
655a64a8e02SBarry Smith /*@C
656a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
657a64a8e02SBarry Smith 
658a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
659a64a8e02SBarry Smith 
660a64a8e02SBarry Smith    Input Parameter:
661a64a8e02SBarry Smith .    ptr - the memory location
662a64a8e02SBarry Smith 
663a64a8e02SBarry Smith    Output Paramter:
664a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
665a64a8e02SBarry Smith 
666a64a8e02SBarry Smith    Level: intermediate
667a64a8e02SBarry Smith 
668a64a8e02SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
669a64a8e02SBarry Smith @*/
670a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
671a64a8e02SBarry Smith {
672a64a8e02SBarry Smith   TRSPACE *head;
673a64a8e02SBarry Smith 
674a64a8e02SBarry Smith   PetscFunctionBegin;
675a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
676a64a8e02SBarry Smith   *stack = &head->stack;
677a64a8e02SBarry Smith   PetscFunctionReturn(0);
678a64a8e02SBarry Smith }
67976386721SLisandro Dalcin #else
68076386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
68176386721SLisandro Dalcin {
68276386721SLisandro Dalcin   PetscFunctionBegin;
683f0ba7cfcSLisandro Dalcin   *stack = NULL;
68476386721SLisandro Dalcin   PetscFunctionReturn(0);
68576386721SLisandro Dalcin }
686a64a8e02SBarry Smith #endif
687a64a8e02SBarry Smith 
688e5c89e4eSSatish Balay /*@C
689e5c89e4eSSatish Balay    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
690e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
691e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
692e5c89e4eSSatish Balay    allocated.
693e5c89e4eSSatish Balay 
694e5c89e4eSSatish Balay    Collective on PETSC_COMM_WORLD
695e5c89e4eSSatish Balay 
696e5c89e4eSSatish Balay    Input Parameter:
697e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
698e5c89e4eSSatish Balay 
699e5c89e4eSSatish Balay    Options Database Key:
700e5c89e4eSSatish Balay .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
701e5c89e4eSSatish Balay 
702e5c89e4eSSatish Balay    Level: intermediate
703e5c89e4eSSatish Balay 
704e5c89e4eSSatish Balay    Fortran Note:
705e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
706e5c89e4eSSatish Balay    The fp defaults to stdout.
707e5c89e4eSSatish Balay 
70895452b02SPatrick Sanan    Notes:
70995452b02SPatrick Sanan     uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
710e5c89e4eSSatish Balay           has been freed.
711e5c89e4eSSatish Balay 
712e5c89e4eSSatish Balay    Concepts: memory usage
713e5c89e4eSSatish Balay    Concepts: memory bleeding
714e5c89e4eSSatish Balay    Concepts: bleeding memory
715e5c89e4eSSatish Balay 
7169e9a1f8fSvictor .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
717e5c89e4eSSatish Balay @*/
7187087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
719e5c89e4eSSatish Balay {
720e5c89e4eSSatish Balay   TRSPACE        *head;
721*e3ed9ee7SBarry Smith   size_t         libAlloc = 0;
722e5c89e4eSSatish Balay   PetscErrorCode ierr;
723e5c89e4eSSatish Balay   PetscMPIInt    rank;
724e5c89e4eSSatish Balay 
725e5c89e4eSSatish Balay   PetscFunctionBegin;
726e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
727da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
728e5c89e4eSSatish Balay   head = TRhead;
729e5c89e4eSSatish Balay   while (head) {
7305486ca60SMatthew G. Knepley     libAlloc += head->size;
7315486ca60SMatthew G. Knepley     head = head->next;
7325486ca60SMatthew G. Knepley   }
7335486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
7345486ca60SMatthew G. Knepley   head = TRhead;
7355486ca60SMatthew G. Knepley   while (head) {
7365486ca60SMatthew G. Knepley     PetscBool isLib;
7375486ca60SMatthew G. Knepley 
7385486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
7395486ca60SMatthew G. Knepley     if (!isLib) {
740efca3c55SSatish Balay       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
7418bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
742e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
743e5c89e4eSSatish Balay #endif
7445486ca60SMatthew G. Knepley     }
745e5c89e4eSSatish Balay     head = head->next;
746e5c89e4eSSatish Balay   }
747e5c89e4eSSatish Balay   PetscFunctionReturn(0);
748e5c89e4eSSatish Balay }
749e5c89e4eSSatish Balay 
750e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
751e5c89e4eSSatish Balay 
752dc37d89fSBarry Smith /*@
753e5c89e4eSSatish Balay     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
754e5c89e4eSSatish Balay 
755e5c89e4eSSatish Balay     Not Collective
756e5c89e4eSSatish Balay 
757e5c89e4eSSatish Balay     Options Database Key:
758574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
759574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
760e5c89e4eSSatish Balay 
761e5c89e4eSSatish Balay     Level: advanced
762e5c89e4eSSatish Balay 
763574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
764e5c89e4eSSatish Balay @*/
7657087cfbeSBarry Smith PetscErrorCode PetscMallocSetDumpLog(void)
766e5c89e4eSSatish Balay {
76721b680ceSJed Brown   PetscErrorCode ierr;
76821b680ceSJed Brown 
769e5c89e4eSSatish Balay   PetscFunctionBegin;
770e5c89e4eSSatish Balay   PetscLogMalloc = 0;
771a297a907SKarl Rupp 
77221b680ceSJed Brown   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
773e5c89e4eSSatish Balay   PetscFunctionReturn(0);
774e5c89e4eSSatish Balay }
775e5c89e4eSSatish Balay 
776dc37d89fSBarry Smith /*@
777574034a9SJed Brown     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
778574034a9SJed Brown 
779574034a9SJed Brown     Not Collective
780574034a9SJed Brown 
781574034a9SJed Brown     Input Arguments:
782574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
783574034a9SJed Brown 
784574034a9SJed Brown     Options Database Key:
785574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
786574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
787574034a9SJed Brown 
788574034a9SJed Brown     Level: advanced
789574034a9SJed Brown 
790574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
791574034a9SJed Brown @*/
792574034a9SJed Brown PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
793574034a9SJed Brown {
794574034a9SJed Brown   PetscErrorCode ierr;
795574034a9SJed Brown 
796574034a9SJed Brown   PetscFunctionBegin;
797574034a9SJed Brown   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
798574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
799574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
800574034a9SJed Brown   PetscFunctionReturn(0);
801574034a9SJed Brown }
802574034a9SJed Brown 
803dc37d89fSBarry Smith /*@
80418a2528dSJed Brown     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
80518a2528dSJed Brown 
80618a2528dSJed Brown     Not Collective
80718a2528dSJed Brown 
80818a2528dSJed Brown     Output Arguments
80918a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
81018a2528dSJed Brown 
81118a2528dSJed Brown     Options Database Key:
81218a2528dSJed Brown .  -malloc_log - Activates PetscMallocDumpLog()
81318a2528dSJed Brown 
81418a2528dSJed Brown     Level: advanced
81518a2528dSJed Brown 
81618a2528dSJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog()
81718a2528dSJed Brown @*/
81818a2528dSJed Brown PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
81918a2528dSJed Brown {
82018a2528dSJed Brown 
82118a2528dSJed Brown   PetscFunctionBegin;
82218a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
82318a2528dSJed Brown   PetscFunctionReturn(0);
82418a2528dSJed Brown }
82518a2528dSJed Brown 
826e5c89e4eSSatish Balay /*@C
827e5c89e4eSSatish Balay     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
82821b680ceSJed Brown        PetscMemoryGetMaximumUsage()
829e5c89e4eSSatish Balay 
830e5c89e4eSSatish Balay     Collective on PETSC_COMM_WORLD
831e5c89e4eSSatish Balay 
832e5c89e4eSSatish Balay     Input Parameter:
8330298fd71SBarry Smith .   fp - file pointer; or NULL
834e5c89e4eSSatish Balay 
835e5c89e4eSSatish Balay     Options Database Key:
836e5c89e4eSSatish Balay .  -malloc_log - Activates PetscMallocDumpLog()
837e5c89e4eSSatish Balay 
838e5c89e4eSSatish Balay     Level: advanced
839e5c89e4eSSatish Balay 
840e5c89e4eSSatish Balay    Fortran Note:
841e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
842e5c89e4eSSatish Balay    The fp defaults to stdout.
843e5c89e4eSSatish Balay 
844e5c89e4eSSatish Balay .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
845e5c89e4eSSatish Balay @*/
8467087cfbeSBarry Smith PetscErrorCode  PetscMallocDumpLog(FILE *fp)
847e5c89e4eSSatish Balay {
848e5c89e4eSSatish Balay   PetscInt       i,j,n,dummy,*perm;
849e5c89e4eSSatish Balay   size_t         *shortlength;
850f56c2debSBarry Smith   int            *shortcount,err;
851e5c89e4eSSatish Balay   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
852ace3abfcSBarry Smith   PetscBool      match;
853e5c89e4eSSatish Balay   const char     **shortfunction;
854e5c89e4eSSatish Balay   PetscLogDouble rss;
855e5c89e4eSSatish Balay   MPI_Status     status;
856e5c89e4eSSatish Balay   PetscErrorCode ierr;
857e5c89e4eSSatish Balay 
858e5c89e4eSSatish Balay   PetscFunctionBegin;
859e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
860e5c89e4eSSatish Balay   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
861e5c89e4eSSatish Balay   /*
862e5c89e4eSSatish Balay        Try to get the data printed in order by processor. This will only sometimes work
863e5c89e4eSSatish Balay   */
864f56c2debSBarry Smith   err = fflush(fp);
865e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
866f56c2debSBarry Smith 
867e5c89e4eSSatish Balay   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
868e5c89e4eSSatish Balay   if (rank) {
869e5c89e4eSSatish Balay     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
870e5c89e4eSSatish Balay   }
871e5c89e4eSSatish Balay 
872768aa557SSatish Balay   if (PetscLogMalloc < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"PetscMallocDumpLog() called without call to PetscMallocSetDumpLog() this is often due to\n                      setting the option -malloc_log AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()");
873768aa557SSatish Balay 
874da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
875f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
876e5c89e4eSSatish Balay   if (rss) {
877f3d65365SJed Brown     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);CHKERRQ(ierr);
878e5c89e4eSSatish Balay   } else {
879e5c89e4eSSatish Balay     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);CHKERRQ(ierr);
880e5c89e4eSSatish Balay   }
881e32f2f54SBarry Smith   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
882e32f2f54SBarry Smith   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
883e32f2f54SBarry Smith   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
88497b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
885e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
886e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
887e5c89e4eSSatish Balay       if (match) {
888e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
88959ffdab8SBarry Smith         shortcount[j]++;
890e5c89e4eSSatish Balay         goto foundit;
891e5c89e4eSSatish Balay       }
892e5c89e4eSSatish Balay     }
893e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
894e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
89559ffdab8SBarry Smith     shortcount[n]    = 1;
896e5c89e4eSSatish Balay     n++;
897e5c89e4eSSatish Balay foundit:;
898e5c89e4eSSatish Balay   }
899e5c89e4eSSatish Balay 
900e32f2f54SBarry Smith   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
901e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
902e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
903e5c89e4eSSatish Balay 
904e5c89e4eSSatish Balay   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
905e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
90659ffdab8SBarry Smith     ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);CHKERRQ(ierr);
907e5c89e4eSSatish Balay   }
908e5c89e4eSSatish Balay   free(perm);
909e5c89e4eSSatish Balay   free(shortlength);
91059ffdab8SBarry Smith   free(shortcount);
911e5c89e4eSSatish Balay   free((char**)shortfunction);
912f56c2debSBarry Smith   err = fflush(fp);
913e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
914e5c89e4eSSatish Balay   if (rank != size-1) {
915e5c89e4eSSatish Balay     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
916e5c89e4eSSatish Balay   }
917e5c89e4eSSatish Balay   PetscFunctionReturn(0);
918e5c89e4eSSatish Balay }
919e5c89e4eSSatish Balay 
920e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
921e5c89e4eSSatish Balay 
922dc37d89fSBarry Smith /*@
923e5c89e4eSSatish Balay     PetscMallocDebug - Turns on/off debugging for the memory management routines.
924e5c89e4eSSatish Balay 
925e5c89e4eSSatish Balay     Not Collective
926e5c89e4eSSatish Balay 
927e5c89e4eSSatish Balay     Input Parameter:
928e5c89e4eSSatish Balay .   level - PETSC_TRUE or PETSC_FALSE
929e5c89e4eSSatish Balay 
930e5c89e4eSSatish Balay    Level: intermediate
931e5c89e4eSSatish Balay 
932e5c89e4eSSatish Balay .seealso: CHKMEMQ(), PetscMallocValidate()
933e5c89e4eSSatish Balay @*/
9347087cfbeSBarry Smith PetscErrorCode  PetscMallocDebug(PetscBool level)
935e5c89e4eSSatish Balay {
936e5c89e4eSSatish Balay   PetscFunctionBegin;
937e5c89e4eSSatish Balay   TRdebugLevel = level;
938e5c89e4eSSatish Balay   PetscFunctionReturn(0);
939e5c89e4eSSatish Balay }
9400acecf5bSBarry Smith 
941dc37d89fSBarry Smith /*@
9420acecf5bSBarry Smith     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
9430acecf5bSBarry Smith 
9440acecf5bSBarry Smith     Not Collective
9450acecf5bSBarry Smith 
9460acecf5bSBarry Smith     Output Parameter:
9470acecf5bSBarry Smith .    flg - PETSC_TRUE if any debugger
9480acecf5bSBarry Smith 
9490acecf5bSBarry Smith    Level: intermediate
9500acecf5bSBarry Smith 
9510acecf5bSBarry Smith     Note that by default, the debug version always does some debugging unless you run with -malloc no
9520acecf5bSBarry Smith 
9530acecf5bSBarry Smith 
9540acecf5bSBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate()
9550acecf5bSBarry Smith @*/
9560acecf5bSBarry Smith PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
9570acecf5bSBarry Smith {
9580acecf5bSBarry Smith   PetscFunctionBegin;
9590acecf5bSBarry Smith   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
9600acecf5bSBarry Smith   else *flg = PETSC_FALSE;
9610acecf5bSBarry Smith   PetscFunctionReturn(0);
9620acecf5bSBarry Smith }
963