Actual source code: mtr.c

petsc-3.4.5 2014-06-29
  2: /*
  3:      Interface to malloc() and free(). This code allows for
  4:   logging of memory usage and some error checking
  5: */
  6: #include <petscsys.h>           /*I "petscsys.h" I*/
  7: #include <petscviewer.h>
  8: #if defined(PETSC_HAVE_MALLOC_H)
  9: #include <malloc.h>
 10: #endif


 13: /*
 14:      These are defined in mal.c and ensure that malloced space is PetscScalar aligned
 15: */
 16: extern PetscErrorCode  PetscMallocAlign(size_t,int,const char[],const char[],const char[],void**);
 17: extern PetscErrorCode  PetscFreeAlign(void*,int,const char[],const char[],const char[]);
 18: extern PetscErrorCode  PetscTrMallocDefault(size_t,int,const char[],const char[],const char[],void**);
 19: extern PetscErrorCode  PetscTrFreeDefault(void*,int,const char[],const char[],const char[]);


 22: #define CLASSID_VALUE   ((PetscClassId) 0xf0e0d0c9)
 23: #define ALREADY_FREED  ((PetscClassId) 0x0f0e0d9c)

 25: typedef struct _trSPACE {
 26:   size_t       size;
 27:   int          id;
 28:   int          lineno;
 29:   const char   *filename;
 30:   const char   *functionname;
 31:   const char   *dirname;
 32:   PetscClassId classid;
 33: #if defined(PETSC_USE_DEBUG)
 34:   PetscStack   stack;
 35: #endif
 36:   struct _trSPACE *next,*prev;
 37: } TRSPACE;

 39: /* HEADER_BYTES is the number of bytes in a PetscMalloc() header.
 40:    It is sizeof(TRSPACE) padded to be a multiple of PETSC_MEMALIGN.
 41: */

 43: #define HEADER_BYTES      ((sizeof(TRSPACE)+(PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1))


 46: /* This union is used to insure that the block passed to the user retains
 47:    a minimum alignment of PETSC_MEMALIGN.
 48: */
 49: typedef union {
 50:   TRSPACE sp;
 51:   char    v[HEADER_BYTES];
 52: } TrSPACE;


 55: static size_t    TRallocated  = 0;
 56: static int       TRfrags      = 0;
 57: static TRSPACE   *TRhead      = 0;
 58: static int       TRid         = 0;
 59: static PetscBool TRdebugLevel = PETSC_FALSE;
 60: static size_t    TRMaxMem     = 0;
 61: /*
 62:       Arrays to log information on all Mallocs
 63: */
 64: static int        PetscLogMallocMax       = 10000,PetscLogMalloc = -1;
 65: static size_t     PetscLogMallocThreshold = 0;
 66: static size_t     *PetscLogMallocLength;
 67: static const char **PetscLogMallocDirectory,**PetscLogMallocFile,**PetscLogMallocFunction;

 71: PetscErrorCode PetscSetUseTrMalloc_Private(void)
 72: {

 76:   PetscMallocSet(PetscTrMallocDefault,PetscTrFreeDefault);

 78:   TRallocated       = 0;
 79:   TRfrags           = 0;
 80:   TRhead            = 0;
 81:   TRid              = 0;
 82:   TRdebugLevel      = PETSC_FALSE;
 83:   TRMaxMem          = 0;
 84:   PetscLogMallocMax = 10000;
 85:   PetscLogMalloc    = -1;
 86:   return(0);
 87: }

 91: /*@C
 92:    PetscMallocValidate - Test the memory for corruption.  This can be used to
 93:    check for memory overwrites.

 95:    Input Parameter:
 96: +  line - line number where call originated.
 97: .  function - name of function calling
 98: .  file - file where function is
 99: -  dir - directory where function is

101:    Return value:
102:    The number of errors detected.

104:    Output Effect:
105:    Error messages are written to stdout.

107:    Level: advanced

109:    Notes:
110:     You should generally use CHKMEMQ as a short cut for calling this
111:     routine.

113:     The line, function, file and dir are given by the C preprocessor as
114:     __LINE__, __FUNCT__, __FILE__, and __DIR__

116:     The Fortran calling sequence is simply PetscMallocValidate(ierr)

118:    No output is generated if there are no problems detected.

120: .seealso: CHKMEMQ

122: @*/
123: PetscErrorCode  PetscMallocValidate(int line,const char function[],const char file[],const char dir[])
124: {
125:   TRSPACE      *head,*lasthead;
126:   char         *a;
127:   PetscClassId *nend;

130:   head = TRhead; lasthead = NULL;
131:   while (head) {
132:     if (head->classid != CLASSID_VALUE) {
133:       (*PetscErrorPrintf)("PetscMallocValidate: error detected at  %s() line %d in %s%s\n",function,line,dir,file);
134:       (*PetscErrorPrintf)("Memory at address %p is corrupted\n",head);
135:       (*PetscErrorPrintf)("Probably write past beginning or end of array\n");
136:       if (lasthead) (*PetscErrorPrintf)("Last intact block allocated in %s() line %d in %s%s\n",lasthead->functionname,lasthead->lineno,lasthead->dirname,lasthead->filename);
137:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
138:     }
139:     a    = (char*)(((TrSPACE*)head) + 1);
140:     nend = (PetscClassId*)(a + head->size);
141:     if (*nend != CLASSID_VALUE) {
142:       (*PetscErrorPrintf)("PetscMallocValidate: error detected at %s() line %d in %s%s\n",function,line,dir,file);
143:       if (*nend == ALREADY_FREED) {
144:         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n",head->id,(PetscLogDouble)head->size,a);
145:         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
146:       } else {
147:         (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
148:         (*PetscErrorPrintf)("Memory originally allocated in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename);
149:         SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC," ");
150:       }
151:     }
152:     lasthead = head;
153:     head     = head->next;
154:   }
155:   return(0);
156: }

160: /*
161:     PetscTrMallocDefault - Malloc with tracing.

163:     Input Parameters:
164: +   a   - number of bytes to allocate
165: .   lineno - line number where used.  Use __LINE__ for this
166: .   function - function calling routine. Use __FUNCT__ for this
167: .   filename  - file name where used.  Use __FILE__ for this
168: -   dir - directory where file is. Use __SDIR__ for this

170:     Returns:
171:     double aligned pointer to requested storage, or null if not
172:     available.
173:  */
174: PetscErrorCode  PetscTrMallocDefault(size_t a,int lineno,const char function[],const char filename[],const char dir[],void **result)
175: {
176:   TRSPACE        *head;
177:   char           *inew;
178:   size_t         nsize;

182:   if (!a) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to malloc zero size array");

184:   if (TRdebugLevel) {
185:     PetscMallocValidate(lineno,function,filename,dir); if (ierr) PetscFunctionReturn(ierr);
186:   }

188:   nsize = (a + (PETSC_MEMALIGN-1)) & ~(PETSC_MEMALIGN-1);
189:   PetscMallocAlign(nsize+sizeof(TrSPACE)+sizeof(PetscClassId),lineno,function,filename,dir,(void**)&inew);

191:   head  = (TRSPACE*)inew;
192:   inew += sizeof(TrSPACE);

194:   if (TRhead) TRhead->prev = head;
195:   head->next   = TRhead;
196:   TRhead       = head;
197:   head->prev   = 0;
198:   head->size   = nsize;
199:   head->id     = TRid;
200:   head->lineno = lineno;

202:   head->filename                 = filename;
203:   head->functionname             = function;
204:   head->dirname                  = dir;
205:   head->classid                  = CLASSID_VALUE;
206:   *(PetscClassId*)(inew + nsize) = CLASSID_VALUE;

208:   TRallocated += nsize;
209:   if (TRallocated > TRMaxMem) TRMaxMem = TRallocated;
210:   TRfrags++;

212: #if defined(PETSC_USE_DEBUG)
213:   if (PetscStackActive()) {
214:     PetscStackCopy((PetscStack*)PetscThreadLocalGetValue(petscstack),&head->stack);
216:     head->stack.line[head->stack.currentsize-2] = lineno;
217:   }
218: #endif

220:   /*
221:          Allow logging of all mallocs made
222:   */
223:   if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) {
224:     if (!PetscLogMalloc) {
225:       PetscLogMallocLength = (size_t*)malloc(PetscLogMallocMax*sizeof(size_t));
226:       if (!PetscLogMallocLength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");

228:       PetscLogMallocDirectory = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
229:       if (!PetscLogMallocDirectory) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");

231:       PetscLogMallocFile = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
232:       if (!PetscLogMallocFile) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");

234:       PetscLogMallocFunction = (const char**)malloc(PetscLogMallocMax*sizeof(char*));
235:       if (!PetscLogMallocFunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM," ");
236:     }
237:     PetscLogMallocLength[PetscLogMalloc]     = nsize;
238:     PetscLogMallocDirectory[PetscLogMalloc]  = dir;
239:     PetscLogMallocFile[PetscLogMalloc]       = filename;
240:     PetscLogMallocFunction[PetscLogMalloc++] = function;
241:   }
242:   *result = (void*)inew;
243:   return(0);
244: }


249: /*
250:    PetscTrFreeDefault - Free with tracing.

252:    Input Parameters:
253: .   a    - pointer to a block allocated with PetscTrMalloc
254: .   lineno - line number where used.  Use __LINE__ for this
255: .   function - function calling routine. Use __FUNCT__ for this
256: .   file  - file name where used.  Use __FILE__ for this
257: .   dir - directory where file is. Use __SDIR__ for this
258:  */
259: PetscErrorCode  PetscTrFreeDefault(void *aa,int line,const char function[],const char file[],const char dir[])
260: {
261:   char           *a = (char*)aa;
262:   TRSPACE        *head;
263:   char           *ahead;
265:   PetscClassId   *nend;

268:   /* Do not try to handle empty blocks */
269:   if (!a) {
270:     (*PetscErrorPrintf)("PetscTrFreeDefault called from %s() line %d in %s%s\n",function,line,dir,file);
271:     SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to free null block: Free called from %s() line %d in %s%s\n",function,line,dir,file);
272:   }

274:   if (TRdebugLevel) {
275:     PetscMallocValidate(line,function,file,dir);
276:   }

278:   ahead = a;
279:   a     = a - sizeof(TrSPACE);
280:   head  = (TRSPACE*)a;

282:   if (head->classid != CLASSID_VALUE) {
283:     (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file);
284:     (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n",a);
285:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Bad location or corrupted memory");
286:   }
287:   nend = (PetscClassId*)(ahead + head->size);
288:   if (*nend != CLASSID_VALUE) {
289:     if (*nend == ALREADY_FREED) {
290:       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file);
291:       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n",head->id,(PetscLogDouble)head->size,a + sizeof(TrSPACE));
292:       if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) {
293:         (*PetscErrorPrintf)("Block freed in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename);
294:       } else {
295:         (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,-head->lineno,head->dirname,head->filename);
296:       }
297:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Memory already freed");
298:     } else {
299:       /* Damaged tail */
300:       (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() line %d in %s%s\n",function,line,dir,file);
301:       (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n",head->id,(PetscLogDouble)head->size,a);
302:       (*PetscErrorPrintf)("Block allocated in %s() line %d in %s%s\n",head->functionname,head->lineno,head->dirname,head->filename);
303:       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Corrupted memory");
304:     }
305:   }
306:   /* Mark the location freed */
307:   *nend = ALREADY_FREED;
308:   /* Save location where freed.  If we suspect the line number, mark as  allocated location */
309:   if (line > 0 && line < 50000) {
310:     head->lineno       = line;
311:     head->filename     = file;
312:     head->functionname = function;
313:     head->dirname      = dir;
314:   } else {
315:     head->lineno = -head->lineno;
316:   }
317:   /* zero out memory - helps to find some reuse of already freed memory */
318:   PetscMemzero(aa,head->size);

320:   TRallocated -= head->size;
321:   TRfrags--;
322:   if (head->prev) head->prev->next = head->next;
323:   else TRhead = head->next;

325:   if (head->next) head->next->prev = head->prev;
326:   PetscFreeAlign(a,line,function,file,dir);
327:   return(0);
328: }


333: /*@C
334:     PetscMemoryShowUsage - Shows the amount of memory currently being used
335:         in a communicator.

337:     Collective on PetscViewer

339:     Input Parameter:
340: +    viewer - the viewer that defines the communicator
341: -    message - string printed before values

343:     Level: intermediate

345:     Concepts: memory usage

347: .seealso: PetscMallocDump(), PetscMemoryGetCurrentUsage()
348:  @*/
349: PetscErrorCode  PetscMemoryShowUsage(PetscViewer viewer,const char message[])
350: {
351:   PetscLogDouble allocated,maximum,resident,residentmax;
353:   PetscMPIInt    rank;
354:   MPI_Comm       comm;

357:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
358:   PetscMallocGetCurrentUsage(&allocated);
359:   PetscMallocGetMaximumUsage(&maximum);
360:   PetscMemoryGetCurrentUsage(&resident);
361:   PetscMemoryGetMaximumUsage(&residentmax);
362:   if (residentmax > 0) residentmax = PetscMax(resident,residentmax);
363:   PetscObjectGetComm((PetscObject)viewer,&comm);
364:   MPI_Comm_rank(comm,&rank);
365:   PetscViewerASCIIPrintf(viewer,message);
366:   PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);
367:   if (resident && residentmax && allocated) {
368:     PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g max process memory %g\n",rank,allocated,maximum,rank,resident,residentmax);
369:   } else if (resident && residentmax) {
370:     PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Run with -malloc to get statistics on PetscMalloc() calls\n[%d]Current process memory %g max process memory %g\n",rank,rank,resident,residentmax);
371:   } else if (resident && allocated) {
372:     PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]Current process memory %g, run with -memory_info to get max memory usage\n",rank,allocated,maximum,rank,resident);
373:   } else if (allocated) {
374:     PetscViewerASCIISynchronizedPrintf(viewer,"[%d]Current space PetscMalloc()ed %g, max space PetscMalloced() %g\n[%d]OS cannot compute process memory\n",rank,allocated,maximum,rank);
375:   } else {
376:     PetscViewerASCIIPrintf(viewer,"Run with -malloc to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n");
377:   }
378:   PetscViewerFlush(viewer);
379:   PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);
380:   return(0);
381: }

