xref: /petsc/src/sys/memory/mtr.c (revision 3854875937c97dfa6f77d5745fa8c0bc6576357e)
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 */
16071fcb05SBarry 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**);
19071fcb05SBarry 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:
114*38548759SBarry Smith     This is only run if PetscMallocDebug() has been called which is set by -malloc_test (if debugging is turned on) or -malloc_debug (any time)
115*38548759SBarry Smith 
116e5c89e4eSSatish Balay     You should generally use CHKMEMQ as a short cut for calling this
117e5c89e4eSSatish Balay     routine.
118e5c89e4eSSatish Balay 
119efca3c55SSatish Balay     The line, function, file are given by the C preprocessor as
120e5c89e4eSSatish Balay 
121e5c89e4eSSatish Balay     The Fortran calling sequence is simply PetscMallocValidate(ierr)
122e5c89e4eSSatish Balay 
123e5c89e4eSSatish Balay    No output is generated if there are no problems detected.
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay .seealso: CHKMEMQ
126e5c89e4eSSatish Balay 
127e5c89e4eSSatish Balay @*/
128efca3c55SSatish Balay PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
129e5c89e4eSSatish Balay {
1306c093d5bSvictor   TRSPACE      *head,*lasthead;
131e5c89e4eSSatish Balay   char         *a;
1320700a824SBarry Smith   PetscClassId *nend;
133e5c89e4eSSatish Balay 
134*38548759SBarry Smith   if (!TRdebugLevel) return 0;
135e5c89e4eSSatish Balay   PetscFunctionBegin;
1366c093d5bSvictor   head = TRhead; lasthead = NULL;
137e5c89e4eSSatish Balay   while (head) {
1380700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
139efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s\n",function,line,file);
140e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
141e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
142efca3c55SSatish Balay       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
143e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
144e5c89e4eSSatish Balay     }
145e5c89e4eSSatish Balay     a    = (char*)(((TrSPACE*)head) + 1);
1460700a824SBarry Smith     nend = (PetscClassId*)(a + head->size);
1470700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
148efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
149e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
150e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
151e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
152e5c89e4eSSatish Balay       } else {
153e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
154efca3c55SSatish Balay         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
155e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
156e5c89e4eSSatish Balay       }
157e5c89e4eSSatish Balay     }
1586c093d5bSvictor     lasthead = head;
159e5c89e4eSSatish Balay     head     = head->next;
160e5c89e4eSSatish Balay   }
161e5c89e4eSSatish Balay   PetscFunctionReturn(0);
162e5c89e4eSSatish Balay }
163e5c89e4eSSatish Balay 
164e5c89e4eSSatish Balay /*
165e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
166e5c89e4eSSatish Balay 
167e5c89e4eSSatish Balay     Input Parameters:
168e5c89e4eSSatish Balay +   a   - number of bytes to allocate
169e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
170efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
171e5c89e4eSSatish Balay 
172e5c89e4eSSatish Balay     Returns:
173e5c89e4eSSatish Balay     double aligned pointer to requested storage, or null if not
174e5c89e4eSSatish Balay     available.
175e5c89e4eSSatish Balay  */
176071fcb05SBarry Smith PetscErrorCode  PetscTrMallocDefault(size_t a,PetscBool clear,int lineno,const char function[],const char filename[],void **result)
177e5c89e4eSSatish Balay {
178e5c89e4eSSatish Balay   TRSPACE        *head;
179e5c89e4eSSatish Balay   char           *inew;
180e5c89e4eSSatish Balay   size_t         nsize;
181e5c89e4eSSatish Balay   PetscErrorCode ierr;
182e5c89e4eSSatish Balay 
183e5c89e4eSSatish Balay   PetscFunctionBegin;
184f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
185f0ba7cfcSLisandro Dalcin   if (!a) { *result = NULL; PetscFunctionReturn(0); }
186f0ba7cfcSLisandro Dalcin 
187efca3c55SSatish Balay   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
188e5c89e4eSSatish Balay 
18925b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
190071fcb05SBarry Smith   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),clear,lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
191e3ed9ee7SBarry Smith 
192e5c89e4eSSatish Balay   head  = (TRSPACE*)inew;
193e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
194e5c89e4eSSatish Balay 
195e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
196e5c89e4eSSatish Balay   head->next   = TRhead;
197e5c89e4eSSatish Balay   TRhead       = head;
198f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
199e5c89e4eSSatish Balay   head->size   = nsize;
200e5c89e4eSSatish Balay   head->id     = TRid;
201e5c89e4eSSatish Balay   head->lineno = lineno;
202e5c89e4eSSatish Balay 
203e5c89e4eSSatish Balay   head->filename                 = filename;
204e5c89e4eSSatish Balay   head->functionname             = function;
2050700a824SBarry Smith   head->classid                  = CLASSID_VALUE;
2060700a824SBarry Smith   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
207e5c89e4eSSatish Balay 
208e5c89e4eSSatish Balay   TRallocated += nsize;
209a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
210e3ed9ee7SBarry Smith   if (PetscLogMemory) {
211e3ed9ee7SBarry Smith     PetscInt i;
212e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
213e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
214e3ed9ee7SBarry Smith     }
215e3ed9ee7SBarry Smith   }
216e5c89e4eSSatish Balay   TRfrags++;
217e5c89e4eSSatish Balay 
2188bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
21976386721SLisandro Dalcin   if (PetscStackActive()) {
2205c25fcd7SBarry Smith     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
2212c9581d2SBarry Smith     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2222c9581d2SBarry Smith     head->stack.line[head->stack.currentsize-2] = lineno;
2239de0f6ecSBarry Smith   } else {
2249de0f6ecSBarry Smith     head->stack.currentsize = 0;
22576386721SLisandro Dalcin   }
226e5c89e4eSSatish Balay #endif
227e5c89e4eSSatish Balay 
228e5c89e4eSSatish Balay   /*
229e5c89e4eSSatish Balay          Allow logging of all mallocs made
230e5c89e4eSSatish Balay   */
231574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
232e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
233e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
234e32f2f54SBarry Smith       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
235a297a907SKarl Rupp 
236a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
237e32f2f54SBarry Smith       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
238a297a907SKarl Rupp 
239a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
240e32f2f54SBarry Smith       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
241e5c89e4eSSatish Balay     }
242e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
243e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
244e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
245e5c89e4eSSatish Balay   }
246e5c89e4eSSatish Balay   *result = (void*)inew;
247e5c89e4eSSatish Balay   PetscFunctionReturn(0);
248e5c89e4eSSatish Balay }
249e5c89e4eSSatish Balay 
250e5c89e4eSSatish Balay 
251e5c89e4eSSatish Balay /*
252e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
253e5c89e4eSSatish Balay 
254e5c89e4eSSatish Balay    Input Parameters:
255e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
256e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
257e5c89e4eSSatish Balay .   file  - file name where used.  Use __FILE__ for this
258e5c89e4eSSatish Balay  */
259efca3c55SSatish Balay PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
260e5c89e4eSSatish Balay {
261e5c89e4eSSatish Balay   char           *a = (char*)aa;
262e5c89e4eSSatish Balay   TRSPACE        *head;
263e5c89e4eSSatish Balay   char           *ahead;
264e5c89e4eSSatish Balay   PetscErrorCode ierr;
2650700a824SBarry Smith   PetscClassId   *nend;
266e5c89e4eSSatish Balay 
267e5c89e4eSSatish Balay   PetscFunctionBegin;
268e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
26949d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
270e5c89e4eSSatish Balay 
271efca3c55SSatish Balay   ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr);
272e5c89e4eSSatish Balay 
273e5c89e4eSSatish Balay   ahead = a;
274e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
275e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
276e5c89e4eSSatish Balay 
2770700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
278efca3c55SSatish Balay     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
279e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
280e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
281e5c89e4eSSatish Balay   }
2820700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2830700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
284e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
285efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
286e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
287e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
288efca3c55SSatish Balay         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
289e5c89e4eSSatish Balay       } else {
290efca3c55SSatish Balay         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
291e5c89e4eSSatish Balay       }
292e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
293e5c89e4eSSatish Balay     } else {
294e5c89e4eSSatish Balay       /* Damaged tail */
295efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
296e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
297efca3c55SSatish Balay       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
298e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
299e5c89e4eSSatish Balay     }
300e5c89e4eSSatish Balay   }
301e5c89e4eSSatish Balay   /* Mark the location freed */
302e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
303e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
304e5c89e4eSSatish Balay   if (line > 0 && line < 50000) {
305e5c89e4eSSatish Balay     head->lineno       = line;
306e5c89e4eSSatish Balay     head->filename     = file;
307e5c89e4eSSatish Balay     head->functionname = function;
308e5c89e4eSSatish Balay   } else {
309e5c89e4eSSatish Balay     head->lineno = -head->lineno;
310e5c89e4eSSatish Balay   }
311e3ed9ee7SBarry Smith   if (TRallocated < head->size) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"TRallocate is smaller than memory just freed");
312e5c89e4eSSatish Balay   TRallocated -= head->size;
313e5c89e4eSSatish Balay   TRfrags--;
314e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
315e5c89e4eSSatish Balay   else TRhead = head->next;
316e5c89e4eSSatish Balay 
317e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
318efca3c55SSatish Balay   ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr);
319e5c89e4eSSatish Balay   PetscFunctionReturn(0);
320e5c89e4eSSatish Balay }
321e5c89e4eSSatish Balay 
322e5c89e4eSSatish Balay 
3233221ece2SMatthew G. Knepley 
3243221ece2SMatthew G. Knepley /*
3253221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3263221ece2SMatthew G. Knepley 
3273221ece2SMatthew G. Knepley   Input Parameters:
3283221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3293221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3303221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
3313221ece2SMatthew G. Knepley - result   - double aligned pointer to initial storage.
3323221ece2SMatthew G. Knepley 
3333221ece2SMatthew G. Knepley   Output Parameter:
3343221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3353221ece2SMatthew G. Knepley 
3363221ece2SMatthew G. Knepley   Level: developer
3373221ece2SMatthew G. Knepley 
3383221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3393221ece2SMatthew G. Knepley */
3403221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3413221ece2SMatthew G. Knepley {
3423221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3433221ece2SMatthew G. Knepley   TRSPACE        *head;
3443221ece2SMatthew G. Knepley   char           *ahead, *inew;
3453221ece2SMatthew G. Knepley   PetscClassId   *nend;
3463221ece2SMatthew G. Knepley   size_t         nsize;
3473221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3483221ece2SMatthew G. Knepley 
3493221ece2SMatthew G. Knepley   PetscFunctionBegin;
350c22f1541SToby Isaac   /* Realloc to zero = free */
351c22f1541SToby Isaac   if (!len) {
352c22f1541SToby Isaac     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
353c22f1541SToby Isaac     *result = NULL;
354c22f1541SToby Isaac     PetscFunctionReturn(0);
355c22f1541SToby Isaac   }
356f590eff4SLisandro Dalcin   /* Realloc with NULL = malloc */
357f590eff4SLisandro Dalcin   if (!*result) {
358071fcb05SBarry Smith     ierr = PetscTrMallocDefault(len,PETSC_FALSE,lineno,function,filename,result);CHKERRQ(ierr);
359f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
360f590eff4SLisandro Dalcin   }
3613221ece2SMatthew G. Knepley 
362*38548759SBarry Smith   ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
3633221ece2SMatthew G. Knepley 
3643221ece2SMatthew G. Knepley   ahead = a;
3653221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3663221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3673221ece2SMatthew G. Knepley   inew  = a;
3683221ece2SMatthew G. Knepley 
3693221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3703221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3713221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3723221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3733221ece2SMatthew G. Knepley   }
3743221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3753221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3763221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3773221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3783221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3793221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3803221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3813221ece2SMatthew G. Knepley       } else {
3823221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
3833221ece2SMatthew G. Knepley       }
3843221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3853221ece2SMatthew G. Knepley     } else {
3863221ece2SMatthew G. Knepley       /* Damaged tail */
3873221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3883221ece2SMatthew 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);
3893221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3903221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
3913221ece2SMatthew G. Knepley     }
3923221ece2SMatthew G. Knepley   }
3933221ece2SMatthew G. Knepley 
3943221ece2SMatthew G. Knepley   TRallocated -= head->size;
3953221ece2SMatthew G. Knepley   TRfrags--;
3963221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
3973221ece2SMatthew G. Knepley   else TRhead = head->next;
3983221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
3993221ece2SMatthew G. Knepley 
4003221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
4013221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
4023221ece2SMatthew G. Knepley 
4033221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
4043221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
4053221ece2SMatthew G. Knepley 
4063221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
4073221ece2SMatthew G. Knepley   head->next   = TRhead;
4083221ece2SMatthew G. Knepley   TRhead       = head;
4093221ece2SMatthew G. Knepley   head->prev   = NULL;
4103221ece2SMatthew G. Knepley   head->size   = nsize;
4113221ece2SMatthew G. Knepley   head->id     = TRid;
4123221ece2SMatthew G. Knepley   head->lineno = lineno;
4133221ece2SMatthew G. Knepley 
4143221ece2SMatthew G. Knepley   head->filename                 = filename;
4153221ece2SMatthew G. Knepley   head->functionname             = function;
4163221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4173221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4183221ece2SMatthew G. Knepley 
4193221ece2SMatthew G. Knepley   TRallocated += nsize;
4203221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
421e3ed9ee7SBarry Smith   if (PetscLogMemory) {
422e3ed9ee7SBarry Smith     PetscInt i;
423e3ed9ee7SBarry Smith     for (i=0; i<NumTRMaxMems; i++) {
424e3ed9ee7SBarry Smith       if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated;
425e3ed9ee7SBarry Smith     }
426e3ed9ee7SBarry Smith   }
4273221ece2SMatthew G. Knepley   TRfrags++;
4283221ece2SMatthew G. Knepley 
4293221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4303221ece2SMatthew G. Knepley   if (PetscStackActive()) {
4313221ece2SMatthew G. Knepley     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
4323221ece2SMatthew G. Knepley     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4333221ece2SMatthew G. Knepley     head->stack.line[head->stack.currentsize-2] = lineno;
4343221ece2SMatthew G. Knepley   } else {
4353221ece2SMatthew G. Knepley     head->stack.currentsize = 0;
4363221ece2SMatthew G. Knepley   }
4373221ece2SMatthew G. Knepley #endif
4383221ece2SMatthew G. Knepley 
4393221ece2SMatthew G. Knepley   /*
4403221ece2SMatthew G. Knepley          Allow logging of all mallocs made
4413221ece2SMatthew G. Knepley   */
4423221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4433221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4443221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
4453221ece2SMatthew G. Knepley       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4463221ece2SMatthew G. Knepley 
4473221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4483221ece2SMatthew G. Knepley       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4493221ece2SMatthew G. Knepley 
4503221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4513221ece2SMatthew G. Knepley       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4523221ece2SMatthew G. Knepley     }
4533221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4543221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4553221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4563221ece2SMatthew G. Knepley   }
4573221ece2SMatthew G. Knepley   *result = (void*)inew;
4583221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4593221ece2SMatthew G. Knepley }
4603221ece2SMatthew G. Knepley 
4613221ece2SMatthew G. Knepley 
462fe7fb379SMatthew Knepley /*@C
4630841954dSBarry Smith     PetscMemoryView - Shows the amount of memory currently being used
464e5c89e4eSSatish Balay         in a communicator.
465e5c89e4eSSatish Balay 
466e5c89e4eSSatish Balay     Collective on PetscViewer
467e5c89e4eSSatish Balay 
468e5c89e4eSSatish Balay     Input Parameter:
469e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
470e5c89e4eSSatish Balay -    message - string printed before values
471e5c89e4eSSatish Balay 
4720841954dSBarry Smith     Options Database:
4730841954dSBarry Smith +    -malloc - have PETSc track how much memory it has allocated
4740841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4750841954dSBarry Smith 
476e5c89e4eSSatish Balay     Level: intermediate
477e5c89e4eSSatish Balay 
4780841954dSBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage()
479e5c89e4eSSatish Balay  @*/
4800841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
481e5c89e4eSSatish Balay {
4820841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4830841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
484e5c89e4eSSatish Balay   PetscErrorCode ierr;
485e5c89e4eSSatish Balay   MPI_Comm       comm;
486e5c89e4eSSatish Balay 
487e5c89e4eSSatish Balay   PetscFunctionBegin;
488e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
489e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
4900841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
491e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
492e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
493e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
494e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
495e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
496e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4970841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4980841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4990841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5000841954dSBarry 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);
5010841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5020841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5030841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5040841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5050841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5060841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5070841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5080841954dSBarry 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);
5090841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5100841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5110841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5120841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
513e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5140841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5150841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5160841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5170841954dSBarry 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);
5180841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5190841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5200841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5210841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
522e5c89e4eSSatish Balay   } else if (resident && allocated) {
5230841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5240841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5250841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5260841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5270841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5280841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5290841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5300841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5310841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
532e5c89e4eSSatish Balay   } else if (allocated) {
5330841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5340841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5350841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5360841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5370841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5380841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
539e5c89e4eSSatish Balay   } else {
540e5c89e4eSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
541e5c89e4eSSatish Balay   }
542e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
543e5c89e4eSSatish Balay   PetscFunctionReturn(0);
544e5c89e4eSSatish Balay }
545e5c89e4eSSatish Balay 
54646eb3923SBarry Smith /*@
547e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
548e5c89e4eSSatish Balay 
549e5c89e4eSSatish Balay     Not Collective
550e5c89e4eSSatish Balay 
551e5c89e4eSSatish Balay     Output Parameters:
552e5c89e4eSSatish Balay .   space - number of bytes currently allocated
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay     Level: intermediate
555e5c89e4eSSatish Balay 
556e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
557e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
558e5c89e4eSSatish Balay  @*/
5597087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
560e5c89e4eSSatish Balay {
561e5c89e4eSSatish Balay   PetscFunctionBegin;
562e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
563e5c89e4eSSatish Balay   PetscFunctionReturn(0);
564e5c89e4eSSatish Balay }
565e5c89e4eSSatish Balay 
566dc37d89fSBarry Smith /*@
567e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
568e5c89e4eSSatish Balay         during this run.
569e5c89e4eSSatish Balay 
570e5c89e4eSSatish Balay     Not Collective
571e5c89e4eSSatish Balay 
572e5c89e4eSSatish Balay     Output Parameters:
573e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
574e5c89e4eSSatish Balay 
575e5c89e4eSSatish Balay     Level: intermediate
576e5c89e4eSSatish Balay 
577e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
578e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
579e5c89e4eSSatish Balay  @*/
5807087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
581e5c89e4eSSatish Balay {
582e5c89e4eSSatish Balay   PetscFunctionBegin;
583e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
584e5c89e4eSSatish Balay   PetscFunctionReturn(0);
585e5c89e4eSSatish Balay }
586e5c89e4eSSatish Balay 
587e3ed9ee7SBarry Smith /*@
588e3ed9ee7SBarry Smith     PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event
589e3ed9ee7SBarry Smith 
590e3ed9ee7SBarry Smith     Not Collective
591e3ed9ee7SBarry Smith 
592e3ed9ee7SBarry Smith     Input Parameter:
593e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
594e3ed9ee7SBarry Smith 
595e3ed9ee7SBarry Smith     Level: developer
596e3ed9ee7SBarry Smith 
597e3ed9ee7SBarry Smith .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
598e3ed9ee7SBarry Smith           PetscMallocPopMaximumUsage()
599e3ed9ee7SBarry Smith  @*/
600e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPushMaximumUsage(int event)
601e3ed9ee7SBarry Smith {
602e3ed9ee7SBarry Smith   PetscFunctionBegin;
603e3ed9ee7SBarry Smith   if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0);
604e3ed9ee7SBarry Smith   TRMaxMems[NumTRMaxMems-1]       = TRallocated;
605e3ed9ee7SBarry Smith   TRMaxMemsEvents[NumTRMaxMems-1] = event;
606e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
607e3ed9ee7SBarry Smith }
608e3ed9ee7SBarry Smith 
609e3ed9ee7SBarry Smith /*@
610e3ed9ee7SBarry Smith     PetscMallocPopMaximumUsage - collect the maximum memory usage over an event
611e3ed9ee7SBarry Smith 
612e3ed9ee7SBarry Smith     Not Collective
613e3ed9ee7SBarry Smith 
614e3ed9ee7SBarry Smith     Input Parameter:
615e3ed9ee7SBarry Smith .   event - an event id; this is just for error checking
616e3ed9ee7SBarry Smith 
617e3ed9ee7SBarry Smith     Output Parameter:
618e3ed9ee7SBarry Smith .   mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event
619e3ed9ee7SBarry Smith 
620e3ed9ee7SBarry Smith     Level: developer
621e3ed9ee7SBarry Smith 
622e3ed9ee7SBarry Smith .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
623e3ed9ee7SBarry Smith           PetscMallocPushMaximumUsage()
624e3ed9ee7SBarry Smith  @*/
625e3ed9ee7SBarry Smith PetscErrorCode  PetscMallocPopMaximumUsage(int event,PetscLogDouble *mu)
626e3ed9ee7SBarry Smith {
627e3ed9ee7SBarry Smith   PetscFunctionBegin;
628e3ed9ee7SBarry Smith   *mu = 0;
629e3ed9ee7SBarry Smith   if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0);
630e3ed9ee7SBarry Smith   if (TRMaxMemsEvents[NumTRMaxMems] != event) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"PetscMallocPush/PopMaximumUsage() are not nested");
631e3ed9ee7SBarry Smith   *mu = TRMaxMems[NumTRMaxMems];
632e3ed9ee7SBarry Smith   PetscFunctionReturn(0);
633e3ed9ee7SBarry Smith }
634e3ed9ee7SBarry Smith 
635a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
636a64a8e02SBarry Smith /*@C
637a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
638a64a8e02SBarry Smith 
639a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
640a64a8e02SBarry Smith 
641a64a8e02SBarry Smith    Input Parameter:
642a64a8e02SBarry Smith .    ptr - the memory location
643a64a8e02SBarry Smith 
644a64a8e02SBarry Smith    Output Paramter:
645a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
646a64a8e02SBarry Smith 
647a64a8e02SBarry Smith    Level: intermediate
648a64a8e02SBarry Smith 
649a64a8e02SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
650a64a8e02SBarry Smith @*/
651a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
652a64a8e02SBarry Smith {
653a64a8e02SBarry Smith   TRSPACE *head;
654a64a8e02SBarry Smith 
655a64a8e02SBarry Smith   PetscFunctionBegin;
656a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
657a64a8e02SBarry Smith   *stack = &head->stack;
658a64a8e02SBarry Smith   PetscFunctionReturn(0);
659a64a8e02SBarry Smith }
66076386721SLisandro Dalcin #else
66176386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
66276386721SLisandro Dalcin {
66376386721SLisandro Dalcin   PetscFunctionBegin;
664f0ba7cfcSLisandro Dalcin   *stack = NULL;
66576386721SLisandro Dalcin   PetscFunctionReturn(0);
66676386721SLisandro Dalcin }
667a64a8e02SBarry Smith #endif
668a64a8e02SBarry Smith 
669e5c89e4eSSatish Balay /*@C
670e5c89e4eSSatish Balay    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
671e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
672e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
673e5c89e4eSSatish Balay    allocated.
674e5c89e4eSSatish Balay 
675e5c89e4eSSatish Balay    Collective on PETSC_COMM_WORLD
676e5c89e4eSSatish Balay 
677e5c89e4eSSatish Balay    Input Parameter:
678e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
679e5c89e4eSSatish Balay 
680e5c89e4eSSatish Balay    Options Database Key:
681e5c89e4eSSatish Balay .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
682e5c89e4eSSatish Balay 
683e5c89e4eSSatish Balay    Level: intermediate
684e5c89e4eSSatish Balay 
685e5c89e4eSSatish Balay    Fortran Note:
686e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
687e5c89e4eSSatish Balay    The fp defaults to stdout.
688e5c89e4eSSatish Balay 
68995452b02SPatrick Sanan    Notes:
69095452b02SPatrick Sanan     uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
691e5c89e4eSSatish Balay           has been freed.
692e5c89e4eSSatish Balay 
6939e9a1f8fSvictor .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
694e5c89e4eSSatish Balay @*/
6957087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
696e5c89e4eSSatish Balay {
697e5c89e4eSSatish Balay   TRSPACE        *head;
698e3ed9ee7SBarry Smith   size_t         libAlloc = 0;
699e5c89e4eSSatish Balay   PetscErrorCode ierr;
700e5c89e4eSSatish Balay   PetscMPIInt    rank;
701e5c89e4eSSatish Balay 
702e5c89e4eSSatish Balay   PetscFunctionBegin;
703e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
704da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
705e5c89e4eSSatish Balay   head = TRhead;
706e5c89e4eSSatish Balay   while (head) {
7075486ca60SMatthew G. Knepley     libAlloc += head->size;
7085486ca60SMatthew G. Knepley     head = head->next;
7095486ca60SMatthew G. Knepley   }
7105486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
7115486ca60SMatthew G. Knepley   head = TRhead;
7125486ca60SMatthew G. Knepley   while (head) {
7135486ca60SMatthew G. Knepley     PetscBool isLib;
7145486ca60SMatthew G. Knepley 
7155486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
7165486ca60SMatthew G. Knepley     if (!isLib) {
717efca3c55SSatish Balay       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
7188bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
719e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
720e5c89e4eSSatish Balay #endif
7215486ca60SMatthew G. Knepley     }
722e5c89e4eSSatish Balay     head = head->next;
723e5c89e4eSSatish Balay   }
724e5c89e4eSSatish Balay   PetscFunctionReturn(0);
725e5c89e4eSSatish Balay }
726e5c89e4eSSatish Balay 
727e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
728e5c89e4eSSatish Balay 
729dc37d89fSBarry Smith /*@
730e5c89e4eSSatish Balay     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
731e5c89e4eSSatish Balay 
732e5c89e4eSSatish Balay     Not Collective
733e5c89e4eSSatish Balay 
734e5c89e4eSSatish Balay     Options Database Key:
735574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
736574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
737e5c89e4eSSatish Balay 
738e5c89e4eSSatish Balay     Level: advanced
739e5c89e4eSSatish Balay 
740574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
741e5c89e4eSSatish Balay @*/
7427087cfbeSBarry Smith PetscErrorCode PetscMallocSetDumpLog(void)
743e5c89e4eSSatish Balay {
74421b680ceSJed Brown   PetscErrorCode ierr;
74521b680ceSJed Brown 
746e5c89e4eSSatish Balay   PetscFunctionBegin;
747e5c89e4eSSatish Balay   PetscLogMalloc = 0;
748a297a907SKarl Rupp 
74921b680ceSJed Brown   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
750e5c89e4eSSatish Balay   PetscFunctionReturn(0);
751e5c89e4eSSatish Balay }
752e5c89e4eSSatish Balay 
753dc37d89fSBarry Smith /*@
754574034a9SJed Brown     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
755574034a9SJed Brown 
756574034a9SJed Brown     Not Collective
757574034a9SJed Brown 
758574034a9SJed Brown     Input Arguments:
759574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
760574034a9SJed Brown 
761574034a9SJed Brown     Options Database Key:
762574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
763574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
764574034a9SJed Brown 
765574034a9SJed Brown     Level: advanced
766574034a9SJed Brown 
767574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
768574034a9SJed Brown @*/
769574034a9SJed Brown PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
770574034a9SJed Brown {
771574034a9SJed Brown   PetscErrorCode ierr;
772574034a9SJed Brown 
773574034a9SJed Brown   PetscFunctionBegin;
774574034a9SJed Brown   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
775574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
776574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
777574034a9SJed Brown   PetscFunctionReturn(0);
778574034a9SJed Brown }
779574034a9SJed Brown 
780dc37d89fSBarry Smith /*@
78118a2528dSJed Brown     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
78218a2528dSJed Brown 
78318a2528dSJed Brown     Not Collective
78418a2528dSJed Brown 
78518a2528dSJed Brown     Output Arguments
78618a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
78718a2528dSJed Brown 
78818a2528dSJed Brown     Options Database Key:
78918a2528dSJed Brown .  -malloc_log - Activates PetscMallocDumpLog()
79018a2528dSJed Brown 
79118a2528dSJed Brown     Level: advanced
79218a2528dSJed Brown 
79318a2528dSJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog()
79418a2528dSJed Brown @*/
79518a2528dSJed Brown PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
79618a2528dSJed Brown {
79718a2528dSJed Brown 
79818a2528dSJed Brown   PetscFunctionBegin;
79918a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
80018a2528dSJed Brown   PetscFunctionReturn(0);
80118a2528dSJed Brown }
80218a2528dSJed Brown 
803e5c89e4eSSatish Balay /*@C
804e5c89e4eSSatish Balay     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
80521b680ceSJed Brown        PetscMemoryGetMaximumUsage()
806e5c89e4eSSatish Balay 
807e5c89e4eSSatish Balay     Collective on PETSC_COMM_WORLD
808e5c89e4eSSatish Balay 
809e5c89e4eSSatish Balay     Input Parameter:
8100298fd71SBarry Smith .   fp - file pointer; or NULL
811e5c89e4eSSatish Balay 
812e5c89e4eSSatish Balay     Options Database Key:
813e5c89e4eSSatish Balay .  -malloc_log - Activates PetscMallocDumpLog()
814e5c89e4eSSatish Balay 
815e5c89e4eSSatish Balay     Level: advanced
816e5c89e4eSSatish Balay 
817e5c89e4eSSatish Balay    Fortran Note:
818e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
819e5c89e4eSSatish Balay    The fp defaults to stdout.
820e5c89e4eSSatish Balay 
821e5c89e4eSSatish Balay .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
822e5c89e4eSSatish Balay @*/
8237087cfbeSBarry Smith PetscErrorCode  PetscMallocDumpLog(FILE *fp)
824e5c89e4eSSatish Balay {
825e5c89e4eSSatish Balay   PetscInt       i,j,n,dummy,*perm;
826e5c89e4eSSatish Balay   size_t         *shortlength;
827f56c2debSBarry Smith   int            *shortcount,err;
828e5c89e4eSSatish Balay   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
829ace3abfcSBarry Smith   PetscBool      match;
830e5c89e4eSSatish Balay   const char     **shortfunction;
831e5c89e4eSSatish Balay   PetscLogDouble rss;
832e5c89e4eSSatish Balay   MPI_Status     status;
833e5c89e4eSSatish Balay   PetscErrorCode ierr;
834e5c89e4eSSatish Balay 
835e5c89e4eSSatish Balay   PetscFunctionBegin;
836e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
837e5c89e4eSSatish Balay   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
838e5c89e4eSSatish Balay   /*
839e5c89e4eSSatish Balay        Try to get the data printed in order by processor. This will only sometimes work
840e5c89e4eSSatish Balay   */
841f56c2debSBarry Smith   err = fflush(fp);
842e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
843f56c2debSBarry Smith 
844e5c89e4eSSatish Balay   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
845e5c89e4eSSatish Balay   if (rank) {
846e5c89e4eSSatish Balay     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
847e5c89e4eSSatish Balay   }
848e5c89e4eSSatish Balay 
849768aa557SSatish 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()");
850768aa557SSatish Balay 
851da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
852f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
853e5c89e4eSSatish Balay   if (rss) {
854f3d65365SJed 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);
855e5c89e4eSSatish Balay   } else {
856e5c89e4eSSatish 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);
857e5c89e4eSSatish Balay   }
858e32f2f54SBarry Smith   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
859e32f2f54SBarry Smith   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
860e32f2f54SBarry Smith   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
86197b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
862e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
863e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
864e5c89e4eSSatish Balay       if (match) {
865e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
86659ffdab8SBarry Smith         shortcount[j]++;
867e5c89e4eSSatish Balay         goto foundit;
868e5c89e4eSSatish Balay       }
869e5c89e4eSSatish Balay     }
870e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
871e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
87259ffdab8SBarry Smith     shortcount[n]    = 1;
873e5c89e4eSSatish Balay     n++;
874e5c89e4eSSatish Balay foundit:;
875e5c89e4eSSatish Balay   }
876e5c89e4eSSatish Balay 
877e32f2f54SBarry Smith   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
878e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
879e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
880e5c89e4eSSatish Balay 
881e5c89e4eSSatish Balay   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
882e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
88359ffdab8SBarry 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);
884e5c89e4eSSatish Balay   }
885e5c89e4eSSatish Balay   free(perm);
886e5c89e4eSSatish Balay   free(shortlength);
88759ffdab8SBarry Smith   free(shortcount);
888e5c89e4eSSatish Balay   free((char**)shortfunction);
889f56c2debSBarry Smith   err = fflush(fp);
890e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
891e5c89e4eSSatish Balay   if (rank != size-1) {
892e5c89e4eSSatish Balay     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
893e5c89e4eSSatish Balay   }
894e5c89e4eSSatish Balay   PetscFunctionReturn(0);
895e5c89e4eSSatish Balay }
896e5c89e4eSSatish Balay 
897e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
898e5c89e4eSSatish Balay 
899dc37d89fSBarry Smith /*@
900e5c89e4eSSatish Balay     PetscMallocDebug - Turns on/off debugging for the memory management routines.
901e5c89e4eSSatish Balay 
902e5c89e4eSSatish Balay     Not Collective
903e5c89e4eSSatish Balay 
904e5c89e4eSSatish Balay     Input Parameter:
905e5c89e4eSSatish Balay .   level - PETSC_TRUE or PETSC_FALSE
906e5c89e4eSSatish Balay 
907e5c89e4eSSatish Balay    Level: intermediate
908e5c89e4eSSatish Balay 
909e5c89e4eSSatish Balay .seealso: CHKMEMQ(), PetscMallocValidate()
910e5c89e4eSSatish Balay @*/
9117087cfbeSBarry Smith PetscErrorCode  PetscMallocDebug(PetscBool level)
912e5c89e4eSSatish Balay {
913e5c89e4eSSatish Balay   PetscFunctionBegin;
914e5c89e4eSSatish Balay   TRdebugLevel = level;
915e5c89e4eSSatish Balay   PetscFunctionReturn(0);
916e5c89e4eSSatish Balay }
9170acecf5bSBarry Smith 
918dc37d89fSBarry Smith /*@
9190acecf5bSBarry Smith     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
9200acecf5bSBarry Smith 
9210acecf5bSBarry Smith     Not Collective
9220acecf5bSBarry Smith 
9230acecf5bSBarry Smith     Output Parameter:
9240acecf5bSBarry Smith .    flg - PETSC_TRUE if any debugger
9250acecf5bSBarry Smith 
9260acecf5bSBarry Smith    Level: intermediate
9270acecf5bSBarry Smith 
9280acecf5bSBarry Smith     Note that by default, the debug version always does some debugging unless you run with -malloc no
9290acecf5bSBarry Smith 
9300acecf5bSBarry Smith 
9310acecf5bSBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate()
9320acecf5bSBarry Smith @*/
9330acecf5bSBarry Smith PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
9340acecf5bSBarry Smith {
9350acecf5bSBarry Smith   PetscFunctionBegin;
9360acecf5bSBarry Smith   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
9370acecf5bSBarry Smith   else *flg = PETSC_FALSE;
9380acecf5bSBarry Smith   PetscFunctionReturn(0);
9390acecf5bSBarry Smith }
940