xref: /petsc/src/sys/memory/mtr.c (revision 071fcb05f2a6aea8aef2c2090580530b9e9df77e)
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 */
16*071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,PetscBool,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**);
19*071fcb05SBarry Smith PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,PetscBool,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 
55e3ed9ee7SBarry 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;
62e3ed9ee7SBarry Smith static int       NumTRMaxMems = 0;
63e3ed9ee7SBarry Smith static size_t    TRMaxMems[MAXTRMAXMEMS];
64e3ed9ee7SBarry 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;
73e3ed9ee7SBarry 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;
80e3ed9ee7SBarry Smith   if (PetscSetUseTrMallocCalled) PetscFunctionReturn(0);
81e3ed9ee7SBarry 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  */
173*071fcb05SBarry Smith PetscErrorCode  PetscTrMallocDefault(size_t a,PetscBool clear,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);
189*071fcb05SBarry Smith   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
190e3ed9ee7SBarry Smith 
191e5c89e4eSSatish Balay   head  = (TRSPACE*)inew;
192e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
193e5c89e4eSSatish Balay 
194e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
195e5c89e4eSSatish Balay   head->next   = TRhead;
196e5c89e4eSSatish Balay   TRhead       = head;
197f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
198e5c89e4eSSatish Balay   head->size   = nsize;
199e5c89e4eSSatish Balay   head->id     = TRid;
200e5c89e4eSSatish Balay   head->lineno = lineno;
201e5c89e4eSSatish Balay 
202e5c89e4eSSatish Balay   head->filename                 = filename;
203e5c89e4eSSatish Balay   head->functionname             = function;
2040700a824SBarry Smith   head->classid                  = CLASSID_VALUE;
2050700a824SBarry Smith   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
206e5c89e4eSSatish Balay 
207e5c89e4eSSatish Balay   TRallocated += nsize;
208a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
209e3ed9ee7SBarry Smith   if (PetscLogMemory) {
210e3ed9ee7SBarry Smith     PetscInt i;
211e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
212e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
213e3ed9ee7SBarry Smith     }
214e3ed9ee7SBarry Smith   }
215e5c89e4eSSatish Balay   TRfrags++;
216e5c89e4eSSatish Balay 
2178bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
21876386721SLisandro Dalcin   if (PetscStackActive()) {
2195c25fcd7SBarry Smith     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
2202c9581d2SBarry Smith     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2212c9581d2SBarry Smith     head->stack.line[head->stack.currentsize-2] = lineno;
2229de0f6ecSBarry Smith   } else {
2239de0f6ecSBarry Smith     head->stack.currentsize = 0;
22476386721SLisandro Dalcin   }
225e5c89e4eSSatish Balay #endif
226e5c89e4eSSatish Balay 
227e5c89e4eSSatish Balay   /*
228e5c89e4eSSatish Balay          Allow logging of all mallocs made
229e5c89e4eSSatish Balay   */
230574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
231e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
232e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
233e32f2f54SBarry Smith       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
234a297a907SKarl Rupp 
235a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
236e32f2f54SBarry Smith       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
237a297a907SKarl Rupp 
238a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
239e32f2f54SBarry Smith       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
240e5c89e4eSSatish Balay     }
241e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
242e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
243e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
244e5c89e4eSSatish Balay   }
245e5c89e4eSSatish Balay   *result = (void*)inew;
246e5c89e4eSSatish Balay   PetscFunctionReturn(0);
247e5c89e4eSSatish Balay }
248e5c89e4eSSatish Balay 
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay /*
251e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
252e5c89e4eSSatish Balay 
253e5c89e4eSSatish Balay    Input Parameters:
254e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
255e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
256e5c89e4eSSatish Balay .   file  - file name where used.  Use __FILE__ for this
257e5c89e4eSSatish Balay  */
258efca3c55SSatish Balay PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
259e5c89e4eSSatish Balay {
260e5c89e4eSSatish Balay   char           *a = (char*)aa;
261e5c89e4eSSatish Balay   TRSPACE        *head;
262e5c89e4eSSatish Balay   char           *ahead;
263e5c89e4eSSatish Balay   PetscErrorCode ierr;
2640700a824SBarry Smith   PetscClassId   *nend;
265e5c89e4eSSatish Balay 
266e5c89e4eSSatish Balay   PetscFunctionBegin;
267e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
26849d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
269e5c89e4eSSatish Balay 
270e5c89e4eSSatish Balay   if (TRdebugLevel) {
271efca3c55SSatish Balay     ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr);
272e5c89e4eSSatish Balay   }
273e5c89e4eSSatish Balay 
274e5c89e4eSSatish Balay   ahead = a;
275e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
276e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
277e5c89e4eSSatish Balay 
2780700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
279efca3c55SSatish Balay     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
280e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
281e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
282e5c89e4eSSatish Balay   }
2830700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2840700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
285e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
286efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
287e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
288e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
289efca3c55SSatish Balay         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
290e5c89e4eSSatish Balay       } else {
291efca3c55SSatish Balay         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
292e5c89e4eSSatish Balay       }
293e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
294e5c89e4eSSatish Balay     } else {
295e5c89e4eSSatish Balay       /* Damaged tail */
296efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
297e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
298efca3c55SSatish Balay       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
299e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
300e5c89e4eSSatish Balay     }
301e5c89e4eSSatish Balay   }
302e5c89e4eSSatish Balay   /* Mark the location freed */
303e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
304e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
305e5c89e4eSSatish Balay   if (line > 0 && line < 50000) {
306e5c89e4eSSatish Balay     head->lineno       = line;
307e5c89e4eSSatish Balay     head->filename     = file;
308e5c89e4eSSatish Balay     head->functionname = function;
309e5c89e4eSSatish Balay   } else {
310e5c89e4eSSatish Balay     head->lineno = -head->lineno;
311e5c89e4eSSatish Balay   }
312e3ed9ee7SBarry Smith   if (TRallocated < head->size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
313e5c89e4eSSatish Balay   TRallocated -= head->size;
314e5c89e4eSSatish Balay   TRfrags--;
315e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
316e5c89e4eSSatish Balay   else TRhead = head->next;
317e5c89e4eSSatish Balay 
318e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
319efca3c55SSatish Balay   ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr);
320e5c89e4eSSatish Balay   PetscFunctionReturn(0);
321e5c89e4eSSatish Balay }
322e5c89e4eSSatish Balay 
323e5c89e4eSSatish Balay 
3243221ece2SMatthew G. Knepley 
3253221ece2SMatthew G. Knepley /*
3263221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3273221ece2SMatthew G. Knepley 
3283221ece2SMatthew G. Knepley   Input Parameters:
3293221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3303221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3313221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
3323221ece2SMatthew G. Knepley - result   - double aligned pointer to initial storage.
3333221ece2SMatthew G. Knepley 
3343221ece2SMatthew G. Knepley   Output Parameter:
3353221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3363221ece2SMatthew G. Knepley 
3373221ece2SMatthew G. Knepley   Level: developer
3383221ece2SMatthew G. Knepley 
3393221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3403221ece2SMatthew G. Knepley */
3413221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3423221ece2SMatthew G. Knepley {
3433221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3443221ece2SMatthew G. Knepley   TRSPACE        *head;
3453221ece2SMatthew G. Knepley   char           *ahead, *inew;
3463221ece2SMatthew G. Knepley   PetscClassId   *nend;
3473221ece2SMatthew G. Knepley   size_t         nsize;
3483221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3493221ece2SMatthew G. Knepley 
3503221ece2SMatthew G. Knepley   PetscFunctionBegin;
351c22f1541SToby Isaac   /* Realloc to zero = free */
352c22f1541SToby Isaac   if (!len) {
353c22f1541SToby Isaac     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
354c22f1541SToby Isaac     *result = NULL;
355c22f1541SToby Isaac     PetscFunctionReturn(0);
356c22f1541SToby Isaac   }
357f590eff4SLisandro Dalcin   /* Realloc with NULL = malloc */
358f590eff4SLisandro Dalcin   if (!*result) {
359*071fcb05SBarry Smith     ierr = PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);CHKERRQ(ierr);
360f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
361f590eff4SLisandro Dalcin   }
3623221ece2SMatthew G. Knepley 
3633221ece2SMatthew G. Knepley   if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);}
3643221ece2SMatthew G. Knepley 
3653221ece2SMatthew G. Knepley   ahead = a;
3663221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3673221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3683221ece2SMatthew G. Knepley   inew  = a;
3693221ece2SMatthew G. Knepley 
3703221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3713221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3723221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3733221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3743221ece2SMatthew G. Knepley   }
3753221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3763221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3773221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3783221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3793221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3803221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3813221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3823221ece2SMatthew G. Knepley       } else {
3833221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
3843221ece2SMatthew G. Knepley       }
3853221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3863221ece2SMatthew G. Knepley     } else {
3873221ece2SMatthew G. Knepley       /* Damaged tail */
3883221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3893221ece2SMatthew 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);
3903221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3913221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
3923221ece2SMatthew G. Knepley     }
3933221ece2SMatthew G. Knepley   }
3943221ece2SMatthew G. Knepley 
3953221ece2SMatthew G. Knepley   TRallocated -= head->size;
3963221ece2SMatthew G. Knepley   TRfrags--;
3973221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
3983221ece2SMatthew G. Knepley   else TRhead = head->next;
3993221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
4003221ece2SMatthew G. Knepley 
4013221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
4023221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
4033221ece2SMatthew G. Knepley 
4043221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
4053221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4063221ece2SMatthew G. Knepley 
4073221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4083221ece2SMatthew G. Knepley   head->next   = TRhead;
4093221ece2SMatthew G. Knepley   TRhead       = head;
4103221ece2SMatthew G. Knepley   head->prev   = NULL;
4113221ece2SMatthew G. Knepley   head->size   = nsize;
4123221ece2SMatthew G. Knepley   head->id     = TRid;
4133221ece2SMatthew G. Knepley   head->lineno = lineno;
4143221ece2SMatthew G. Knepley 
4153221ece2SMatthew G. Knepley   head->filename                 = filename;
4163221ece2SMatthew G. Knepley   head->functionname             = function;
4173221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4183221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4193221ece2SMatthew G. Knepley 
4203221ece2SMatthew G. Knepley   TRallocated += nsize;
4213221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
422e3ed9ee7SBarry Smith   if (PetscLogMemory) {
423e3ed9ee7SBarry Smith     PetscInt i;
424e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
425e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
426e3ed9ee7SBarry Smith     }
427e3ed9ee7SBarry Smith   }
4283221ece2SMatthew G. Knepley   TRfrags++;
4293221ece2SMatthew G. Knepley 
4303221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4313221ece2SMatthew G. Knepley   if (PetscStackActive()) {
4323221ece2SMatthew G. Knepley     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
4333221ece2SMatthew G. Knepley     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4343221ece2SMatthew G. Knepley     head->stack.line[head->stack.currentsize-2] = lineno;
4353221ece2SMatthew G. Knepley   } else {
4363221ece2SMatthew G. Knepley     head->stack.currentsize = 0;
4373221ece2SMatthew G. Knepley   }
4383221ece2SMatthew G. Knepley #endif
4393221ece2SMatthew G. Knepley 
4403221ece2SMatthew G. Knepley   /*
4413221ece2SMatthew G. Knepley          Allow logging of all mallocs made
4423221ece2SMatthew G. Knepley   */
4433221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4443221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4453221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
4463221ece2SMatthew G. Knepley       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4473221ece2SMatthew G. Knepley 
4483221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4493221ece2SMatthew G. Knepley       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4503221ece2SMatthew G. Knepley 
4513221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4523221ece2SMatthew G. Knepley       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4533221ece2SMatthew G. Knepley     }
4543221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4553221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4563221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4573221ece2SMatthew G. Knepley   }
4583221ece2SMatthew G. Knepley   *result = (void*)inew;
4593221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4603221ece2SMatthew G. Knepley }
4613221ece2SMatthew G. Knepley 
4623221ece2SMatthew G. Knepley 
463fe7fb379SMatthew Knepley /*@C
4640841954dSBarry Smith     PetscMemoryView - Shows the amount of memory currently being used
465e5c89e4eSSatish Balay         in a communicator.
466e5c89e4eSSatish Balay 
467e5c89e4eSSatish Balay     Collective on PetscViewer
468e5c89e4eSSatish Balay 
469e5c89e4eSSatish Balay     Input Parameter:
470e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
471e5c89e4eSSatish Balay -    message - string printed before values
472e5c89e4eSSatish Balay 
4730841954dSBarry Smith     Options Database:
4740841954dSBarry Smith +    -malloc - have PETSc track how much memory it has allocated
4750841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4760841954dSBarry Smith 
477e5c89e4eSSatish Balay     Level: intermediate
478e5c89e4eSSatish Balay 
4790841954dSBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage()
480e5c89e4eSSatish Balay  @*/
4810841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
482e5c89e4eSSatish Balay {
4830841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4840841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
485e5c89e4eSSatish Balay   PetscErrorCode ierr;
486e5c89e4eSSatish Balay   MPI_Comm       comm;
487e5c89e4eSSatish Balay 
488e5c89e4eSSatish Balay   PetscFunctionBegin;
489e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
490e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
4910841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
492e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
493e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
494e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
495e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
496e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
497e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4980841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4990841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5000841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5010841954dSBarry 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);
5020841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5030841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5040841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5050841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5060841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5070841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5080841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5090841954dSBarry 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);
5100841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5110841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5120841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5130841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
514e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5150841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5160841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5170841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5180841954dSBarry 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);
5190841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5200841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5210841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5220841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
523e5c89e4eSSatish Balay   } else if (resident && allocated) {
5240841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5250841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5260841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5270841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5280841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5290841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5300841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5310841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5320841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
533e5c89e4eSSatish Balay   } else if (allocated) {
5340841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5350841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5360841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5370841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5380841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5390841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
540e5c89e4eSSatish Balay   } else {
541e5c89e4eSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
542e5c89e4eSSatish Balay   }
543e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
544e5c89e4eSSatish Balay   PetscFunctionReturn(0);
545e5c89e4eSSatish Balay }
546e5c89e4eSSatish Balay 
54746eb3923SBarry Smith /*@
548e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
549e5c89e4eSSatish Balay 
550e5c89e4eSSatish Balay     Not Collective
551e5c89e4eSSatish Balay 
552e5c89e4eSSatish Balay     Output Parameters:
553e5c89e4eSSatish Balay .   space - number of bytes currently allocated
554e5c89e4eSSatish Balay 
555e5c89e4eSSatish Balay     Level: intermediate
556e5c89e4eSSatish Balay 
557e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
558e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
559e5c89e4eSSatish Balay  @*/
5607087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
561e5c89e4eSSatish Balay {
562e5c89e4eSSatish Balay   PetscFunctionBegin;
563e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
564e5c89e4eSSatish Balay   PetscFunctionReturn(0);
565e5c89e4eSSatish Balay }
566e5c89e4eSSatish Balay 
567dc37d89fSBarry Smith /*@
568e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
569e5c89e4eSSatish Balay         during this run.
570e5c89e4eSSatish Balay 
571e5c89e4eSSatish Balay     Not Collective
572e5c89e4eSSatish Balay 
573e5c89e4eSSatish Balay     Output Parameters:
574e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
575e5c89e4eSSatish Balay 
576e5c89e4eSSatish Balay     Level: intermediate
577e5c89e4eSSatish Balay 
578e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
579e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
580e5c89e4eSSatish Balay  @*/
5817087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
582e5c89e4eSSatish Balay {
583e5c89e4eSSatish Balay   PetscFunctionBegin;
584e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
585e5c89e4eSSatish Balay   PetscFunctionReturn(0);
586e5c89e4eSSatish Balay }
587e5c89e4eSSatish Balay 
588e3ed9ee7SBarry Smith /*@
589e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
590e3ed9ee7SBarry Smith 
591e3ed9ee7SBarry Smith     Not Collective
592e3ed9ee7SBarry Smith 
593e3ed9ee7SBarry Smith     Input Parameter:
594e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
595e3ed9ee7SBarry Smith 
596e3ed9ee7SBarry Smith     Level: developer
597e3ed9ee7SBarry Smith 
598e3ed9ee7SBarry Smith .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
599e3ed9ee7SBarry Smith           PetscMallocPopMaximumUsage()
600e3ed9ee7SBarry Smith  @*/
601e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPushMaximumUsage(int event)
602e3ed9ee7SBarry Smith {
603e3ed9ee7SBarry Smith   PetscFunctionBegin;
604e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
605e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
606e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems-1] = event;
607e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
608e3ed9ee7SBarry Smith }
609e3ed9ee7SBarry Smith 
610e3ed9ee7SBarry Smith /*@
611e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
612e3ed9ee7SBarry Smith 
613e3ed9ee7SBarry Smith     Not Collective
614e3ed9ee7SBarry Smith 
615e3ed9ee7SBarry Smith     Input Parameter:
616e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
617e3ed9ee7SBarry Smith 
618e3ed9ee7SBarry Smith     Output Parameter:
619e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
620e3ed9ee7SBarry Smith 
621e3ed9ee7SBarry Smith     Level: developer
622e3ed9ee7SBarry Smith 
623e3ed9ee7SBarry Smith .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
624e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
625e3ed9ee7SBarry Smith  @*/
626e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
627e3ed9ee7SBarry Smith {
628e3ed9ee7SBarry Smith   PetscFunctionBegin;
629e3ed9ee7SBarry Smith   *mu = 0;
630e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
631e3ed9ee7SBarry Smith   if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
632e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
633e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
634e3ed9ee7SBarry Smith }
635e3ed9ee7SBarry Smith 
636a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
637a64a8e02SBarry Smith /*@C
638a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
639a64a8e02SBarry Smith 
640a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
641a64a8e02SBarry Smith 
642a64a8e02SBarry Smith    Input Parameter:
643a64a8e02SBarry Smith .    ptr - the memory location
644a64a8e02SBarry Smith 
645a64a8e02SBarry Smith    Output Paramter:
646a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
647a64a8e02SBarry Smith 
648a64a8e02SBarry Smith    Level: intermediate
649a64a8e02SBarry Smith 
650a64a8e02SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
651a64a8e02SBarry Smith @*/
652a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
653a64a8e02SBarry Smith {
654a64a8e02SBarry Smith   TRSPACE *head;
655a64a8e02SBarry Smith 
656a64a8e02SBarry Smith   PetscFunctionBegin;
657a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
658a64a8e02SBarry Smith   *stack = &head->stack;
659a64a8e02SBarry Smith   PetscFunctionReturn(0);
660a64a8e02SBarry Smith }
66176386721SLisandro Dalcin #else
66276386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
66376386721SLisandro Dalcin {
66476386721SLisandro Dalcin   PetscFunctionBegin;
665f0ba7cfcSLisandro Dalcin   *stack = NULL;
66676386721SLisandro Dalcin   PetscFunctionReturn(0);
66776386721SLisandro Dalcin }
668a64a8e02SBarry Smith #endif
669a64a8e02SBarry Smith 
670e5c89e4eSSatish Balay /*@C
671e5c89e4eSSatish Balay    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
672e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
673e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
674e5c89e4eSSatish Balay    allocated.
675e5c89e4eSSatish Balay 
676e5c89e4eSSatish Balay    Collective on PETSC_COMM_WORLD
677e5c89e4eSSatish Balay 
678e5c89e4eSSatish Balay    Input Parameter:
679e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
680e5c89e4eSSatish Balay 
681e5c89e4eSSatish Balay    Options Database Key:
682e5c89e4eSSatish Balay .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
683e5c89e4eSSatish Balay 
684e5c89e4eSSatish Balay    Level: intermediate
685e5c89e4eSSatish Balay 
686e5c89e4eSSatish Balay    Fortran Note:
687e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
688e5c89e4eSSatish Balay    The fp defaults to stdout.
689e5c89e4eSSatish Balay 
69095452b02SPatrick Sanan    Notes:
69195452b02SPatrick Sanan     uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
692e5c89e4eSSatish Balay           has been freed.
693e5c89e4eSSatish Balay 
6949e9a1f8fSvictor .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
695e5c89e4eSSatish Balay @*/
6967087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
697e5c89e4eSSatish Balay {
698e5c89e4eSSatish Balay   TRSPACE        *head;
699e3ed9ee7SBarry Smith   size_t         libAlloc = 0;
700e5c89e4eSSatish Balay   PetscErrorCode ierr;
701e5c89e4eSSatish Balay   PetscMPIInt    rank;
702e5c89e4eSSatish Balay 
703e5c89e4eSSatish Balay   PetscFunctionBegin;
704e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
705da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
706e5c89e4eSSatish Balay   head = TRhead;
707e5c89e4eSSatish Balay   while (head) {
7085486ca60SMatthew G. Knepley     libAlloc += head->size;
7095486ca60SMatthew G. Knepley     head = head->next;
7105486ca60SMatthew G. Knepley   }
7115486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
7125486ca60SMatthew G. Knepley   head = TRhead;
7135486ca60SMatthew G. Knepley   while (head) {
7145486ca60SMatthew G. Knepley     PetscBool isLib;
7155486ca60SMatthew G. Knepley 
7165486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
7175486ca60SMatthew G. Knepley     if (!isLib) {
718efca3c55SSatish Balay       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
7198bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
720e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
721e5c89e4eSSatish Balay #endif
7225486ca60SMatthew G. Knepley     }
723e5c89e4eSSatish Balay     head = head->next;
724e5c89e4eSSatish Balay   }
725e5c89e4eSSatish Balay   PetscFunctionReturn(0);
726e5c89e4eSSatish Balay }
727e5c89e4eSSatish Balay 
728e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
729e5c89e4eSSatish Balay 
730dc37d89fSBarry Smith /*@
731e5c89e4eSSatish Balay     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
732e5c89e4eSSatish Balay 
733e5c89e4eSSatish Balay     Not Collective
734e5c89e4eSSatish Balay 
735e5c89e4eSSatish Balay     Options Database Key:
736574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
737574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
738e5c89e4eSSatish Balay 
739e5c89e4eSSatish Balay     Level: advanced
740e5c89e4eSSatish Balay 
741574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
742e5c89e4eSSatish Balay @*/
7437087cfbeSBarry Smith PetscErrorCode PetscMallocSetDumpLog(void)
744e5c89e4eSSatish Balay {
74521b680ceSJed Brown   PetscErrorCode ierr;
74621b680ceSJed Brown 
747e5c89e4eSSatish Balay   PetscFunctionBegin;
748e5c89e4eSSatish Balay   PetscLogMalloc = 0;
749a297a907SKarl Rupp 
75021b680ceSJed Brown   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
751e5c89e4eSSatish Balay   PetscFunctionReturn(0);
752e5c89e4eSSatish Balay }
753e5c89e4eSSatish Balay 
754dc37d89fSBarry Smith /*@
755574034a9SJed Brown     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
756574034a9SJed Brown 
757574034a9SJed Brown     Not Collective
758574034a9SJed Brown 
759574034a9SJed Brown     Input Arguments:
760574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
761574034a9SJed Brown 
762574034a9SJed Brown     Options Database Key:
763574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
764574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
765574034a9SJed Brown 
766574034a9SJed Brown     Level: advanced
767574034a9SJed Brown 
768574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
769574034a9SJed Brown @*/
770574034a9SJed Brown PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
771574034a9SJed Brown {
772574034a9SJed Brown   PetscErrorCode ierr;
773574034a9SJed Brown 
774574034a9SJed Brown   PetscFunctionBegin;
775574034a9SJed Brown   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
776574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
777574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
778574034a9SJed Brown   PetscFunctionReturn(0);
779574034a9SJed Brown }
780574034a9SJed Brown 
781dc37d89fSBarry Smith /*@
78218a2528dSJed Brown     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
78318a2528dSJed Brown 
78418a2528dSJed Brown     Not Collective
78518a2528dSJed Brown 
78618a2528dSJed Brown     Output Arguments
78718a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
78818a2528dSJed Brown 
78918a2528dSJed Brown     Options Database Key:
79018a2528dSJed Brown .  -malloc_log - Activates PetscMallocDumpLog()
79118a2528dSJed Brown 
79218a2528dSJed Brown     Level: advanced
79318a2528dSJed Brown 
79418a2528dSJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog()
79518a2528dSJed Brown @*/
79618a2528dSJed Brown PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
79718a2528dSJed Brown {
79818a2528dSJed Brown 
79918a2528dSJed Brown   PetscFunctionBegin;
80018a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
80118a2528dSJed Brown   PetscFunctionReturn(0);
80218a2528dSJed Brown }
80318a2528dSJed Brown 
804e5c89e4eSSatish Balay /*@C
805e5c89e4eSSatish Balay     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
80621b680ceSJed Brown        PetscMemoryGetMaximumUsage()
807e5c89e4eSSatish Balay 
808e5c89e4eSSatish Balay     Collective on PETSC_COMM_WORLD
809e5c89e4eSSatish Balay 
810e5c89e4eSSatish Balay     Input Parameter:
8110298fd71SBarry Smith .   fp - file pointer; or NULL
812e5c89e4eSSatish Balay 
813e5c89e4eSSatish Balay     Options Database Key:
814e5c89e4eSSatish Balay .  -malloc_log - Activates PetscMallocDumpLog()
815e5c89e4eSSatish Balay 
816e5c89e4eSSatish Balay     Level: advanced
817e5c89e4eSSatish Balay 
818e5c89e4eSSatish Balay    Fortran Note:
819e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
820e5c89e4eSSatish Balay    The fp defaults to stdout.
821e5c89e4eSSatish Balay 
822e5c89e4eSSatish Balay .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
823e5c89e4eSSatish Balay @*/
8247087cfbeSBarry Smith PetscErrorCode  PetscMallocDumpLog(FILE *fp)
825e5c89e4eSSatish Balay {
826e5c89e4eSSatish Balay   PetscInt       i,j,n,dummy,*perm;
827e5c89e4eSSatish Balay   size_t         *shortlength;
828f56c2debSBarry Smith   int            *shortcount,err;
829e5c89e4eSSatish Balay   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
830ace3abfcSBarry Smith   PetscBool      match;
831e5c89e4eSSatish Balay   const char     **shortfunction;
832e5c89e4eSSatish Balay   PetscLogDouble rss;
833e5c89e4eSSatish Balay   MPI_Status     status;
834e5c89e4eSSatish Balay   PetscErrorCode ierr;
835e5c89e4eSSatish Balay 
836e5c89e4eSSatish Balay   PetscFunctionBegin;
837e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
838e5c89e4eSSatish Balay   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
839e5c89e4eSSatish Balay   /*
840e5c89e4eSSatish Balay        Try to get the data printed in order by processor. This will only sometimes work
841e5c89e4eSSatish Balay   */
842f56c2debSBarry Smith   err = fflush(fp);
843e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
844f56c2debSBarry Smith 
845e5c89e4eSSatish Balay   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
846e5c89e4eSSatish Balay   if (rank) {
847e5c89e4eSSatish Balay     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
848e5c89e4eSSatish Balay   }
849e5c89e4eSSatish Balay 
850768aa557SSatish 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()");
851768aa557SSatish Balay 
852da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
853f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
854e5c89e4eSSatish Balay   if (rss) {
855f3d65365SJed 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);
856e5c89e4eSSatish Balay   } else {
857e5c89e4eSSatish 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);
858e5c89e4eSSatish Balay   }
859e32f2f54SBarry Smith   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
860e32f2f54SBarry Smith   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
861e32f2f54SBarry Smith   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
86297b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
863e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
864e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
865e5c89e4eSSatish Balay       if (match) {
866e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
86759ffdab8SBarry Smith         shortcount[j]++;
868e5c89e4eSSatish Balay         goto foundit;
869e5c89e4eSSatish Balay       }
870e5c89e4eSSatish Balay     }
871e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
872e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
87359ffdab8SBarry Smith     shortcount[n]    = 1;
874e5c89e4eSSatish Balay     n++;
875e5c89e4eSSatish Balay foundit:;
876e5c89e4eSSatish Balay   }
877e5c89e4eSSatish Balay 
878e32f2f54SBarry Smith   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
879e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
880e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
881e5c89e4eSSatish Balay 
882e5c89e4eSSatish Balay   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
883e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
88459ffdab8SBarry 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);
885e5c89e4eSSatish Balay   }
886e5c89e4eSSatish Balay   free(perm);
887e5c89e4eSSatish Balay   free(shortlength);
88859ffdab8SBarry Smith   free(shortcount);
889e5c89e4eSSatish Balay   free((char**)shortfunction);
890f56c2debSBarry Smith   err = fflush(fp);
891e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
892e5c89e4eSSatish Balay   if (rank != size-1) {
893e5c89e4eSSatish Balay     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
894e5c89e4eSSatish Balay   }
895e5c89e4eSSatish Balay   PetscFunctionReturn(0);
896e5c89e4eSSatish Balay }
897e5c89e4eSSatish Balay 
898e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
899e5c89e4eSSatish Balay 
900dc37d89fSBarry Smith /*@
901e5c89e4eSSatish Balay     PetscMallocDebug - Turns on/off debugging for the memory management routines.
902e5c89e4eSSatish Balay 
903e5c89e4eSSatish Balay     Not Collective
904e5c89e4eSSatish Balay 
905e5c89e4eSSatish Balay     Input Parameter:
906e5c89e4eSSatish Balay .   level - PETSC_TRUE or PETSC_FALSE
907e5c89e4eSSatish Balay 
908e5c89e4eSSatish Balay    Level: intermediate
909e5c89e4eSSatish Balay 
910e5c89e4eSSatish Balay .seealso: CHKMEMQ(), PetscMallocValidate()
911e5c89e4eSSatish Balay @*/
9127087cfbeSBarry Smith PetscErrorCode  PetscMallocDebug(PetscBool level)
913e5c89e4eSSatish Balay {
914e5c89e4eSSatish Balay   PetscFunctionBegin;
915e5c89e4eSSatish Balay   TRdebugLevel = level;
916e5c89e4eSSatish Balay   PetscFunctionReturn(0);
917e5c89e4eSSatish Balay }
9180acecf5bSBarry Smith 
919dc37d89fSBarry Smith /*@
9200acecf5bSBarry Smith     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
9210acecf5bSBarry Smith 
9220acecf5bSBarry Smith     Not Collective
9230acecf5bSBarry Smith 
9240acecf5bSBarry Smith     Output Parameter:
9250acecf5bSBarry Smith .    flg - PETSC_TRUE if any debugger
9260acecf5bSBarry Smith 
9270acecf5bSBarry Smith    Level: intermediate
9280acecf5bSBarry Smith 
9290acecf5bSBarry Smith     Note that by default, the debug version always does some debugging unless you run with -malloc no
9300acecf5bSBarry Smith 
9310acecf5bSBarry Smith 
9320acecf5bSBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate()
9330acecf5bSBarry Smith @*/
9340acecf5bSBarry Smith PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
9350acecf5bSBarry Smith {
9360acecf5bSBarry Smith   PetscFunctionBegin;
9370acecf5bSBarry Smith   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
9380acecf5bSBarry Smith   else *flg = PETSC_FALSE;
9390acecf5bSBarry Smith   PetscFunctionReturn(0);
9400acecf5bSBarry Smith }
941