385: /*@C
386:     PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed

388:     Not Collective

390:     Output Parameters:
391: .   space - number of bytes currently allocated

393:     Level: intermediate

395:     Concepts: memory usage

397: .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
398:           PetscMemoryGetMaximumUsage()
399:  @*/
400: PetscErrorCode  PetscMallocGetCurrentUsage(PetscLogDouble *space)
401: {
403:   *space = (PetscLogDouble) TRallocated;
404:   return(0);
405: }

409: /*@C
410:     PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time
411:         during this run.

413:     Not Collective

415:     Output Parameters:
416: .   space - maximum number of bytes ever allocated at one time

418:     Level: intermediate

420:     Concepts: memory usage

422: .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocGetMaximumUsage(), PetscMemoryGetCurrentUsage(),
423:           PetscMemoryGetCurrentUsage()
424:  @*/
425: PetscErrorCode  PetscMallocGetMaximumUsage(PetscLogDouble *space)
426: {
428:   *space = (PetscLogDouble) TRMaxMem;
429:   return(0);
430: }

432: #if defined(PETSC_USE_DEBUG)
435: /*@C
436:    PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory

438:    Collective on PETSC_COMM_WORLD

440:    Input Parameter:
441: .    ptr - the memory location

443:    Output Paramter:
444: .    stack - the stack indicating where the program allocated this memory

446:    Level: intermediate

448: .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
449: @*/
450: PetscErrorCode  PetscMallocGetStack(void *ptr,PetscStack **stack)
451: {
452:   TRSPACE *head;

455:   head   = (TRSPACE*) (((char*)ptr) - HEADER_BYTES);
456:   *stack = &head->stack;
457:   return(0);
458: }
459: #else
462: PetscErrorCode  PetscMallocGetStack(void *ptr,void **stack)
463: {
465:   *stack = 0;
466:   return(0);
467: }
468: #endif

