xref: /petsc/src/sys/memory/mtr.c (revision f590eff4b3f246503244355ffdc5e442c736bc96)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay      Interface to malloc() and free(). This code allows for
4e5c89e4eSSatish Balay   logging of memory usage and some error checking
5e5c89e4eSSatish Balay */
6c6db04a5SJed Brown #include <petscsys.h>           /*I "petscsys.h" I*/
7665c2dedSJed Brown #include <petscviewer.h>
8e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
9e5c89e4eSSatish Balay #include <malloc.h>
10e5c89e4eSSatish Balay #endif
11e5c89e4eSSatish Balay 
12e5c89e4eSSatish Balay 
13e5c89e4eSSatish Balay /*
14e5c89e4eSSatish Balay      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
15e5c89e4eSSatish Balay */
1695c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,int,const char[],const char[],void**);
1795c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]);
1895c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**);
1995c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],void**);
2095c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]);
2195c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrReallocDefault(size_t,int,const char[],const char[],void**);
22e5c89e4eSSatish Balay 
23e5c89e4eSSatish Balay 
240700a824SBarry Smith #define CLASSID_VALUE  ((PetscClassId) 0xf0e0d0c9)
250700a824SBarry Smith #define ALREADY_FREED  ((PetscClassId) 0x0f0e0d9c)
26e5c89e4eSSatish Balay 
27e5c89e4eSSatish Balay typedef struct _trSPACE {
28e5c89e4eSSatish Balay   size_t       size;
29e5c89e4eSSatish Balay   int          id;
30e5c89e4eSSatish Balay   int          lineno;
31e5c89e4eSSatish Balay   const char   *filename;
32e5c89e4eSSatish Balay   const char   *functionname;
330700a824SBarry Smith   PetscClassId classid;
348bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
35e5c89e4eSSatish Balay   PetscStack   stack;
36e5c89e4eSSatish Balay #endif
37e5c89e4eSSatish Balay   struct _trSPACE *next,*prev;
38e5c89e4eSSatish Balay } TRSPACE;
39e5c89e4eSSatish Balay 
4025b53cc9SJed Brown /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
4125b53cc9SJed Brown    It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN.
4225b53cc9SJed Brown */
43e5c89e4eSSatish Balay 
44a64a8e02SBarry Smith #define HEADER_BYTES  ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))
45e5c89e4eSSatish Balay 
46e5c89e4eSSatish Balay 
4725b53cc9SJed Brown /* This union is used to insure that the block passed to the user retains
4825b53cc9SJed Brown    a minimum alignment of PETSC_MEMALIGN.
4925b53cc9SJed Brown */
50e5c89e4eSSatish Balay typedef union {
51e5c89e4eSSatish Balay   TRSPACE sp;
5225b53cc9SJed Brown   char    v[HEADER_BYTES];
53e5c89e4eSSatish Balay } TrSPACE;
54e5c89e4eSSatish Balay 
55b022a5c1SBarry Smith 
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;
62e5c89e4eSSatish Balay /*
63e5c89e4eSSatish Balay       Arrays to log information on all Mallocs
64e5c89e4eSSatish Balay */
65f0ba7cfcSLisandro Dalcin static int        PetscLogMallocMax       = 10000;
66f0ba7cfcSLisandro Dalcin static int        PetscLogMalloc          = -1;
67574034a9SJed Brown static size_t     PetscLogMallocThreshold = 0;
68e5c89e4eSSatish Balay static size_t     *PetscLogMallocLength;
69efca3c55SSatish Balay static const char **PetscLogMallocFile,**PetscLogMallocFunction;
70e5c89e4eSSatish Balay 
7195c0884eSLisandro Dalcin PETSC_INTERN PetscErrorCode PetscSetUseTrMalloc_Private(void)
72b022a5c1SBarry Smith {
73b022a5c1SBarry Smith   PetscErrorCode ierr;
74b022a5c1SBarry Smith 
75b022a5c1SBarry Smith   PetscFunctionBegin;
76b022a5c1SBarry Smith   ierr = PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);CHKERRQ(ierr);
773221ece2SMatthew G. Knepley   PetscTrRealloc = PetscTrReallocDefault;
78a297a907SKarl Rupp 
79b022a5c1SBarry Smith   TRallocated       = 0;
80b022a5c1SBarry Smith   TRfrags           = 0;
81f0ba7cfcSLisandro Dalcin   TRhead            = NULL;
82b022a5c1SBarry Smith   TRid              = 0;
83b022a5c1SBarry Smith   TRdebugLevel      = PETSC_FALSE;
84b022a5c1SBarry Smith   TRMaxMem          = 0;
85b022a5c1SBarry Smith   PetscLogMallocMax = 10000;
86b022a5c1SBarry Smith   PetscLogMalloc    = -1;
87b022a5c1SBarry Smith   PetscFunctionReturn(0);
88b022a5c1SBarry Smith }
89b022a5c1SBarry Smith 
90e5c89e4eSSatish Balay /*@C
91e5c89e4eSSatish Balay    PetscMallocValidate - Test the memory for corruption.  This can be used to
92e5c89e4eSSatish Balay    check for memory overwrites.
93e5c89e4eSSatish Balay 
94e5c89e4eSSatish Balay    Input Parameter:
95e5c89e4eSSatish Balay +  line - line number where call originated.
96e5c89e4eSSatish Balay .  function - name of function calling
97efca3c55SSatish Balay -  file - file where function is
98e5c89e4eSSatish Balay 
99e5c89e4eSSatish Balay    Return value:
100e5c89e4eSSatish Balay    The number of errors detected.
101e5c89e4eSSatish Balay 
102e5c89e4eSSatish Balay    Output Effect:
103e5c89e4eSSatish Balay    Error messages are written to stdout.
104e5c89e4eSSatish Balay 
105e5c89e4eSSatish Balay    Level: advanced
106e5c89e4eSSatish Balay 
107e5c89e4eSSatish Balay    Notes:
108e5c89e4eSSatish Balay     You should generally use CHKMEMQ as a short cut for calling this
109e5c89e4eSSatish Balay     routine.
110e5c89e4eSSatish Balay 
111efca3c55SSatish Balay     The line, function, file are given by the C preprocessor as
112e5c89e4eSSatish Balay 
113e5c89e4eSSatish Balay     The Fortran calling sequence is simply PetscMallocValidate(ierr)
114e5c89e4eSSatish Balay 
115e5c89e4eSSatish Balay    No output is generated if there are no problems detected.
116e5c89e4eSSatish Balay 
117e5c89e4eSSatish Balay .seealso: CHKMEMQ
118e5c89e4eSSatish Balay 
119e5c89e4eSSatish Balay @*/
120efca3c55SSatish Balay PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[])
121e5c89e4eSSatish Balay {
1226c093d5bSvictor   TRSPACE      *head,*lasthead;
123e5c89e4eSSatish Balay   char         *a;
1240700a824SBarry Smith   PetscClassId *nend;
125e5c89e4eSSatish Balay 
126e5c89e4eSSatish Balay   PetscFunctionBegin;
1276c093d5bSvictor   head = TRhead; lasthead = NULL;
128e5c89e4eSSatish Balay   while (head) {
1290700a824SBarry Smith     if (head->classid != CLASSID_VALUE) {
130efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s\n",function,line,file);
131e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
132e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
133efca3c55SSatish Balay       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s\n",lasthead->functionname,lasthead->lineno,lasthead->filename);
134e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
135e5c89e4eSSatish Balay     }
136e5c89e4eSSatish Balay     a    = (char*)(((TrSPACE*)head) + 1);
1370700a824SBarry Smith     nend = (PetscClassId*)(a + head->size);
1380700a824SBarry Smith     if (*nend != CLASSID_VALUE) {
139efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s\n",function,line,file);
140e5c89e4eSSatish Balay       if (*nend == ALREADY_FREED) {
141e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
142e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
143e5c89e4eSSatish Balay       } else {
144e5c89e4eSSatish Balay         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
145efca3c55SSatish Balay         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
146e32f2f54SBarry Smith         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
147e5c89e4eSSatish Balay       }
148e5c89e4eSSatish Balay     }
1496c093d5bSvictor     lasthead = head;
150e5c89e4eSSatish Balay     head     = head->next;
151e5c89e4eSSatish Balay   }
152e5c89e4eSSatish Balay   PetscFunctionReturn(0);
153e5c89e4eSSatish Balay }
154e5c89e4eSSatish Balay 
155e5c89e4eSSatish Balay /*
156e5c89e4eSSatish Balay     PetscTrMallocDefault - Malloc with tracing.
157e5c89e4eSSatish Balay 
158e5c89e4eSSatish Balay     Input Parameters:
159e5c89e4eSSatish Balay +   a   - number of bytes to allocate
160e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
161efca3c55SSatish Balay -   filename  - file name where used.  Use __FILE__ for this
162e5c89e4eSSatish Balay 
163e5c89e4eSSatish Balay     Returns:
164e5c89e4eSSatish Balay     double aligned pointer to requested storage, or null if not
165e5c89e4eSSatish Balay     available.
166e5c89e4eSSatish Balay  */
167efca3c55SSatish Balay PetscErrorCode  PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],void **result)
168e5c89e4eSSatish Balay {
169e5c89e4eSSatish Balay   TRSPACE        *head;
170e5c89e4eSSatish Balay   char           *inew;
171e5c89e4eSSatish Balay   size_t         nsize;
172e5c89e4eSSatish Balay   PetscErrorCode ierr;
173e5c89e4eSSatish Balay 
174e5c89e4eSSatish Balay   PetscFunctionBegin;
175f0ba7cfcSLisandro Dalcin   /* Do not try to handle empty blocks */
176f0ba7cfcSLisandro Dalcin   if (!a) { *result = NULL; PetscFunctionReturn(0); }
177f0ba7cfcSLisandro Dalcin 
178e5c89e4eSSatish Balay   if (TRdebugLevel) {
179efca3c55SSatish Balay     ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);
180e5c89e4eSSatish Balay   }
181e5c89e4eSSatish Balay 
18225b53cc9SJed Brown   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
183efca3c55SSatish Balay   ierr  = PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
184e5c89e4eSSatish Balay 
185e5c89e4eSSatish Balay   head  = (TRSPACE*)inew;
186e5c89e4eSSatish Balay   inew += sizeof(TrSPACE);
187e5c89e4eSSatish Balay 
188e5c89e4eSSatish Balay   if (TRhead) TRhead->prev = head;
189e5c89e4eSSatish Balay   head->next   = TRhead;
190e5c89e4eSSatish Balay   TRhead       = head;
191f0ba7cfcSLisandro Dalcin   head->prev   = NULL;
192e5c89e4eSSatish Balay   head->size   = nsize;
193e5c89e4eSSatish Balay   head->id     = TRid;
194e5c89e4eSSatish Balay   head->lineno = lineno;
195e5c89e4eSSatish Balay 
196e5c89e4eSSatish Balay   head->filename                 = filename;
197e5c89e4eSSatish Balay   head->functionname             = function;
1980700a824SBarry Smith   head->classid                  = CLASSID_VALUE;
1990700a824SBarry Smith   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
200e5c89e4eSSatish Balay 
201e5c89e4eSSatish Balay   TRallocated += nsize;
202a297a907SKarl Rupp   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
203e5c89e4eSSatish Balay   TRfrags++;
204e5c89e4eSSatish Balay 
2058bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
20676386721SLisandro Dalcin   if (PetscStackActive()) {
2075c25fcd7SBarry Smith     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
2082c9581d2SBarry Smith     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
2092c9581d2SBarry Smith     head->stack.line[head->stack.currentsize-2] = lineno;
2109de0f6ecSBarry Smith   } else {
2119de0f6ecSBarry Smith     head->stack.currentsize = 0;
21276386721SLisandro Dalcin   }
213e5c89e4eSSatish Balay #endif
214e5c89e4eSSatish Balay 
215e5c89e4eSSatish Balay   /*
216e5c89e4eSSatish Balay          Allow logging of all mallocs made
217e5c89e4eSSatish Balay   */
218574034a9SJed Brown   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
219e5c89e4eSSatish Balay     if (!PetscLogMalloc) {
220e5c89e4eSSatish Balay       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
221e32f2f54SBarry Smith       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
222a297a907SKarl Rupp 
223a2ea699eSBarry Smith       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
224e32f2f54SBarry Smith       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
225a297a907SKarl Rupp 
226a2ea699eSBarry Smith       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
227e32f2f54SBarry Smith       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
228e5c89e4eSSatish Balay     }
229e5c89e4eSSatish Balay     PetscLogMallocLength[PetscLogMalloc]     = nsize;
230e5c89e4eSSatish Balay     PetscLogMallocFile[PetscLogMalloc]       = filename;
231e5c89e4eSSatish Balay     PetscLogMallocFunction[PetscLogMalloc++] = function;
232e5c89e4eSSatish Balay   }
233e5c89e4eSSatish Balay   *result = (void*)inew;
234e5c89e4eSSatish Balay   PetscFunctionReturn(0);
235e5c89e4eSSatish Balay }
236e5c89e4eSSatish Balay 
237e5c89e4eSSatish Balay 
238e5c89e4eSSatish Balay /*
239e5c89e4eSSatish Balay    PetscTrFreeDefault - Free with tracing.
240e5c89e4eSSatish Balay 
241e5c89e4eSSatish Balay    Input Parameters:
242e5c89e4eSSatish Balay .   a    - pointer to a block allocated with PetscTrMalloc
243e5c89e4eSSatish Balay .   lineno - line number where used.  Use __LINE__ for this
244e5c89e4eSSatish Balay .   file  - file name where used.  Use __FILE__ for this
245e5c89e4eSSatish Balay  */
246efca3c55SSatish Balay PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[])
247e5c89e4eSSatish Balay {
248e5c89e4eSSatish Balay   char           *a = (char*)aa;
249e5c89e4eSSatish Balay   TRSPACE        *head;
250e5c89e4eSSatish Balay   char           *ahead;
251e5c89e4eSSatish Balay   PetscErrorCode ierr;
2520700a824SBarry Smith   PetscClassId   *nend;
253e5c89e4eSSatish Balay 
254e5c89e4eSSatish Balay   PetscFunctionBegin;
255e5c89e4eSSatish Balay   /* Do not try to handle empty blocks */
25649d7da52SJed Brown   if (!a) PetscFunctionReturn(0);
257e5c89e4eSSatish Balay 
258e5c89e4eSSatish Balay   if (TRdebugLevel) {
259efca3c55SSatish Balay     ierr = PetscMallocValidate(line,function,file);CHKERRQ(ierr);
260e5c89e4eSSatish Balay   }
261e5c89e4eSSatish Balay 
262e5c89e4eSSatish Balay   ahead = a;
263e5c89e4eSSatish Balay   a     = a - sizeof(TrSPACE);
264e5c89e4eSSatish Balay   head  = (TRSPACE*)a;
265e5c89e4eSSatish Balay 
2660700a824SBarry Smith   if (head->classid != CLASSID_VALUE) {
267efca3c55SSatish Balay     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
268e5c89e4eSSatish Balay     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
269e32f2f54SBarry Smith     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
270e5c89e4eSSatish Balay   }
2710700a824SBarry Smith   nend = (PetscClassId*)(ahead + head->size);
2720700a824SBarry Smith   if (*nend != CLASSID_VALUE) {
273e5c89e4eSSatish Balay     if (*nend == ALREADY_FREED) {
274efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
275e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
276e5c89e4eSSatish Balay       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
277efca3c55SSatish Balay         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
278e5c89e4eSSatish Balay       } else {
279efca3c55SSatish Balay         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
280e5c89e4eSSatish Balay       }
281e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
282e5c89e4eSSatish Balay     } else {
283e5c89e4eSSatish Balay       /* Damaged tail */
284efca3c55SSatish Balay       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s\n",function,line,file);
285e5c89e4eSSatish Balay       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
286efca3c55SSatish Balay       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
287e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
288e5c89e4eSSatish Balay     }
289e5c89e4eSSatish Balay   }
290e5c89e4eSSatish Balay   /* Mark the location freed */
291e5c89e4eSSatish Balay   *nend = ALREADY_FREED;
292e5c89e4eSSatish Balay   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
293e5c89e4eSSatish Balay   if (line > 0 && line < 50000) {
294e5c89e4eSSatish Balay     head->lineno       = line;
295e5c89e4eSSatish Balay     head->filename     = file;
296e5c89e4eSSatish Balay     head->functionname = function;
297e5c89e4eSSatish Balay   } else {
298e5c89e4eSSatish Balay     head->lineno = -head->lineno;
299e5c89e4eSSatish Balay   }
300e5c89e4eSSatish Balay   /* zero out memory - helps to find some reuse of already freed memory */
301e5c89e4eSSatish Balay   ierr = PetscMemzero(aa,head->size);CHKERRQ(ierr);
302e5c89e4eSSatish Balay 
303e5c89e4eSSatish Balay   TRallocated -= head->size;
304e5c89e4eSSatish Balay   TRfrags--;
305e5c89e4eSSatish Balay   if (head->prev) head->prev->next = head->next;
306e5c89e4eSSatish Balay   else TRhead = head->next;
307e5c89e4eSSatish Balay 
308e5c89e4eSSatish Balay   if (head->next) head->next->prev = head->prev;
309efca3c55SSatish Balay   ierr = PetscFreeAlign(a,line,function,file);CHKERRQ(ierr);
310e5c89e4eSSatish Balay   PetscFunctionReturn(0);
311e5c89e4eSSatish Balay }
312e5c89e4eSSatish Balay 
313e5c89e4eSSatish Balay 
3143221ece2SMatthew G. Knepley 
3153221ece2SMatthew G. Knepley /*
3163221ece2SMatthew G. Knepley   PetscTrReallocDefault - Realloc with tracing.
3173221ece2SMatthew G. Knepley 
3183221ece2SMatthew G. Knepley   Input Parameters:
3193221ece2SMatthew G. Knepley + len      - number of bytes to allocate
3203221ece2SMatthew G. Knepley . lineno   - line number where used.  Use __LINE__ for this
3213221ece2SMatthew G. Knepley . filename - file name where used.  Use __FILE__ for this
3223221ece2SMatthew G. Knepley - result   - double aligned pointer to initial storage.
3233221ece2SMatthew G. Knepley 
3243221ece2SMatthew G. Knepley   Output Parameter:
3253221ece2SMatthew G. Knepley . result - double aligned pointer to requested storage, or null if not available.
3263221ece2SMatthew G. Knepley 
3273221ece2SMatthew G. Knepley   Level: developer
3283221ece2SMatthew G. Knepley 
3293221ece2SMatthew G. Knepley .seealso: PetscTrMallocDefault(), PetscTrFreeDefault()
3303221ece2SMatthew G. Knepley */
3313221ece2SMatthew G. Knepley PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result)
3323221ece2SMatthew G. Knepley {
3333221ece2SMatthew G. Knepley   char           *a = (char *) *result;
3343221ece2SMatthew G. Knepley   TRSPACE        *head;
3353221ece2SMatthew G. Knepley   char           *ahead, *inew;
3363221ece2SMatthew G. Knepley   PetscClassId   *nend;
3373221ece2SMatthew G. Knepley   size_t         nsize;
3383221ece2SMatthew G. Knepley   PetscErrorCode ierr;
3393221ece2SMatthew G. Knepley 
3403221ece2SMatthew G. Knepley   PetscFunctionBegin;
341c22f1541SToby Isaac   /* Realloc to zero = free */
342c22f1541SToby Isaac   if (!len) {
343c22f1541SToby Isaac     ierr = PetscTrFreeDefault(*result,lineno,function,filename);CHKERRQ(ierr);
344c22f1541SToby Isaac     *result = NULL;
345c22f1541SToby Isaac     PetscFunctionReturn(0);
346c22f1541SToby Isaac   }
347*f590eff4SLisandro Dalcin   /* Realloc with NULL = malloc */
348*f590eff4SLisandro Dalcin   if (!*result) {
349*f590eff4SLisandro Dalcin     ierr = PetscTrMallocDefault(len,lineno,function,filename,result);CHKERRQ(ierr);
350*f590eff4SLisandro Dalcin     PetscFunctionReturn(0);
351*f590eff4SLisandro Dalcin   }
3523221ece2SMatthew G. Knepley 
3533221ece2SMatthew G. Knepley   if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);}
3543221ece2SMatthew G. Knepley 
3553221ece2SMatthew G. Knepley   ahead = a;
3563221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3573221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3583221ece2SMatthew G. Knepley   inew  = a;
3593221ece2SMatthew G. Knepley 
3603221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3613221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3623221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3633221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3643221ece2SMatthew G. Knepley   }
3653221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3663221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3673221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3683221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3693221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3703221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3713221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3723221ece2SMatthew G. Knepley       } else {
3733221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
3743221ece2SMatthew G. Knepley       }
3753221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3763221ece2SMatthew G. Knepley     } else {
3773221ece2SMatthew G. Knepley       /* Damaged tail */
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 is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
3803221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3813221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
3823221ece2SMatthew G. Knepley     }
3833221ece2SMatthew G. Knepley   }
3843221ece2SMatthew G. Knepley 
3853221ece2SMatthew G. Knepley   TRallocated -= head->size;
3863221ece2SMatthew G. Knepley   TRfrags--;
3873221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
3883221ece2SMatthew G. Knepley   else TRhead = head->next;
3893221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
3903221ece2SMatthew G. Knepley 
3913221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
3923221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
3933221ece2SMatthew G. Knepley 
3943221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
3953221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
3963221ece2SMatthew G. Knepley 
3973221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
3983221ece2SMatthew G. Knepley   head->next   = TRhead;
3993221ece2SMatthew G. Knepley   TRhead       = head;
4003221ece2SMatthew G. Knepley   head->prev   = NULL;
4013221ece2SMatthew G. Knepley   head->size   = nsize;
4023221ece2SMatthew G. Knepley   head->id     = TRid;
4033221ece2SMatthew G. Knepley   head->lineno = lineno;
4043221ece2SMatthew G. Knepley 
4053221ece2SMatthew G. Knepley   head->filename                 = filename;
4063221ece2SMatthew G. Knepley   head->functionname             = function;
4073221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4083221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4093221ece2SMatthew G. Knepley 
4103221ece2SMatthew G. Knepley   TRallocated += nsize;
4113221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
4123221ece2SMatthew G. Knepley   TRfrags++;
4133221ece2SMatthew G. Knepley 
4143221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4153221ece2SMatthew G. Knepley   if (PetscStackActive()) {
4163221ece2SMatthew G. Knepley     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
4173221ece2SMatthew G. Knepley     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4183221ece2SMatthew G. Knepley     head->stack.line[head->stack.currentsize-2] = lineno;
4193221ece2SMatthew G. Knepley   } else {
4203221ece2SMatthew G. Knepley     head->stack.currentsize = 0;
4213221ece2SMatthew G. Knepley   }
4223221ece2SMatthew G. Knepley #endif
4233221ece2SMatthew G. Knepley 
4243221ece2SMatthew G. Knepley   /*
4253221ece2SMatthew G. Knepley          Allow logging of all mallocs made
4263221ece2SMatthew G. Knepley   */
4273221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4283221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4293221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
4303221ece2SMatthew G. Knepley       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4313221ece2SMatthew G. Knepley 
4323221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4333221ece2SMatthew G. Knepley       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4343221ece2SMatthew G. Knepley 
4353221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4363221ece2SMatthew G. Knepley       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4373221ece2SMatthew G. Knepley     }
4383221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4393221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4403221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4413221ece2SMatthew G. Knepley   }
4423221ece2SMatthew G. Knepley   *result = (void*)inew;
4433221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4443221ece2SMatthew G. Knepley }
4453221ece2SMatthew G. Knepley 
4463221ece2SMatthew G. Knepley 
447fe7fb379SMatthew Knepley /*@C
4480841954dSBarry Smith     PetscMemoryView - Shows the amount of memory currently being used
449e5c89e4eSSatish Balay         in a communicator.
450e5c89e4eSSatish Balay 
451e5c89e4eSSatish Balay     Collective on PetscViewer
452e5c89e4eSSatish Balay 
453e5c89e4eSSatish Balay     Input Parameter:
454e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
455e5c89e4eSSatish Balay -    message - string printed before values
456e5c89e4eSSatish Balay 
4570841954dSBarry Smith     Options Database:
4580841954dSBarry Smith +    -malloc - have PETSc track how much memory it has allocated
4590841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4600841954dSBarry Smith 
461e5c89e4eSSatish Balay     Level: intermediate
462e5c89e4eSSatish Balay 
463e5c89e4eSSatish Balay     Concepts: memory usage
464e5c89e4eSSatish Balay 
4650841954dSBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage()
466e5c89e4eSSatish Balay  @*/
4670841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
468e5c89e4eSSatish Balay {
4690841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4700841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
471e5c89e4eSSatish Balay   PetscErrorCode ierr;
472e5c89e4eSSatish Balay   MPI_Comm       comm;
473e5c89e4eSSatish Balay 
474e5c89e4eSSatish Balay   PetscFunctionBegin;
475e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
476e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
4770841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
478e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
479e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
480e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
481e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
482e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
483e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4840841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4850841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4860841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4870841954dSBarry 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);
4880841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4890841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4900841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4910841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
4920841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4930841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4940841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4950841954dSBarry 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);
4960841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4970841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4980841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4990841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
500e5c89e4eSSatish Balay   } else if (resident && residentmax) {
5010841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5020841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5030841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5040841954dSBarry 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);
5050841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5060841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5070841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5080841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
509e5c89e4eSSatish Balay   } else if (resident && allocated) {
5100841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5110841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5120841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5130841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
5140841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5150841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5160841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5170841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5180841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
519e5c89e4eSSatish Balay   } else if (allocated) {
5200841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5210841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5220841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5230841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5240841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5250841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
526e5c89e4eSSatish Balay   } else {
527e5c89e4eSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
528e5c89e4eSSatish Balay   }
529e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
530e5c89e4eSSatish Balay   PetscFunctionReturn(0);
531e5c89e4eSSatish Balay }
532e5c89e4eSSatish Balay 
53346eb3923SBarry Smith /*@
534e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
535e5c89e4eSSatish Balay 
536e5c89e4eSSatish Balay     Not Collective
537e5c89e4eSSatish Balay 
538e5c89e4eSSatish Balay     Output Parameters:
539e5c89e4eSSatish Balay .   space - number of bytes currently allocated
540e5c89e4eSSatish Balay 
541e5c89e4eSSatish Balay     Level: intermediate
542e5c89e4eSSatish Balay 
543e5c89e4eSSatish Balay     Concepts: memory usage
544e5c89e4eSSatish Balay 
545e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
546e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
547e5c89e4eSSatish Balay  @*/
5487087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
549e5c89e4eSSatish Balay {
550e5c89e4eSSatish Balay   PetscFunctionBegin;
551e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
552e5c89e4eSSatish Balay   PetscFunctionReturn(0);
553e5c89e4eSSatish Balay }
554e5c89e4eSSatish Balay 
555dc37d89fSBarry Smith /*@
556e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
557e5c89e4eSSatish Balay         during this run.
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay     Not Collective
560e5c89e4eSSatish Balay 
561e5c89e4eSSatish Balay     Output Parameters:
562e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
563e5c89e4eSSatish Balay 
564e5c89e4eSSatish Balay     Level: intermediate
565e5c89e4eSSatish Balay 
566e5c89e4eSSatish Balay     Concepts: memory usage
567e5c89e4eSSatish Balay 
568e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
569e5c89e4eSSatish Balay           PetscMemoryGetCurrentUsage()
570e5c89e4eSSatish Balay  @*/
5717087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
572e5c89e4eSSatish Balay {
573e5c89e4eSSatish Balay   PetscFunctionBegin;
574e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
575e5c89e4eSSatish Balay   PetscFunctionReturn(0);
576e5c89e4eSSatish Balay }
577e5c89e4eSSatish Balay 
578a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
579a64a8e02SBarry Smith /*@C
580a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
581a64a8e02SBarry Smith 
582a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
583a64a8e02SBarry Smith 
584a64a8e02SBarry Smith    Input Parameter:
585a64a8e02SBarry Smith .    ptr - the memory location
586a64a8e02SBarry Smith 
587a64a8e02SBarry Smith    Output Paramter:
588a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
589a64a8e02SBarry Smith 
590a64a8e02SBarry Smith    Level: intermediate
591a64a8e02SBarry Smith 
592a64a8e02SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
593a64a8e02SBarry Smith @*/
594a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
595a64a8e02SBarry Smith {
596a64a8e02SBarry Smith   TRSPACE *head;
597a64a8e02SBarry Smith 
598a64a8e02SBarry Smith   PetscFunctionBegin;
599a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
600a64a8e02SBarry Smith   *stack = &head->stack;
601a64a8e02SBarry Smith   PetscFunctionReturn(0);
602a64a8e02SBarry Smith }
60376386721SLisandro Dalcin #else
60476386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
60576386721SLisandro Dalcin {
60676386721SLisandro Dalcin   PetscFunctionBegin;
607f0ba7cfcSLisandro Dalcin   *stack = NULL;
60876386721SLisandro Dalcin   PetscFunctionReturn(0);
60976386721SLisandro Dalcin }
610a64a8e02SBarry Smith #endif
611a64a8e02SBarry Smith 
612e5c89e4eSSatish Balay /*@C
613e5c89e4eSSatish Balay    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
614e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
615e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
616e5c89e4eSSatish Balay    allocated.
617e5c89e4eSSatish Balay 
618e5c89e4eSSatish Balay    Collective on PETSC_COMM_WORLD
619e5c89e4eSSatish Balay 
620e5c89e4eSSatish Balay    Input Parameter:
621e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
622e5c89e4eSSatish Balay 
623e5c89e4eSSatish Balay    Options Database Key:
624e5c89e4eSSatish Balay .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
625e5c89e4eSSatish Balay 
626e5c89e4eSSatish Balay    Level: intermediate
627e5c89e4eSSatish Balay 
628e5c89e4eSSatish Balay    Fortran Note:
629e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
630e5c89e4eSSatish Balay    The fp defaults to stdout.
631e5c89e4eSSatish Balay 
63295452b02SPatrick Sanan    Notes:
63395452b02SPatrick Sanan     uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
634e5c89e4eSSatish Balay           has been freed.
635e5c89e4eSSatish Balay 
636e5c89e4eSSatish Balay    Concepts: memory usage
637e5c89e4eSSatish Balay    Concepts: memory bleeding
638e5c89e4eSSatish Balay    Concepts: bleeding memory
639e5c89e4eSSatish Balay 
6409e9a1f8fSvictor .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
641e5c89e4eSSatish Balay @*/
6427087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
643e5c89e4eSSatish Balay {
644e5c89e4eSSatish Balay   TRSPACE        *head;
6455486ca60SMatthew G. Knepley   PetscInt       libAlloc = 0;
646e5c89e4eSSatish Balay   PetscErrorCode ierr;
647e5c89e4eSSatish Balay   PetscMPIInt    rank;
648e5c89e4eSSatish Balay 
649e5c89e4eSSatish Balay   PetscFunctionBegin;
650e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
651da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
652e5c89e4eSSatish Balay   head = TRhead;
653e5c89e4eSSatish Balay   while (head) {
6545486ca60SMatthew G. Knepley     PetscBool isLib;
6555486ca60SMatthew G. Knepley 
6565486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
6575486ca60SMatthew G. Knepley     libAlloc += head->size;
6585486ca60SMatthew G. Knepley     head = head->next;
6595486ca60SMatthew G. Knepley   }
6605486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
6615486ca60SMatthew G. Knepley   head = TRhead;
6625486ca60SMatthew G. Knepley   while (head) {
6635486ca60SMatthew G. Knepley     PetscBool isLib;
6645486ca60SMatthew G. Knepley 
6655486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
6665486ca60SMatthew G. Knepley     if (!isLib) {
667efca3c55SSatish Balay       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
6688bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
669e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
670e5c89e4eSSatish Balay #endif
6715486ca60SMatthew G. Knepley     }
672e5c89e4eSSatish Balay     head = head->next;
673e5c89e4eSSatish Balay   }
674e5c89e4eSSatish Balay   PetscFunctionReturn(0);
675e5c89e4eSSatish Balay }
676e5c89e4eSSatish Balay 
677e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
678e5c89e4eSSatish Balay 
679dc37d89fSBarry Smith /*@
680e5c89e4eSSatish Balay     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
681e5c89e4eSSatish Balay 
682e5c89e4eSSatish Balay     Not Collective
683e5c89e4eSSatish Balay 
684e5c89e4eSSatish Balay     Options Database Key:
685574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
686574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
687e5c89e4eSSatish Balay 
688e5c89e4eSSatish Balay     Level: advanced
689e5c89e4eSSatish Balay 
690574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
691e5c89e4eSSatish Balay @*/
6927087cfbeSBarry Smith PetscErrorCode PetscMallocSetDumpLog(void)
693e5c89e4eSSatish Balay {
69421b680ceSJed Brown   PetscErrorCode ierr;
69521b680ceSJed Brown 
696e5c89e4eSSatish Balay   PetscFunctionBegin;
697e5c89e4eSSatish Balay   PetscLogMalloc = 0;
698a297a907SKarl Rupp 
69921b680ceSJed Brown   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
700e5c89e4eSSatish Balay   PetscFunctionReturn(0);
701e5c89e4eSSatish Balay }
702e5c89e4eSSatish Balay 
703dc37d89fSBarry Smith /*@
704574034a9SJed Brown     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
705574034a9SJed Brown 
706574034a9SJed Brown     Not Collective
707574034a9SJed Brown 
708574034a9SJed Brown     Input Arguments:
709574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
710574034a9SJed Brown 
711574034a9SJed Brown     Options Database Key:
712574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
713574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
714574034a9SJed Brown 
715574034a9SJed Brown     Level: advanced
716574034a9SJed Brown 
717574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
718574034a9SJed Brown @*/
719574034a9SJed Brown PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
720574034a9SJed Brown {
721574034a9SJed Brown   PetscErrorCode ierr;
722574034a9SJed Brown 
723574034a9SJed Brown   PetscFunctionBegin;
724574034a9SJed Brown   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
725574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
726574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
727574034a9SJed Brown   PetscFunctionReturn(0);
728574034a9SJed Brown }
729574034a9SJed Brown 
730dc37d89fSBarry Smith /*@
73118a2528dSJed Brown     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
73218a2528dSJed Brown 
73318a2528dSJed Brown     Not Collective
73418a2528dSJed Brown 
73518a2528dSJed Brown     Output Arguments
73618a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
73718a2528dSJed Brown 
73818a2528dSJed Brown     Options Database Key:
73918a2528dSJed Brown .  -malloc_log - Activates PetscMallocDumpLog()
74018a2528dSJed Brown 
74118a2528dSJed Brown     Level: advanced
74218a2528dSJed Brown 
74318a2528dSJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog()
74418a2528dSJed Brown @*/
74518a2528dSJed Brown PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
74618a2528dSJed Brown {
74718a2528dSJed Brown 
74818a2528dSJed Brown   PetscFunctionBegin;
74918a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
75018a2528dSJed Brown   PetscFunctionReturn(0);
75118a2528dSJed Brown }
75218a2528dSJed Brown 
753e5c89e4eSSatish Balay /*@C
754e5c89e4eSSatish Balay     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
75521b680ceSJed Brown        PetscMemoryGetMaximumUsage()
756e5c89e4eSSatish Balay 
757e5c89e4eSSatish Balay     Collective on PETSC_COMM_WORLD
758e5c89e4eSSatish Balay 
759e5c89e4eSSatish Balay     Input Parameter:
7600298fd71SBarry Smith .   fp - file pointer; or NULL
761e5c89e4eSSatish Balay 
762e5c89e4eSSatish Balay     Options Database Key:
763e5c89e4eSSatish Balay .  -malloc_log - Activates PetscMallocDumpLog()
764e5c89e4eSSatish Balay 
765e5c89e4eSSatish Balay     Level: advanced
766e5c89e4eSSatish Balay 
767e5c89e4eSSatish Balay    Fortran Note:
768e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
769e5c89e4eSSatish Balay    The fp defaults to stdout.
770e5c89e4eSSatish Balay 
771e5c89e4eSSatish Balay .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
772e5c89e4eSSatish Balay @*/
7737087cfbeSBarry Smith PetscErrorCode  PetscMallocDumpLog(FILE *fp)
774e5c89e4eSSatish Balay {
775e5c89e4eSSatish Balay   PetscInt       i,j,n,dummy,*perm;
776e5c89e4eSSatish Balay   size_t         *shortlength;
777f56c2debSBarry Smith   int            *shortcount,err;
778e5c89e4eSSatish Balay   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
779ace3abfcSBarry Smith   PetscBool      match;
780e5c89e4eSSatish Balay   const char     **shortfunction;
781e5c89e4eSSatish Balay   PetscLogDouble rss;
782e5c89e4eSSatish Balay   MPI_Status     status;
783e5c89e4eSSatish Balay   PetscErrorCode ierr;
784e5c89e4eSSatish Balay 
785e5c89e4eSSatish Balay   PetscFunctionBegin;
786e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
787e5c89e4eSSatish Balay   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
788e5c89e4eSSatish Balay   /*
789e5c89e4eSSatish Balay        Try to get the data printed in order by processor. This will only sometimes work
790e5c89e4eSSatish Balay   */
791f56c2debSBarry Smith   err = fflush(fp);
792e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
793f56c2debSBarry Smith 
794e5c89e4eSSatish Balay   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
795e5c89e4eSSatish Balay   if (rank) {
796e5c89e4eSSatish Balay     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
797e5c89e4eSSatish Balay   }
798e5c89e4eSSatish Balay 
799768aa557SSatish 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()");
800768aa557SSatish Balay 
801da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
802f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
803e5c89e4eSSatish Balay   if (rss) {
804f3d65365SJed 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);
805e5c89e4eSSatish Balay   } else {
806e5c89e4eSSatish 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);
807e5c89e4eSSatish Balay   }
808e32f2f54SBarry Smith   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
809e32f2f54SBarry Smith   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
810e32f2f54SBarry Smith   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
81197b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
812e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
813e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
814e5c89e4eSSatish Balay       if (match) {
815e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
81659ffdab8SBarry Smith         shortcount[j]++;
817e5c89e4eSSatish Balay         goto foundit;
818e5c89e4eSSatish Balay       }
819e5c89e4eSSatish Balay     }
820e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
821e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
82259ffdab8SBarry Smith     shortcount[n]    = 1;
823e5c89e4eSSatish Balay     n++;
824e5c89e4eSSatish Balay foundit:;
825e5c89e4eSSatish Balay   }
826e5c89e4eSSatish Balay 
827e32f2f54SBarry Smith   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
828e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
829e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
830e5c89e4eSSatish Balay 
831e5c89e4eSSatish Balay   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
832e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
83359ffdab8SBarry 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);
834e5c89e4eSSatish Balay   }
835e5c89e4eSSatish Balay   free(perm);
836e5c89e4eSSatish Balay   free(shortlength);
83759ffdab8SBarry Smith   free(shortcount);
838e5c89e4eSSatish Balay   free((char**)shortfunction);
839f56c2debSBarry Smith   err = fflush(fp);
840e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
841e5c89e4eSSatish Balay   if (rank != size-1) {
842e5c89e4eSSatish Balay     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
843e5c89e4eSSatish Balay   }
844e5c89e4eSSatish Balay   PetscFunctionReturn(0);
845e5c89e4eSSatish Balay }
846e5c89e4eSSatish Balay 
847e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
848e5c89e4eSSatish Balay 
849dc37d89fSBarry Smith /*@
850e5c89e4eSSatish Balay     PetscMallocDebug - Turns on/off debugging for the memory management routines.
851e5c89e4eSSatish Balay 
852e5c89e4eSSatish Balay     Not Collective
853e5c89e4eSSatish Balay 
854e5c89e4eSSatish Balay     Input Parameter:
855e5c89e4eSSatish Balay .   level - PETSC_TRUE or PETSC_FALSE
856e5c89e4eSSatish Balay 
857e5c89e4eSSatish Balay    Level: intermediate
858e5c89e4eSSatish Balay 
859e5c89e4eSSatish Balay .seealso: CHKMEMQ(), PetscMallocValidate()
860e5c89e4eSSatish Balay @*/
8617087cfbeSBarry Smith PetscErrorCode  PetscMallocDebug(PetscBool level)
862e5c89e4eSSatish Balay {
863e5c89e4eSSatish Balay   PetscFunctionBegin;
864e5c89e4eSSatish Balay   TRdebugLevel = level;
865e5c89e4eSSatish Balay   PetscFunctionReturn(0);
866e5c89e4eSSatish Balay }
8670acecf5bSBarry Smith 
868dc37d89fSBarry Smith /*@
8690acecf5bSBarry Smith     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
8700acecf5bSBarry Smith 
8710acecf5bSBarry Smith     Not Collective
8720acecf5bSBarry Smith 
8730acecf5bSBarry Smith     Output Parameter:
8740acecf5bSBarry Smith .    flg - PETSC_TRUE if any debugger
8750acecf5bSBarry Smith 
8760acecf5bSBarry Smith    Level: intermediate
8770acecf5bSBarry Smith 
8780acecf5bSBarry Smith     Note that by default, the debug version always does some debugging unless you run with -malloc no
8790acecf5bSBarry Smith 
8800acecf5bSBarry Smith 
8810acecf5bSBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate()
8820acecf5bSBarry Smith @*/
8830acecf5bSBarry Smith PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
8840acecf5bSBarry Smith {
8850acecf5bSBarry Smith   PetscFunctionBegin;
8860acecf5bSBarry Smith   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
8870acecf5bSBarry Smith   else *flg = PETSC_FALSE;
8880acecf5bSBarry Smith   PetscFunctionReturn(0);
8890acecf5bSBarry Smith }
890