xref: /petsc/src/sys/memory/mtr.c (revision 95c0884e6f7665b705eebf88174e89dc920c2fc0)
17d0a6c19SBarry Smith 
2e5c89e4eSSatish Balay /*
3e5c89e4eSSatish Balay      Interface to malloc() and free(). This code allows for
4e5c89e4eSSatish Balay   logging of memory usage and some error checking
5e5c89e4eSSatish Balay */
6c6db04a5SJed Brown #include <petscsys.h>           /*I "petscsys.h" I*/
7665c2dedSJed Brown #include <petscviewer.h>
8e5c89e4eSSatish Balay #if defined(PETSC_HAVE_MALLOC_H)
9e5c89e4eSSatish Balay #include <malloc.h>
10e5c89e4eSSatish Balay #endif
11e5c89e4eSSatish Balay 
12e5c89e4eSSatish Balay 
13e5c89e4eSSatish Balay /*
14e5c89e4eSSatish Balay      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
15e5c89e4eSSatish Balay */
16*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t,int,const char[],const char[],void**);
17*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscFreeAlign(void*,int,const char[],const char[]);
18*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t,int,const char[],const char[],void**);
19*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrMallocDefault(size_t,int,const char[],const char[],void**);
20*95c0884eSLisandro Dalcin PETSC_EXTERN PetscErrorCode PetscTrFreeDefault(void*,int,const char[],const char[]);
21*95c0884eSLisandro 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 
71*95c0884eSLisandro 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   }
3473221ece2SMatthew G. Knepley 
3483221ece2SMatthew G. Knepley   if (TRdebugLevel) {ierr = PetscMallocValidate(lineno,function,filename); if (ierr) PetscFunctionReturn(ierr);}
3493221ece2SMatthew G. Knepley 
3503221ece2SMatthew G. Knepley   ahead = a;
3513221ece2SMatthew G. Knepley   a     = a - sizeof(TrSPACE);
3523221ece2SMatthew G. Knepley   head  = (TRSPACE *) a;
3533221ece2SMatthew G. Knepley   inew  = a;
3543221ece2SMatthew G. Knepley 
3553221ece2SMatthew G. Knepley   if (head->classid != CLASSID_VALUE) {
3563221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3573221ece2SMatthew G. Knepley     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
3583221ece2SMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
3593221ece2SMatthew G. Knepley   }
3603221ece2SMatthew G. Knepley   nend = (PetscClassId *)(ahead + head->size);
3613221ece2SMatthew G. Knepley   if (*nend != CLASSID_VALUE) {
3623221ece2SMatthew G. Knepley     if (*nend == ALREADY_FREED) {
3633221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3643221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
3653221ece2SMatthew G. Knepley       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
3663221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block freed in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3673221ece2SMatthew G. Knepley       } else {
3683221ece2SMatthew G. Knepley         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,-head->lineno,head->filename);
3693221ece2SMatthew G. Knepley       }
3703221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
3713221ece2SMatthew G. Knepley     } else {
3723221ece2SMatthew G. Knepley       /* Damaged tail */
3733221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() line %d in %s\n",function,lineno,filename);
3743221ece2SMatthew 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);
3753221ece2SMatthew G. Knepley       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s\n",head->functionname,head->lineno,head->filename);
3763221ece2SMatthew G. Knepley       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
3773221ece2SMatthew G. Knepley     }
3783221ece2SMatthew G. Knepley   }
3793221ece2SMatthew G. Knepley 
3803221ece2SMatthew G. Knepley   TRallocated -= head->size;
3813221ece2SMatthew G. Knepley   TRfrags--;
3823221ece2SMatthew G. Knepley   if (head->prev) head->prev->next = head->next;
3833221ece2SMatthew G. Knepley   else TRhead = head->next;
3843221ece2SMatthew G. Knepley   if (head->next) head->next->prev = head->prev;
3853221ece2SMatthew G. Knepley 
3863221ece2SMatthew G. Knepley   nsize = (len + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
3873221ece2SMatthew G. Knepley   ierr  = PetscReallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,(void**)&inew);CHKERRQ(ierr);
3883221ece2SMatthew G. Knepley 
3893221ece2SMatthew G. Knepley   head  = (TRSPACE*)inew;
3903221ece2SMatthew G. Knepley   inew += sizeof(TrSPACE);
3913221ece2SMatthew G. Knepley 
3923221ece2SMatthew G. Knepley   if (TRhead) TRhead->prev = head;
3933221ece2SMatthew G. Knepley   head->next   = TRhead;
3943221ece2SMatthew G. Knepley   TRhead       = head;
3953221ece2SMatthew G. Knepley   head->prev   = NULL;
3963221ece2SMatthew G. Knepley   head->size   = nsize;
3973221ece2SMatthew G. Knepley   head->id     = TRid;
3983221ece2SMatthew G. Knepley   head->lineno = lineno;
3993221ece2SMatthew G. Knepley 
4003221ece2SMatthew G. Knepley   head->filename                 = filename;
4013221ece2SMatthew G. Knepley   head->functionname             = function;
4023221ece2SMatthew G. Knepley   head->classid                  = CLASSID_VALUE;
4033221ece2SMatthew G. Knepley   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;
4043221ece2SMatthew G. Knepley 
4053221ece2SMatthew G. Knepley   TRallocated += nsize;
4063221ece2SMatthew G. Knepley   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
4073221ece2SMatthew G. Knepley   TRfrags++;
4083221ece2SMatthew G. Knepley 
4093221ece2SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
4103221ece2SMatthew G. Knepley   if (PetscStackActive()) {
4113221ece2SMatthew G. Knepley     ierr = PetscStackCopy(petscstack,&head->stack);CHKERRQ(ierr);
4123221ece2SMatthew G. Knepley     /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */
4133221ece2SMatthew G. Knepley     head->stack.line[head->stack.currentsize-2] = lineno;
4143221ece2SMatthew G. Knepley   } else {
4153221ece2SMatthew G. Knepley     head->stack.currentsize = 0;
4163221ece2SMatthew G. Knepley   }
4173221ece2SMatthew G. Knepley #endif
4183221ece2SMatthew G. Knepley 
4193221ece2SMatthew G. Knepley   /*
4203221ece2SMatthew G. Knepley          Allow logging of all mallocs made
4213221ece2SMatthew G. Knepley   */
4223221ece2SMatthew G. Knepley   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) {
4233221ece2SMatthew G. Knepley     if (!PetscLogMalloc) {
4243221ece2SMatthew G. Knepley       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
4253221ece2SMatthew G. Knepley       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4263221ece2SMatthew G. Knepley 
4273221ece2SMatthew G. Knepley       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4283221ece2SMatthew G. Knepley       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4293221ece2SMatthew G. Knepley 
4303221ece2SMatthew G. Knepley       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
4313221ece2SMatthew G. Knepley       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
4323221ece2SMatthew G. Knepley     }
4333221ece2SMatthew G. Knepley     PetscLogMallocLength[PetscLogMalloc]     = nsize;
4343221ece2SMatthew G. Knepley     PetscLogMallocFile[PetscLogMalloc]       = filename;
4353221ece2SMatthew G. Knepley     PetscLogMallocFunction[PetscLogMalloc++] = function;
4363221ece2SMatthew G. Knepley   }
4373221ece2SMatthew G. Knepley   *result = (void*)inew;
4383221ece2SMatthew G. Knepley   PetscFunctionReturn(0);
4393221ece2SMatthew G. Knepley }
4403221ece2SMatthew G. Knepley 
4413221ece2SMatthew G. Knepley 
442fe7fb379SMatthew Knepley /*@C
4430841954dSBarry Smith     PetscMemoryView - Shows the amount of memory currently being used
444e5c89e4eSSatish Balay         in a communicator.
445e5c89e4eSSatish Balay 
446e5c89e4eSSatish Balay     Collective on PetscViewer
447e5c89e4eSSatish Balay 
448e5c89e4eSSatish Balay     Input Parameter:
449e5c89e4eSSatish Balay +    viewer - the viewer that defines the communicator
450e5c89e4eSSatish Balay -    message - string printed before values
451e5c89e4eSSatish Balay 
4520841954dSBarry Smith     Options Database:
4530841954dSBarry Smith +    -malloc - have PETSc track how much memory it has allocated
4540841954dSBarry Smith -    -memory_view - during PetscFinalize() have this routine called
4550841954dSBarry Smith 
456e5c89e4eSSatish Balay     Level: intermediate
457e5c89e4eSSatish Balay 
458e5c89e4eSSatish Balay     Concepts: memory usage
459e5c89e4eSSatish Balay 
4600841954dSBarry Smith .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage(), PetscMemorySetGetMaximumUsage()
461e5c89e4eSSatish Balay  @*/
4620841954dSBarry Smith PetscErrorCode  PetscMemoryView(PetscViewer viewer,const char message[])
463e5c89e4eSSatish Balay {
4640841954dSBarry Smith   PetscLogDouble allocated,allocatedmax,resident,residentmax,gallocated,gallocatedmax,gresident,gresidentmax,maxgallocated,maxgallocatedmax,maxgresident,maxgresidentmax;
4650841954dSBarry Smith   PetscLogDouble mingallocated,mingallocatedmax,mingresident,mingresidentmax;
466e5c89e4eSSatish Balay   PetscErrorCode ierr;
467e5c89e4eSSatish Balay   MPI_Comm       comm;
468e5c89e4eSSatish Balay 
469e5c89e4eSSatish Balay   PetscFunctionBegin;
470e5c89e4eSSatish Balay   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
471e5c89e4eSSatish Balay   ierr = PetscMallocGetCurrentUsage(&allocated);CHKERRQ(ierr);
4720841954dSBarry Smith   ierr = PetscMallocGetMaximumUsage(&allocatedmax);CHKERRQ(ierr);
473e5c89e4eSSatish Balay   ierr = PetscMemoryGetCurrentUsage(&resident);CHKERRQ(ierr);
474e5c89e4eSSatish Balay   ierr = PetscMemoryGetMaximumUsage(&residentmax);CHKERRQ(ierr);
475e5c89e4eSSatish Balay   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
476e5c89e4eSSatish Balay   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
477e5c89e4eSSatish Balay   ierr = PetscViewerASCIIPrintf(viewer,message);CHKERRQ(ierr);
478e5c89e4eSSatish Balay   if (resident && residentmax && allocated) {
4790841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4800841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4810841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4820841954dSBarry 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);
4830841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4840841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4850841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4860841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
4870841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&gallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4880841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&maxgallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4890841954dSBarry Smith     ierr = MPI_Reduce(&allocatedmax,&mingallocatedmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4900841954dSBarry 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);
4910841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4920841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4930841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4940841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
495e5c89e4eSSatish Balay   } else if (resident && residentmax) {
4960841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&gresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
4970841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&maxgresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
4980841954dSBarry Smith     ierr = MPI_Reduce(&residentmax,&mingresidentmax,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
4990841954dSBarry 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);
5000841954dSBarry Smith     ierr = MPI_Reduce(&resident,&gresident,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5010841954dSBarry Smith     ierr = MPI_Reduce(&resident,&maxgresident,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5020841954dSBarry Smith     ierr = MPI_Reduce(&resident,&mingresident,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5030841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current process memory:                                  total %5.4e max %5.4e min %5.4e\n",gresident,maxgresident,mingresident);CHKERRQ(ierr);
504e5c89e4eSSatish Balay   } else if (resident && allocated) {
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);
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);
5130841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
514e5c89e4eSSatish Balay   } else if (allocated) {
5150841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&gallocated,1,MPIU_PETSCLOGDOUBLE,MPI_SUM,0,comm);CHKERRQ(ierr);
5160841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&maxgallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MAX,0,comm);CHKERRQ(ierr);
5170841954dSBarry Smith     ierr = MPI_Reduce(&allocated,&mingallocated,1,MPIU_PETSCLOGDOUBLE,MPI_MIN,0,comm);CHKERRQ(ierr);
5180841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Current space PetscMalloc()ed:                           total %5.4e max %5.4e min %5.4e\n",gallocated,maxgallocated,mingallocated);CHKERRQ(ierr);
5190841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"Run with -memory_view to get maximum memory usage\n");CHKERRQ(ierr);
5200841954dSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"OS cannot compute process memory\n");CHKERRQ(ierr);
521e5c89e4eSSatish Balay   } else {
522e5c89e4eSSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");CHKERRQ(ierr);
523e5c89e4eSSatish Balay   }
524e5c89e4eSSatish Balay   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
525e5c89e4eSSatish Balay   PetscFunctionReturn(0);
526e5c89e4eSSatish Balay }
527e5c89e4eSSatish Balay 
52846eb3923SBarry Smith /*@
529e5c89e4eSSatish Balay     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed
530e5c89e4eSSatish Balay 
531e5c89e4eSSatish Balay     Not Collective
532e5c89e4eSSatish Balay 
533e5c89e4eSSatish Balay     Output Parameters:
534e5c89e4eSSatish Balay .   space - number of bytes currently allocated
535e5c89e4eSSatish Balay 
536e5c89e4eSSatish Balay     Level: intermediate
537e5c89e4eSSatish Balay 
538e5c89e4eSSatish Balay     Concepts: memory usage
539e5c89e4eSSatish Balay 
540e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
541e5c89e4eSSatish Balay           PetscMemoryGetMaximumUsage()
542e5c89e4eSSatish Balay  @*/
5437087cfbeSBarry Smith PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
544e5c89e4eSSatish Balay {
545e5c89e4eSSatish Balay   PetscFunctionBegin;
546e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRallocated;
547e5c89e4eSSatish Balay   PetscFunctionReturn(0);
548e5c89e4eSSatish Balay }
549e5c89e4eSSatish Balay 
550dc37d89fSBarry Smith /*@
551e5c89e4eSSatish Balay     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
552e5c89e4eSSatish Balay         during this run.
553e5c89e4eSSatish Balay 
554e5c89e4eSSatish Balay     Not Collective
555e5c89e4eSSatish Balay 
556e5c89e4eSSatish Balay     Output Parameters:
557e5c89e4eSSatish Balay .   space - maximum number of bytes ever allocated at one time
558e5c89e4eSSatish Balay 
559e5c89e4eSSatish Balay     Level: intermediate
560e5c89e4eSSatish Balay 
561e5c89e4eSSatish Balay     Concepts: memory usage
562e5c89e4eSSatish Balay 
563e5c89e4eSSatish Balay .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
564e5c89e4eSSatish Balay           PetscMemoryGetCurrentUsage()
565e5c89e4eSSatish Balay  @*/
5667087cfbeSBarry Smith PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
567e5c89e4eSSatish Balay {
568e5c89e4eSSatish Balay   PetscFunctionBegin;
569e5c89e4eSSatish Balay   *space = (PetscLogDouble) TRMaxMem;
570e5c89e4eSSatish Balay   PetscFunctionReturn(0);
571e5c89e4eSSatish Balay }
572e5c89e4eSSatish Balay 
573a64a8e02SBarry Smith #if defined(PETSC_USE_DEBUG)
574a64a8e02SBarry Smith /*@C
575a64a8e02SBarry Smith    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory
576a64a8e02SBarry Smith 
577a64a8e02SBarry Smith    Collective on PETSC_COMM_WORLD
578a64a8e02SBarry Smith 
579a64a8e02SBarry Smith    Input Parameter:
580a64a8e02SBarry Smith .    ptr - the memory location
581a64a8e02SBarry Smith 
582a64a8e02SBarry Smith    Output Paramter:
583a64a8e02SBarry Smith .    stack - the stack indicating where the program allocated this memory
584a64a8e02SBarry Smith 
585a64a8e02SBarry Smith    Level: intermediate
586a64a8e02SBarry Smith 
587a64a8e02SBarry Smith .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
588a64a8e02SBarry Smith @*/
589a64a8e02SBarry Smith PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
590a64a8e02SBarry Smith {
591a64a8e02SBarry Smith   TRSPACE *head;
592a64a8e02SBarry Smith 
593a64a8e02SBarry Smith   PetscFunctionBegin;
594a64a8e02SBarry Smith   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
595a64a8e02SBarry Smith   *stack = &head->stack;
596a64a8e02SBarry Smith   PetscFunctionReturn(0);
597a64a8e02SBarry Smith }
59876386721SLisandro Dalcin #else
59976386721SLisandro Dalcin PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
60076386721SLisandro Dalcin {
60176386721SLisandro Dalcin   PetscFunctionBegin;
602f0ba7cfcSLisandro Dalcin   *stack = NULL;
60376386721SLisandro Dalcin   PetscFunctionReturn(0);
60476386721SLisandro Dalcin }
605a64a8e02SBarry Smith #endif
606a64a8e02SBarry Smith 
607e5c89e4eSSatish Balay /*@C
608e5c89e4eSSatish Balay    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
609e5c89e4eSSatish Balay    printed is: size of space (in bytes), address of space, id of space,
610e5c89e4eSSatish Balay    file in which space was allocated, and line number at which it was
611e5c89e4eSSatish Balay    allocated.
612e5c89e4eSSatish Balay 
613e5c89e4eSSatish Balay    Collective on PETSC_COMM_WORLD
614e5c89e4eSSatish Balay 
615e5c89e4eSSatish Balay    Input Parameter:
616e5c89e4eSSatish Balay .  fp  - file pointer.  If fp is NULL, stdout is assumed.
617e5c89e4eSSatish Balay 
618e5c89e4eSSatish Balay    Options Database Key:
619e5c89e4eSSatish Balay .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()
620e5c89e4eSSatish Balay 
621e5c89e4eSSatish Balay    Level: intermediate
622e5c89e4eSSatish Balay 
623e5c89e4eSSatish Balay    Fortran Note:
624e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDump(integer ierr)
625e5c89e4eSSatish Balay    The fp defaults to stdout.
626e5c89e4eSSatish Balay 
62795452b02SPatrick Sanan    Notes:
62895452b02SPatrick Sanan     uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
629e5c89e4eSSatish Balay           has been freed.
630e5c89e4eSSatish Balay 
631e5c89e4eSSatish Balay    Concepts: memory usage
632e5c89e4eSSatish Balay    Concepts: memory bleeding
633e5c89e4eSSatish Balay    Concepts: bleeding memory
634e5c89e4eSSatish Balay 
6359e9a1f8fSvictor .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
636e5c89e4eSSatish Balay @*/
6377087cfbeSBarry Smith PetscErrorCode  PetscMallocDump(FILE *fp)
638e5c89e4eSSatish Balay {
639e5c89e4eSSatish Balay   TRSPACE        *head;
6405486ca60SMatthew G. Knepley   PetscInt       libAlloc = 0;
641e5c89e4eSSatish Balay   PetscErrorCode ierr;
642e5c89e4eSSatish Balay   PetscMPIInt    rank;
643e5c89e4eSSatish Balay 
644e5c89e4eSSatish Balay   PetscFunctionBegin;
645e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
646da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
647e5c89e4eSSatish Balay   head = TRhead;
648e5c89e4eSSatish Balay   while (head) {
6495486ca60SMatthew G. Knepley     PetscBool isLib;
6505486ca60SMatthew G. Knepley 
6515486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
6525486ca60SMatthew G. Knepley     libAlloc += head->size;
6535486ca60SMatthew G. Knepley     head = head->next;
6545486ca60SMatthew G. Knepley   }
6555486ca60SMatthew G. Knepley   if (TRallocated - libAlloc > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
6565486ca60SMatthew G. Knepley   head = TRhead;
6575486ca60SMatthew G. Knepley   while (head) {
6585486ca60SMatthew G. Knepley     PetscBool isLib;
6595486ca60SMatthew G. Knepley 
6605486ca60SMatthew G. Knepley     ierr = PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib);CHKERRQ(ierr);
6615486ca60SMatthew G. Knepley     if (!isLib) {
662efca3c55SSatish Balay       fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->filename);
6638bf1f09cSShri Abhyankar #if defined(PETSC_USE_DEBUG)
664e5c89e4eSSatish Balay       ierr = PetscStackPrint(&head->stack,fp);CHKERRQ(ierr);
665e5c89e4eSSatish Balay #endif
6665486ca60SMatthew G. Knepley     }
667e5c89e4eSSatish Balay     head = head->next;
668e5c89e4eSSatish Balay   }
669e5c89e4eSSatish Balay   PetscFunctionReturn(0);
670e5c89e4eSSatish Balay }
671e5c89e4eSSatish Balay 
672e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
673e5c89e4eSSatish Balay 
674dc37d89fSBarry Smith /*@
675e5c89e4eSSatish Balay     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().
676e5c89e4eSSatish Balay 
677e5c89e4eSSatish Balay     Not Collective
678e5c89e4eSSatish Balay 
679e5c89e4eSSatish Balay     Options Database Key:
680574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
681574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
682e5c89e4eSSatish Balay 
683e5c89e4eSSatish Balay     Level: advanced
684e5c89e4eSSatish Balay 
685574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
686e5c89e4eSSatish Balay @*/
6877087cfbeSBarry Smith PetscErrorCode PetscMallocSetDumpLog(void)
688e5c89e4eSSatish Balay {
68921b680ceSJed Brown   PetscErrorCode ierr;
69021b680ceSJed Brown 
691e5c89e4eSSatish Balay   PetscFunctionBegin;
692e5c89e4eSSatish Balay   PetscLogMalloc = 0;
693a297a907SKarl Rupp 
69421b680ceSJed Brown   ierr = PetscMemorySetGetMaximumUsage();CHKERRQ(ierr);
695e5c89e4eSSatish Balay   PetscFunctionReturn(0);
696e5c89e4eSSatish Balay }
697e5c89e4eSSatish Balay 
698dc37d89fSBarry Smith /*@
699574034a9SJed Brown     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().
700574034a9SJed Brown 
701574034a9SJed Brown     Not Collective
702574034a9SJed Brown 
703574034a9SJed Brown     Input Arguments:
704574034a9SJed Brown .   logmin - minimum allocation size to log, or PETSC_DEFAULT
705574034a9SJed Brown 
706574034a9SJed Brown     Options Database Key:
707574034a9SJed Brown +  -malloc_log <filename> - Activates PetscMallocDumpLog()
708574034a9SJed Brown -  -malloc_log_threshold <min> - Activates logging and sets a minimum size
709574034a9SJed Brown 
710574034a9SJed Brown     Level: advanced
711574034a9SJed Brown 
712574034a9SJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
713574034a9SJed Brown @*/
714574034a9SJed Brown PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
715574034a9SJed Brown {
716574034a9SJed Brown   PetscErrorCode ierr;
717574034a9SJed Brown 
718574034a9SJed Brown   PetscFunctionBegin;
719574034a9SJed Brown   ierr = PetscMallocSetDumpLog();CHKERRQ(ierr);
720574034a9SJed Brown   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
721574034a9SJed Brown   PetscLogMallocThreshold = (size_t)logmin;
722574034a9SJed Brown   PetscFunctionReturn(0);
723574034a9SJed Brown }
724574034a9SJed Brown 
725dc37d89fSBarry Smith /*@
72618a2528dSJed Brown     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged
72718a2528dSJed Brown 
72818a2528dSJed Brown     Not Collective
72918a2528dSJed Brown 
73018a2528dSJed Brown     Output Arguments
73118a2528dSJed Brown .   logging - PETSC_TRUE if logging is active
73218a2528dSJed Brown 
73318a2528dSJed Brown     Options Database Key:
73418a2528dSJed Brown .  -malloc_log - Activates PetscMallocDumpLog()
73518a2528dSJed Brown 
73618a2528dSJed Brown     Level: advanced
73718a2528dSJed Brown 
73818a2528dSJed Brown .seealso: PetscMallocDump(), PetscMallocDumpLog()
73918a2528dSJed Brown @*/
74018a2528dSJed Brown PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
74118a2528dSJed Brown {
74218a2528dSJed Brown 
74318a2528dSJed Brown   PetscFunctionBegin;
74418a2528dSJed Brown   *logging = (PetscBool)(PetscLogMalloc >= 0);
74518a2528dSJed Brown   PetscFunctionReturn(0);
74618a2528dSJed Brown }
74718a2528dSJed Brown 
748e5c89e4eSSatish Balay /*@C
749e5c89e4eSSatish Balay     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
75021b680ceSJed Brown        PetscMemoryGetMaximumUsage()
751e5c89e4eSSatish Balay 
752e5c89e4eSSatish Balay     Collective on PETSC_COMM_WORLD
753e5c89e4eSSatish Balay 
754e5c89e4eSSatish Balay     Input Parameter:
7550298fd71SBarry Smith .   fp - file pointer; or NULL
756e5c89e4eSSatish Balay 
757e5c89e4eSSatish Balay     Options Database Key:
758e5c89e4eSSatish Balay .  -malloc_log - Activates PetscMallocDumpLog()
759e5c89e4eSSatish Balay 
760e5c89e4eSSatish Balay     Level: advanced
761e5c89e4eSSatish Balay 
762e5c89e4eSSatish Balay    Fortran Note:
763e5c89e4eSSatish Balay    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
764e5c89e4eSSatish Balay    The fp defaults to stdout.
765e5c89e4eSSatish Balay 
766e5c89e4eSSatish Balay .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
767e5c89e4eSSatish Balay @*/
7687087cfbeSBarry Smith PetscErrorCode  PetscMallocDumpLog(FILE *fp)
769e5c89e4eSSatish Balay {
770e5c89e4eSSatish Balay   PetscInt       i,j,n,dummy,*perm;
771e5c89e4eSSatish Balay   size_t         *shortlength;
772f56c2debSBarry Smith   int            *shortcount,err;
773e5c89e4eSSatish Balay   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
774ace3abfcSBarry Smith   PetscBool      match;
775e5c89e4eSSatish Balay   const char     **shortfunction;
776e5c89e4eSSatish Balay   PetscLogDouble rss;
777e5c89e4eSSatish Balay   MPI_Status     status;
778e5c89e4eSSatish Balay   PetscErrorCode ierr;
779e5c89e4eSSatish Balay 
780e5c89e4eSSatish Balay   PetscFunctionBegin;
781e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(MPI_COMM_WORLD,&rank);CHKERRQ(ierr);
782e5c89e4eSSatish Balay   ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr);
783e5c89e4eSSatish Balay   /*
784e5c89e4eSSatish Balay        Try to get the data printed in order by processor. This will only sometimes work
785e5c89e4eSSatish Balay   */
786f56c2debSBarry Smith   err = fflush(fp);
787e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
788f56c2debSBarry Smith 
789e5c89e4eSSatish Balay   ierr = MPI_Barrier(MPI_COMM_WORLD);CHKERRQ(ierr);
790e5c89e4eSSatish Balay   if (rank) {
791e5c89e4eSSatish Balay     ierr = MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);CHKERRQ(ierr);
792e5c89e4eSSatish Balay   }
793e5c89e4eSSatish Balay 
794768aa557SSatish 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()");
795768aa557SSatish Balay 
796da9f1d6bSBarry Smith   if (!fp) fp = PETSC_STDOUT;
797f3d65365SJed Brown   ierr = PetscMemoryGetMaximumUsage(&rss);CHKERRQ(ierr);
798e5c89e4eSSatish Balay   if (rss) {
799f3d65365SJed 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);
800e5c89e4eSSatish Balay   } else {
801e5c89e4eSSatish 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);
802e5c89e4eSSatish Balay   }
803e32f2f54SBarry Smith   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
804e32f2f54SBarry Smith   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
805e32f2f54SBarry Smith   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
80697b9d747SJed Brown   for (i=0,n=0; i<PetscLogMalloc; i++) {
807e5c89e4eSSatish Balay     for (j=0; j<n; j++) {
808e5c89e4eSSatish Balay       ierr = PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);CHKERRQ(ierr);
809e5c89e4eSSatish Balay       if (match) {
810e5c89e4eSSatish Balay         shortlength[j] += PetscLogMallocLength[i];
81159ffdab8SBarry Smith         shortcount[j]++;
812e5c89e4eSSatish Balay         goto foundit;
813e5c89e4eSSatish Balay       }
814e5c89e4eSSatish Balay     }
815e5c89e4eSSatish Balay     shortfunction[n] = PetscLogMallocFunction[i];
816e5c89e4eSSatish Balay     shortlength[n]   = PetscLogMallocLength[i];
81759ffdab8SBarry Smith     shortcount[n]    = 1;
818e5c89e4eSSatish Balay     n++;
819e5c89e4eSSatish Balay foundit:;
820e5c89e4eSSatish Balay   }
821e5c89e4eSSatish Balay 
822e32f2f54SBarry Smith   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
823e5c89e4eSSatish Balay   for (i=0; i<n; i++) perm[i] = i;
824e5c89e4eSSatish Balay   ierr = PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);CHKERRQ(ierr);
825e5c89e4eSSatish Balay 
826e5c89e4eSSatish Balay   ierr = PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);CHKERRQ(ierr);
827e5c89e4eSSatish Balay   for (i=0; i<n; i++) {
82859ffdab8SBarry 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);
829e5c89e4eSSatish Balay   }
830e5c89e4eSSatish Balay   free(perm);
831e5c89e4eSSatish Balay   free(shortlength);
83259ffdab8SBarry Smith   free(shortcount);
833e5c89e4eSSatish Balay   free((char**)shortfunction);
834f56c2debSBarry Smith   err = fflush(fp);
835e32f2f54SBarry Smith   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
836e5c89e4eSSatish Balay   if (rank != size-1) {
837e5c89e4eSSatish Balay     ierr = MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);CHKERRQ(ierr);
838e5c89e4eSSatish Balay   }
839e5c89e4eSSatish Balay   PetscFunctionReturn(0);
840e5c89e4eSSatish Balay }
841e5c89e4eSSatish Balay 
842e5c89e4eSSatish Balay /* ---------------------------------------------------------------------------- */
843e5c89e4eSSatish Balay 
844dc37d89fSBarry Smith /*@
845e5c89e4eSSatish Balay     PetscMallocDebug - Turns on/off debugging for the memory management routines.
846e5c89e4eSSatish Balay 
847e5c89e4eSSatish Balay     Not Collective
848e5c89e4eSSatish Balay 
849e5c89e4eSSatish Balay     Input Parameter:
850e5c89e4eSSatish Balay .   level - PETSC_TRUE or PETSC_FALSE
851e5c89e4eSSatish Balay 
852e5c89e4eSSatish Balay    Level: intermediate
853e5c89e4eSSatish Balay 
854e5c89e4eSSatish Balay .seealso: CHKMEMQ(), PetscMallocValidate()
855e5c89e4eSSatish Balay @*/
8567087cfbeSBarry Smith PetscErrorCode  PetscMallocDebug(PetscBool level)
857e5c89e4eSSatish Balay {
858e5c89e4eSSatish Balay   PetscFunctionBegin;
859e5c89e4eSSatish Balay   TRdebugLevel = level;
860e5c89e4eSSatish Balay   PetscFunctionReturn(0);
861e5c89e4eSSatish Balay }
8620acecf5bSBarry Smith 
863dc37d89fSBarry Smith /*@
8640acecf5bSBarry Smith     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.
8650acecf5bSBarry Smith 
8660acecf5bSBarry Smith     Not Collective
8670acecf5bSBarry Smith 
8680acecf5bSBarry Smith     Output Parameter:
8690acecf5bSBarry Smith .    flg - PETSC_TRUE if any debugger
8700acecf5bSBarry Smith 
8710acecf5bSBarry Smith    Level: intermediate
8720acecf5bSBarry Smith 
8730acecf5bSBarry Smith     Note that by default, the debug version always does some debugging unless you run with -malloc no
8740acecf5bSBarry Smith 
8750acecf5bSBarry Smith 
8760acecf5bSBarry Smith .seealso: CHKMEMQ(), PetscMallocValidate()
8770acecf5bSBarry Smith @*/
8780acecf5bSBarry Smith PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
8790acecf5bSBarry Smith {
8800acecf5bSBarry Smith   PetscFunctionBegin;
8810acecf5bSBarry Smith   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
8820acecf5bSBarry Smith   else *flg = PETSC_FALSE;
8830acecf5bSBarry Smith   PetscFunctionReturn(0);
8840acecf5bSBarry Smith }
885