472: /*@C
473:    PetscMallocDump - Dumps the allocated memory blocks to a file. The information
474:    printed is: size of space (in bytes), address of space, id of space,
475:    file in which space was allocated, and line number at which it was
476:    allocated.

478:    Collective on PETSC_COMM_WORLD

480:    Input Parameter:
481: .  fp  - file pointer.  If fp is NULL, stdout is assumed.

483:    Options Database Key:
484: .  -malloc_dump - Dumps unfreed memory during call to PetscFinalize()

486:    Level: intermediate

488:    Fortran Note:
489:    The calling sequence in Fortran is PetscMallocDump(integer ierr)
490:    The fp defaults to stdout.

492:    Notes: uses MPI_COMM_WORLD, because this may be called in PetscFinalize() after PETSC_COMM_WORLD
493:           has been freed.

495:    Concepts: memory usage
496:    Concepts: memory bleeding
497:    Concepts: bleeding memory

499: .seealso:  PetscMallocGetCurrentUsage(), PetscMallocDumpLog()
500: @*/
501: PetscErrorCode  PetscMallocDump(FILE *fp)
502: {
503:   TRSPACE        *head;
505:   PetscMPIInt    rank;

508:   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
509:   if (!fp) fp = PETSC_STDOUT;
510:   if (TRallocated > 0) fprintf(fp,"[%d]Total space allocated %.0f bytes\n",rank,(PetscLogDouble)TRallocated);
511:   head = TRhead;
512:   while (head) {
513:     fprintf(fp,"[%2d]%.0f bytes %s() line %d in %s%s\n",rank,(PetscLogDouble)head->size,head->functionname,head->lineno,head->dirname,head->filename);
514: #if defined(PETSC_USE_DEBUG)
515:     PetscStackPrint(&head->stack,fp);
516: #endif
517:     head = head->next;
518:   }
519:   return(0);
520: }

522: /* ---------------------------------------------------------------------------- */

526: /*@C
527:     PetscMallocSetDumpLog - Activates logging of all calls to PetscMalloc().

529:     Not Collective

531:     Options Database Key:
532: +  -malloc_log <filename> - Activates PetscMallocDumpLog()
533: -  -malloc_log_threshold <min> - Activates logging and sets a minimum size

535:     Level: advanced

537: .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLogThreshold()
538: @*/
539: PetscErrorCode PetscMallocSetDumpLog(void)
540: {

544:   PetscLogMalloc = 0;

546:   PetscMemorySetGetMaximumUsage();
547:   return(0);
548: }

552: /*@C
553:     PetscMallocSetDumpLogThreshold - Activates logging of all calls to PetscMalloc().

555:     Not Collective

557:     Input Arguments:
558: .   logmin - minimum allocation size to log, or PETSC_DEFAULT

560:     Options Database Key:
561: +  -malloc_log <filename> - Activates PetscMallocDumpLog()
562: -  -malloc_log_threshold <min> - Activates logging and sets a minimum size

564:     Level: advanced

566: .seealso: PetscMallocDump(), PetscMallocDumpLog(), PetscMallocSetDumpLog()
567: @*/
568: PetscErrorCode PetscMallocSetDumpLogThreshold(PetscLogDouble logmin)
569: {

573:   PetscMallocSetDumpLog();
574:   if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */
575:   PetscLogMallocThreshold = (size_t)logmin;
576:   return(0);
577: }

581: /*@C
582:     PetscMallocGetDumpLog - Determine whether all calls to PetscMalloc() are being logged

584:     Not Collective

586:     Output Arguments
587: .   logging - PETSC_TRUE if logging is active

589:     Options Database Key:
590: .  -malloc_log - Activates PetscMallocDumpLog()

592:     Level: advanced

594: .seealso: PetscMallocDump(), PetscMallocDumpLog()
595: @*/
596: PetscErrorCode PetscMallocGetDumpLog(PetscBool *logging)
597: {

600:   *logging = (PetscBool)(PetscLogMalloc >= 0);
601:   return(0);
602: }

606: /*@C
607:     PetscMallocDumpLog - Dumps the log of all calls to PetscMalloc(); also calls
608:        PetscMemoryGetMaximumUsage()

610:     Collective on PETSC_COMM_WORLD

612:     Input Parameter:
613: .   fp - file pointer; or NULL

615:     Options Database Key:
616: .  -malloc_log - Activates PetscMallocDumpLog()

618:     Level: advanced

620:    Fortran Note:
621:    The calling sequence in Fortran is PetscMallocDumpLog(integer ierr)
622:    The fp defaults to stdout.

624: .seealso: PetscMallocGetCurrentUsage(), PetscMallocDump(), PetscMallocSetDumpLog()
625: @*/
626: PetscErrorCode  PetscMallocDumpLog(FILE *fp)
627: {
628:   PetscInt       i,j,n,dummy,*perm;
629:   size_t         *shortlength;
630:   int            *shortcount,err;
631:   PetscMPIInt    rank,size,tag = 1212 /* very bad programming */;
632:   PetscBool      match;
633:   const char     **shortfunction;
634:   PetscLogDouble rss;
635:   MPI_Status     status;

639:   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
640:   MPI_Comm_size(MPI_COMM_WORLD,&size);
641:   /*
642:        Try to get the data printed in order by processor. This will only sometimes work
643:   */
644:   err = fflush(fp);
645:   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");

647:   MPI_Barrier(MPI_COMM_WORLD);
648:   if (rank) {
649:     MPI_Recv(&dummy,1,MPIU_INT,rank-1,tag,MPI_COMM_WORLD,&status);
650:   }

652:   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()");

654:   if (!fp) fp = PETSC_STDOUT;
655:   PetscMemoryGetMaximumUsage(&rss);
656:   if (rss) {
657:     PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n",rank,(PetscLogDouble)TRMaxMem,rss);
658:   } else {
659:     PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n",rank,(PetscLogDouble)TRMaxMem);
660:   }
661:   shortcount    = (int*)malloc(PetscLogMalloc*sizeof(int));if (!shortcount) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
662:   shortlength   = (size_t*)malloc(PetscLogMalloc*sizeof(size_t));if (!shortlength) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
663:   shortfunction = (const char**)malloc(PetscLogMalloc*sizeof(char*));if (!shortfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
664:   for (i=0,n=0; i<PetscLogMalloc; i++) {
665:     for (j=0; j<n; j++) {
666:       PetscStrcmp(shortfunction[j],PetscLogMallocFunction[i],&match);
667:       if (match) {
668:         shortlength[j] += PetscLogMallocLength[i];
669:         shortcount[j]++;
670:         goto foundit;
671:       }
672:     }
673:     shortfunction[n] = PetscLogMallocFunction[i];
674:     shortlength[n]   = PetscLogMallocLength[i];
675:     shortcount[n]    = 1;
676:     n++;
677: foundit:;
678:   }

680:   perm = (PetscInt*)malloc(n*sizeof(PetscInt));if (!perm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEM,"Out of memory");
681:   for (i=0; i<n; i++) perm[i] = i;
682:   PetscSortStrWithPermutation(n,(const char**)shortfunction,perm);

684:   PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] Memory usage sorted by function\n",rank);
685:   for (i=0; i<n; i++) {
686:     PetscFPrintf(MPI_COMM_WORLD,fp,"[%d] %d %.0f %s()\n",rank,shortcount[perm[i]],(PetscLogDouble)shortlength[perm[i]],shortfunction[perm[i]]);
687:   }
688:   free(perm);
689:   free(shortlength);
690:   free(shortcount);
691:   free((char**)shortfunction);
692:   err = fflush(fp);
693:   if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file");
694:   if (rank != size-1) {
695:     MPI_Send(&dummy,1,MPIU_INT,rank+1,tag,MPI_COMM_WORLD);
696:   }
697:   return(0);
698: }

700: /* ---------------------------------------------------------------------------- */

704: /*@C
705:     PetscMallocDebug - Turns on/off debugging for the memory management routines.

707:     Not Collective

709:     Input Parameter:
710: .   level - PETSC_TRUE or PETSC_FALSE

712:    Level: intermediate

714: .seealso: CHKMEMQ(), PetscMallocValidate()
715: @*/
716: PetscErrorCode  PetscMallocDebug(PetscBool level)
717: {
719:   TRdebugLevel = level;
720:   return(0);
721: }

725: /*@C
726:     PetscMallocGetDebug - Indicates if any PETSc is doing ANY memory debugging.

728:     Not Collective

730:     Output Parameter:
731: .    flg - PETSC_TRUE if any debugger

733:    Level: intermediate

735:     Note that by default, the debug version always does some debugging unless you run with -malloc no


738: .seealso: CHKMEMQ(), PetscMallocValidate()
739: @*/
740: PetscErrorCode  PetscMallocGetDebug(PetscBool *flg)
741: {
743:   if (PetscTrMalloc == PetscTrMallocDefault) *flg = PETSC_TRUE;
744:   else *flg = PETSC_FALSE;
745:   return(0);
746: }