1 2 /* 3 Interface to malloc() and free(). This code allows for logging of memory usage and some error checking 4 */ 5 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 6 #include <petscviewer.h> 7 #if defined(PETSC_HAVE_MALLOC_H) 8 #include <malloc.h> 9 #endif 10 11 /* 12 These are defined in mal.c and ensure that malloced space is PetscScalar aligned 13 */ 14 PETSC_EXTERN PetscErrorCode PetscMallocAlign(size_t, PetscBool, int, const char[], const char[], void **); 15 PETSC_EXTERN PetscErrorCode PetscFreeAlign(void *, int, const char[], const char[]); 16 PETSC_EXTERN PetscErrorCode PetscReallocAlign(size_t, int, const char[], const char[], void **); 17 18 #define CLASSID_VALUE ((PetscClassId)0xf0e0d0c9) 19 #define ALREADY_FREED ((PetscClassId)0x0f0e0d9c) 20 21 /* this is the header put at the beginning of each malloc() using for tracking allocated space and checking of allocated space heap */ 22 typedef struct _trSPACE { 23 size_t size, rsize; /* Aligned size and requested size */ 24 int id; 25 int lineno; 26 const char *filename; 27 const char *functionname; 28 PetscClassId classid; 29 #if defined(PETSC_USE_DEBUG) 30 PetscStack stack; 31 #endif 32 struct _trSPACE *next, *prev; 33 } TRSPACE; 34 35 /* HEADER_BYTES is the number of bytes in a PetscMalloc() header. 36 It is sizeof(trSPACE) padded to be a multiple of PETSC_MEMALIGN. 37 */ 38 #define HEADER_BYTES ((sizeof(TRSPACE) + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1)) 39 40 /* This union is used to insure that the block passed to the user retains 41 a minimum alignment of PETSC_MEMALIGN. 42 */ 43 typedef union 44 { 45 TRSPACE sp; 46 char v[HEADER_BYTES]; 47 } TrSPACE; 48 49 #define MAXTRMAXMEMS 50 50 static size_t TRallocated = 0; 51 static int TRfrags = 0; 52 static TRSPACE *TRhead = NULL; 53 static int TRid = 0; 54 static PetscBool TRdebugLevel = PETSC_FALSE; 55 static PetscBool TRdebugIinitializenan = PETSC_FALSE; 56 static PetscBool TRrequestedSize = PETSC_FALSE; 57 static size_t TRMaxMem = 0; 58 static int NumTRMaxMems = 0; 59 static size_t TRMaxMems[MAXTRMAXMEMS]; 60 static int TRMaxMemsEvents[MAXTRMAXMEMS]; 61 /* 62 Arrays to log information on mallocs for PetscMallocView() 63 */ 64 static int PetscLogMallocMax = 10000; 65 static int PetscLogMalloc = -1; 66 static size_t PetscLogMallocThreshold = 0; 67 static size_t *PetscLogMallocLength; 68 static const char **PetscLogMallocFile, **PetscLogMallocFunction; 69 static int PetscLogMallocTrace = -1; 70 static size_t PetscLogMallocTraceThreshold = 0; 71 static PetscViewer PetscLogMallocTraceViewer = NULL; 72 73 /*@C 74 PetscMallocValidate - Test the memory for corruption. This can be called at any time between PetscInitialize() and PetscFinalize() 75 76 Input Parameters: 77 + line - line number where call originated. 78 . function - name of function calling 79 - file - file where function is 80 81 Return value: 82 The number of errors detected. 83 84 Options Database:. 85 + -malloc_test - turns this feature on when PETSc was not configured with --with-debugging=0 86 - -malloc_debug - turns this feature on anytime 87 88 Output Effect: 89 Error messages are written to stdout. 90 91 Level: advanced 92 93 Notes: 94 This is only run if PetscMallocSetDebug() has been called which is set by -malloc_test (if debugging is turned on) or -malloc_debug (any time) 95 96 You should generally use CHKMEMQ as a short cut for calling this routine. 97 98 The Fortran calling sequence is simply PetscMallocValidate(ierr) 99 100 No output is generated if there are no problems detected. 101 102 Developers Note: 103 Uses the flg TRdebugLevel (set as the first argument to PetscMallocSetDebug()) to determine if it should run 104 105 .seealso: `CHKMEMQ` 106 107 @*/ 108 PetscErrorCode PetscMallocValidate(int line, const char function[], const char file[]) { 109 TRSPACE *head, *lasthead; 110 char *a; 111 PetscClassId *nend; 112 113 if (!TRdebugLevel) return 0; 114 head = TRhead; 115 lasthead = NULL; 116 if (head && head->prev) { 117 (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 118 (*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", head, head->prev); 119 return PETSC_ERR_MEMC; 120 } 121 while (head) { 122 if (head->classid != CLASSID_VALUE) { 123 (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 124 (*PetscErrorPrintf)("Memory at address %p is corrupted\n", head); 125 (*PetscErrorPrintf)("Probably write before beginning of or past end of array\n"); 126 if (lasthead) { 127 a = (char *)(((TrSPACE *)head) + 1); 128 (*PetscErrorPrintf)("Last intact block [id=%d(%.0f)] at address %p allocated in %s() at %s:%d\n", lasthead->id, (PetscLogDouble)lasthead->size, a, lasthead->functionname, lasthead->filename, lasthead->lineno); 129 } 130 abort(); 131 return PETSC_ERR_MEMC; 132 } 133 a = (char *)(((TrSPACE *)head) + 1); 134 nend = (PetscClassId *)(a + head->size); 135 if (*nend != CLASSID_VALUE) { 136 (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 137 if (*nend == ALREADY_FREED) { 138 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p already freed\n", head->id, (PetscLogDouble)head->size, a); 139 return PETSC_ERR_MEMC; 140 } else { 141 (*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a); 142 (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 143 return PETSC_ERR_MEMC; 144 } 145 } 146 if (head->prev && head->prev != lasthead) { 147 (*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line); 148 (*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", head->prev, lasthead); 149 (*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno); 150 (*PetscErrorPrintf)("Memory originally allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 151 return PETSC_ERR_MEMC; 152 } 153 lasthead = head; 154 head = head->next; 155 } 156 return 0; 157 } 158 159 /* 160 PetscTrMallocDefault - Malloc with tracing. 161 162 Input Parameters: 163 + a - number of bytes to allocate 164 . lineno - line number where used. Use __LINE__ for this 165 - filename - file name where used. Use __FILE__ for this 166 167 Returns: 168 double aligned pointer to requested storage, or null if not available. 169 */ 170 PetscErrorCode PetscTrMallocDefault(size_t a, PetscBool clear, int lineno, const char function[], const char filename[], void **result) { 171 TRSPACE *head; 172 char *inew; 173 size_t nsize; 174 175 PetscFunctionBegin; 176 /* Do not try to handle empty blocks */ 177 if (!a) { 178 *result = NULL; 179 PetscFunctionReturn(0); 180 } 181 182 PetscCall(PetscMallocValidate(lineno, function, filename)); 183 184 nsize = (a + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 185 PetscCall(PetscMallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), clear, lineno, function, filename, (void **)&inew)); 186 187 head = (TRSPACE *)inew; 188 inew += sizeof(TrSPACE); 189 190 if (TRhead) TRhead->prev = head; 191 head->next = TRhead; 192 TRhead = head; 193 head->prev = NULL; 194 head->size = nsize; 195 head->rsize = a; 196 head->id = TRid++; 197 head->lineno = lineno; 198 199 head->filename = filename; 200 head->functionname = function; 201 head->classid = CLASSID_VALUE; 202 *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 203 204 TRallocated += TRrequestedSize ? head->rsize : head->size; 205 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 206 if (PetscLogMemory) { 207 PetscInt i; 208 for (i = 0; i < NumTRMaxMems; i++) { 209 if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 210 } 211 } 212 TRfrags++; 213 214 #if defined(PETSC_USE_DEBUG) 215 PetscCall(PetscStackCopy(&petscstack, &head->stack)); 216 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 217 head->stack.line[head->stack.currentsize - 2] = lineno; 218 #if defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL_DOUBLE) 219 if (!clear && TRdebugIinitializenan) { 220 size_t i, n = a / sizeof(PetscReal); 221 PetscReal *s = (PetscReal *)inew; 222 /* from https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html */ 223 #if defined(PETSC_USE_REAL_SINGLE) 224 int nas = 0x7F800002; 225 #else 226 PetscInt64 nas = 0x7FF0000000000002; 227 #endif 228 for (i = 0; i < n; i++) memcpy(s + i, &nas, sizeof(PetscReal)); 229 } 230 #endif 231 #endif 232 233 /* 234 Allow logging of all mallocs made. 235 TODO: Currently this memory is never freed, it should be freed during PetscFinalize() 236 */ 237 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && a >= PetscLogMallocThreshold) { 238 if (!PetscLogMalloc) { 239 PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 240 PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 241 242 PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 243 PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 244 245 PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 246 PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 247 } 248 PetscLogMallocLength[PetscLogMalloc] = nsize; 249 PetscLogMallocFile[PetscLogMalloc] = filename; 250 PetscLogMallocFunction[PetscLogMalloc++] = function; 251 } 252 if (PetscLogMallocTrace > -1 && a >= PetscLogMallocTraceThreshold) PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Alloc %zu %s:%d (%s)\n", a, filename ? filename : "null", lineno, function ? function : "null")); 253 *result = (void *)inew; 254 PetscFunctionReturn(0); 255 } 256 257 /* 258 PetscTrFreeDefault - Free with tracing. 259 260 Input Parameters: 261 . a - pointer to a block allocated with PetscTrMalloc 262 . lineno - line number where used. Use __LINE__ for this 263 . filename - file name where used. Use __FILE__ for this 264 */ 265 PetscErrorCode PetscTrFreeDefault(void *aa, int lineno, const char function[], const char filename[]) { 266 char *a = (char *)aa; 267 TRSPACE *head; 268 char *ahead; 269 size_t asize; 270 PetscClassId *nend; 271 272 PetscFunctionBegin; 273 /* Do not try to handle empty blocks */ 274 if (!a) PetscFunctionReturn(0); 275 276 PetscCall(PetscMallocValidate(lineno, function, filename)); 277 278 ahead = a; 279 a = a - sizeof(TrSPACE); 280 head = (TRSPACE *)a; 281 282 if (head->classid != CLASSID_VALUE) { 283 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno); 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() at %s:%d\n", function, filename, lineno); 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() at %s:%d\n", head->functionname, head->filename, head->lineno); 294 } else { 295 (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno); 296 } 297 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 298 } else { 299 /* Damaged tail */ 300 (*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno); 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() at %s:%d\n", head->functionname, head->filename, head->lineno); 303 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 304 } 305 } 306 if (PetscLogMallocTrace > -1 && head->rsize >= PetscLogMallocTraceThreshold) { 307 PetscCall(PetscViewerASCIIPrintf(PetscLogMallocTraceViewer, "Free %zu %s:%d (%s)\n", head->rsize, filename ? filename : "null", lineno, function ? function : "null")); 308 } 309 /* Mark the location freed */ 310 *nend = ALREADY_FREED; 311 /* Save location where freed. If we suspect the line number, mark as allocated location */ 312 if (lineno > 0 && lineno < 50000) { 313 head->lineno = lineno; 314 head->filename = filename; 315 head->functionname = function; 316 } else { 317 head->lineno = -head->lineno; 318 } 319 asize = TRrequestedSize ? head->rsize : head->size; 320 PetscCheck(TRallocated >= asize, PETSC_COMM_SELF, PETSC_ERR_MEMC, "TRallocate is smaller than memory just freed"); 321 TRallocated -= asize; 322 TRfrags--; 323 if (head->prev) head->prev->next = head->next; 324 else TRhead = head->next; 325 326 if (head->next) head->next->prev = head->prev; 327 PetscCall(PetscFreeAlign(a, lineno, function, filename)); 328 PetscFunctionReturn(0); 329 } 330 331 /* 332 PetscTrReallocDefault - Realloc with tracing. 333 334 Input Parameters: 335 + len - number of bytes to allocate 336 . lineno - line number where used. Use __LINE__ for this 337 . filename - file name where used. Use __FILE__ for this 338 - result - original memory 339 340 Output Parameter: 341 . result - double aligned pointer to requested storage, or null if not available. 342 343 Level: developer 344 345 .seealso: `PetscTrMallocDefault()`, `PetscTrFreeDefault()` 346 */ 347 PetscErrorCode PetscTrReallocDefault(size_t len, int lineno, const char function[], const char filename[], void **result) { 348 char *a = (char *)*result; 349 TRSPACE *head; 350 char *ahead, *inew; 351 PetscClassId *nend; 352 size_t nsize; 353 354 PetscFunctionBegin; 355 /* Realloc requests zero space so just free the current space */ 356 if (!len) { 357 PetscCall(PetscTrFreeDefault(*result, lineno, function, filename)); 358 *result = NULL; 359 PetscFunctionReturn(0); 360 } 361 /* If the orginal space was NULL just use the regular malloc() */ 362 if (!*result) { 363 PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result)); 364 PetscFunctionReturn(0); 365 } 366 367 PetscCall(PetscMallocValidate(lineno, function, filename)); 368 369 ahead = a; 370 a = a - sizeof(TrSPACE); 371 head = (TRSPACE *)a; 372 inew = a; 373 374 if (head->classid != CLASSID_VALUE) { 375 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 376 (*PetscErrorPrintf)("Block at address %p is corrupted; cannot free;\nmay be block not allocated with PetscMalloc()\n", a); 377 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Bad location or corrupted memory"); 378 } 379 nend = (PetscClassId *)(ahead + head->size); 380 if (*nend != CLASSID_VALUE) { 381 if (*nend == ALREADY_FREED) { 382 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 383 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p was already freed\n", head->id, (PetscLogDouble)head->size, a + sizeof(TrSPACE)); 384 if (head->lineno > 0 && head->lineno < 50000 /* sanity check */) { 385 (*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 386 } else { 387 (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, -head->lineno); 388 } 389 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Memory already freed"); 390 } else { 391 /* Damaged tail */ 392 (*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno); 393 (*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a); 394 (*PetscErrorPrintf)("Block allocated in %s() at %s:%d\n", head->functionname, head->filename, head->lineno); 395 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_MEMC, "Corrupted memory"); 396 } 397 } 398 399 /* remove original reference to the memory allocated from the PETSc debugging heap */ 400 TRallocated -= TRrequestedSize ? head->rsize : head->size; 401 TRfrags--; 402 if (head->prev) head->prev->next = head->next; 403 else TRhead = head->next; 404 if (head->next) head->next->prev = head->prev; 405 406 nsize = (len + (PETSC_MEMALIGN - 1)) & ~(PETSC_MEMALIGN - 1); 407 PetscCall(PetscReallocAlign(nsize + sizeof(TrSPACE) + sizeof(PetscClassId), lineno, function, filename, (void **)&inew)); 408 409 head = (TRSPACE *)inew; 410 inew += sizeof(TrSPACE); 411 412 if (TRhead) TRhead->prev = head; 413 head->next = TRhead; 414 TRhead = head; 415 head->prev = NULL; 416 head->size = nsize; 417 head->rsize = len; 418 head->id = TRid++; 419 head->lineno = lineno; 420 421 head->filename = filename; 422 head->functionname = function; 423 head->classid = CLASSID_VALUE; 424 *(PetscClassId *)(inew + nsize) = CLASSID_VALUE; 425 426 TRallocated += TRrequestedSize ? head->rsize : head->size; 427 if (TRallocated > TRMaxMem) TRMaxMem = TRallocated; 428 if (PetscLogMemory) { 429 PetscInt i; 430 for (i = 0; i < NumTRMaxMems; i++) { 431 if (TRallocated > TRMaxMems[i]) TRMaxMems[i] = TRallocated; 432 } 433 } 434 TRfrags++; 435 436 #if defined(PETSC_USE_DEBUG) 437 PetscCall(PetscStackCopy(&petscstack, &head->stack)); 438 /* fix the line number to where the malloc() was called, not the PetscFunctionBegin; */ 439 head->stack.line[head->stack.currentsize - 2] = lineno; 440 #endif 441 442 /* 443 Allow logging of all mallocs made. This adds a new entry to the list of allocated memory 444 and does not remove the previous entry to the list hence this memory is "double counted" in PetscMallocView() 445 */ 446 if (PetscLogMalloc > -1 && PetscLogMalloc < PetscLogMallocMax && len >= PetscLogMallocThreshold) { 447 if (!PetscLogMalloc) { 448 PetscLogMallocLength = (size_t *)malloc(PetscLogMallocMax * sizeof(size_t)); 449 PetscCheck(PetscLogMallocLength, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 450 451 PetscLogMallocFile = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 452 PetscCheck(PetscLogMallocFile, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 453 454 PetscLogMallocFunction = (const char **)malloc(PetscLogMallocMax * sizeof(char *)); 455 PetscCheck(PetscLogMallocFunction, PETSC_COMM_SELF, PETSC_ERR_MEM, " "); 456 } 457 PetscLogMallocLength[PetscLogMalloc] = nsize; 458 PetscLogMallocFile[PetscLogMalloc] = filename; 459 PetscLogMallocFunction[PetscLogMalloc++] = function; 460 } 461 *result = (void *)inew; 462 PetscFunctionReturn(0); 463 } 464 465 /*@C 466 PetscMemoryView - Shows the amount of memory currently being used in a communicator. 467 468 Collective on PetscViewer 469 470 Input Parameters: 471 + viewer - the viewer that defines the communicator 472 - message - string printed before values 473 474 Options Database: 475 + -malloc_debug - have PETSc track how much memory it has allocated 476 - -memory_view - during PetscFinalize() have this routine called 477 478 Level: intermediate 479 480 .seealso: `PetscMallocDump()`, `PetscMemoryGetCurrentUsage()`, `PetscMemorySetGetMaximumUsage()`, `PetscMallocView()` 481 @*/ 482 PetscErrorCode PetscMemoryView(PetscViewer viewer, const char message[]) { 483 PetscLogDouble allocated, allocatedmax, resident, residentmax, gallocated, gallocatedmax, gresident, gresidentmax, maxgallocated, maxgallocatedmax, maxgresident, maxgresidentmax; 484 PetscLogDouble mingallocated, mingallocatedmax, mingresident, mingresidentmax; 485 MPI_Comm comm; 486 487 PetscFunctionBegin; 488 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 489 PetscCall(PetscMallocGetCurrentUsage(&allocated)); 490 PetscCall(PetscMallocGetMaximumUsage(&allocatedmax)); 491 PetscCall(PetscMemoryGetCurrentUsage(&resident)); 492 PetscCall(PetscMemoryGetMaximumUsage(&residentmax)); 493 if (residentmax > 0) residentmax = PetscMax(resident, residentmax); 494 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm)); 495 PetscCall(PetscViewerASCIIPrintf(viewer, "%s", message)); 496 if (resident && residentmax && allocated) { 497 PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 498 PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 499 PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 500 PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 501 PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 502 PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 503 PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 504 PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 505 PetscCallMPI(MPI_Reduce(&allocatedmax, &gallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 506 PetscCallMPI(MPI_Reduce(&allocatedmax, &maxgallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 507 PetscCallMPI(MPI_Reduce(&allocatedmax, &mingallocatedmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 508 PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocatedmax, maxgallocatedmax, mingallocatedmax)); 509 PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 510 PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 511 PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 512 PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 513 } else if (resident && residentmax) { 514 PetscCallMPI(MPI_Reduce(&residentmax, &gresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 515 PetscCallMPI(MPI_Reduce(&residentmax, &maxgresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 516 PetscCallMPI(MPI_Reduce(&residentmax, &mingresidentmax, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 517 PetscCall(PetscViewerASCIIPrintf(viewer, "Maximum (over computational time) process memory: total %5.4e max %5.4e min %5.4e\n", gresidentmax, maxgresidentmax, mingresidentmax)); 518 PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 519 PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 520 PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 521 PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 522 } else if (resident && allocated) { 523 PetscCallMPI(MPI_Reduce(&resident, &gresident, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 524 PetscCallMPI(MPI_Reduce(&resident, &maxgresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 525 PetscCallMPI(MPI_Reduce(&resident, &mingresident, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 526 PetscCall(PetscViewerASCIIPrintf(viewer, "Current process memory: total %5.4e max %5.4e min %5.4e\n", gresident, maxgresident, mingresident)); 527 PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 528 PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 529 PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 530 PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 531 PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 532 } else if (allocated) { 533 PetscCallMPI(MPI_Reduce(&allocated, &gallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_SUM, 0, comm)); 534 PetscCallMPI(MPI_Reduce(&allocated, &maxgallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MAX, 0, comm)); 535 PetscCallMPI(MPI_Reduce(&allocated, &mingallocated, 1, MPIU_PETSCLOGDOUBLE, MPI_MIN, 0, comm)); 536 PetscCall(PetscViewerASCIIPrintf(viewer, "Current space PetscMalloc()ed: total %5.4e max %5.4e min %5.4e\n", gallocated, maxgallocated, mingallocated)); 537 PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -memory_view to get maximum memory usage\n")); 538 PetscCall(PetscViewerASCIIPrintf(viewer, "OS cannot compute process memory\n")); 539 } else { 540 PetscCall(PetscViewerASCIIPrintf(viewer, "Run with -malloc_debug to get statistics on PetscMalloc() calls\nOS cannot compute process memory\n")); 541 } 542 PetscCall(PetscViewerFlush(viewer)); 543 PetscFunctionReturn(0); 544 } 545 546 /*@ 547 PetscMallocGetCurrentUsage - gets the current amount of memory used that was PetscMalloc()ed 548 549 Not Collective 550 551 Output Parameters: 552 . space - number of bytes currently allocated 553 554 Level: intermediate 555 556 .seealso: `PetscMallocDump()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 557 `PetscMemoryGetMaximumUsage()` 558 @*/ 559 PetscErrorCode PetscMallocGetCurrentUsage(PetscLogDouble *space) { 560 PetscFunctionBegin; 561 *space = (PetscLogDouble)TRallocated; 562 PetscFunctionReturn(0); 563 } 564 565 /*@ 566 PetscMallocGetMaximumUsage - gets the maximum amount of memory used that was PetscMalloc()ed at any time 567 during this run. 568 569 Not Collective 570 571 Output Parameters: 572 . space - maximum number of bytes ever allocated at one time 573 574 Level: intermediate 575 576 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 577 `PetscMallocPushMaximumUsage()` 578 @*/ 579 PetscErrorCode PetscMallocGetMaximumUsage(PetscLogDouble *space) { 580 PetscFunctionBegin; 581 *space = (PetscLogDouble)TRMaxMem; 582 PetscFunctionReturn(0); 583 } 584 585 /*@ 586 PetscMallocPushMaximumUsage - Adds another event to collect the maximum memory usage over an event 587 588 Not Collective 589 590 Input Parameter: 591 . event - an event id; this is just for error checking 592 593 Level: developer 594 595 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 596 `PetscMallocPopMaximumUsage()` 597 @*/ 598 PetscErrorCode PetscMallocPushMaximumUsage(int event) { 599 PetscFunctionBegin; 600 if (++NumTRMaxMems > MAXTRMAXMEMS) PetscFunctionReturn(0); 601 TRMaxMems[NumTRMaxMems - 1] = TRallocated; 602 TRMaxMemsEvents[NumTRMaxMems - 1] = event; 603 PetscFunctionReturn(0); 604 } 605 606 /*@ 607 PetscMallocPopMaximumUsage - collect the maximum memory usage over an event 608 609 Not Collective 610 611 Input Parameter: 612 . event - an event id; this is just for error checking 613 614 Output Parameter: 615 . mu - maximum amount of memory malloced during this event; high water mark relative to the beginning of the event 616 617 Level: developer 618 619 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocGetMaximumUsage()`, `PetscMemoryGetCurrentUsage()`, 620 `PetscMallocPushMaximumUsage()` 621 @*/ 622 PetscErrorCode PetscMallocPopMaximumUsage(int event, PetscLogDouble *mu) { 623 PetscFunctionBegin; 624 *mu = 0; 625 if (NumTRMaxMems-- > MAXTRMAXMEMS) PetscFunctionReturn(0); 626 PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested"); 627 *mu = TRMaxMems[NumTRMaxMems]; 628 PetscFunctionReturn(0); 629 } 630 631 #if defined(PETSC_USE_DEBUG) 632 /*@C 633 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to PetscMalloc() was used to obtain that memory 634 635 Collective on PETSC_COMM_WORLD 636 637 Input Parameter: 638 . ptr - the memory location 639 640 Output Parameter: 641 . stack - the stack indicating where the program allocated this memory 642 643 Level: intermediate 644 645 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()` 646 @*/ 647 PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) { 648 TRSPACE *head; 649 650 PetscFunctionBegin; 651 head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES); 652 *stack = &head->stack; 653 PetscFunctionReturn(0); 654 } 655 #else 656 PetscErrorCode PetscMallocGetStack(void *ptr, void **stack) { 657 PetscFunctionBegin; 658 *stack = NULL; 659 PetscFunctionReturn(0); 660 } 661 #endif 662 663 /*@C 664 PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information 665 printed is: size of space (in bytes), address of space, id of space, 666 file in which space was allocated, and line number at which it was 667 allocated. 668 669 Not Collective 670 671 Input Parameter: 672 . fp - file pointer. If fp is NULL, stdout is assumed. 673 674 Options Database Key: 675 . -malloc_dump <optional filename> - Dumps unfreed memory during call to PetscFinalize() 676 677 Level: intermediate 678 679 Fortran Note: 680 The calling sequence in Fortran is PetscMallocDump(integer ierr) 681 The fp defaults to stdout. 682 683 Notes: 684 Uses MPI_COMM_WORLD to display rank, because this may be called in PetscFinalize() after PETSC_COMM_WORLD has been freed. 685 686 When called in PetscFinalize() dumps only the allocations that have not been properly freed 687 688 PetscMallocView() prints a list of all memory ever allocated 689 690 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()` 691 @*/ 692 PetscErrorCode PetscMallocDump(FILE *fp) { 693 TRSPACE *head; 694 size_t libAlloc = 0; 695 PetscMPIInt rank; 696 697 PetscFunctionBegin; 698 PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 699 if (!fp) fp = PETSC_STDOUT; 700 head = TRhead; 701 while (head) { 702 libAlloc += TRrequestedSize ? head->rsize : head->size; 703 head = head->next; 704 } 705 if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated); 706 head = TRhead; 707 while (head) { 708 PetscBool isLib; 709 710 PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib)); 711 if (!isLib) { 712 fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno); 713 #if defined(PETSC_USE_DEBUG) 714 PetscCall(PetscStackPrint(&head->stack, fp)); 715 #endif 716 } 717 head = head->next; 718 } 719 PetscFunctionReturn(0); 720 } 721 722 /*@ 723 PetscMallocViewSet - Activates logging of all calls to PetscMalloc() with a minimum size to view 724 725 Not Collective 726 727 Input Parameter: 728 . logmin - minimum allocation size to log, or PETSC_DEFAULT 729 730 Options Database Key: 731 + -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize() 732 . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used 733 - -log_view_memory - view the memory usage also with the -log_view option 734 735 Level: advanced 736 737 Notes: Must be called after PetscMallocSetDebug() 738 739 Uses MPI_COMM_WORLD to determine rank because PETSc communicators may not be available 740 741 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()` 742 @*/ 743 PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) { 744 PetscFunctionBegin; 745 PetscLogMalloc = 0; 746 PetscCall(PetscMemorySetGetMaximumUsage()); 747 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 748 PetscLogMallocThreshold = (size_t)logmin; 749 PetscFunctionReturn(0); 750 } 751 752 /*@ 753 PetscMallocViewGet - Determine whether all calls to PetscMalloc() are being logged 754 755 Not Collective 756 757 Output Parameter 758 . logging - PETSC_TRUE if logging is active 759 760 Options Database Key: 761 . -malloc_view <optional filename> - Activates PetscMallocView() 762 763 Level: advanced 764 765 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()` 766 @*/ 767 PetscErrorCode PetscMallocViewGet(PetscBool *logging) { 768 PetscFunctionBegin; 769 *logging = (PetscBool)(PetscLogMalloc >= 0); 770 PetscFunctionReturn(0); 771 } 772 773 /*@ 774 PetscMallocTraceSet - Trace all calls to PetscMalloc() 775 776 Not Collective 777 778 Input Parameters: 779 + viewer - The viewer to use for tracing, or NULL to use stdout 780 . active - Flag to activate or deactivate tracing 781 - logmin - The smallest memory size that will be logged 782 783 Note: 784 The viewer should not be collective. 785 786 Level: advanced 787 788 .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()` 789 @*/ 790 PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) { 791 PetscFunctionBegin; 792 if (!active) { 793 PetscLogMallocTrace = -1; 794 PetscFunctionReturn(0); 795 } 796 PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer; 797 PetscLogMallocTrace = 0; 798 PetscCall(PetscMemorySetGetMaximumUsage()); 799 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 800 PetscLogMallocTraceThreshold = (size_t)logmin; 801 PetscFunctionReturn(0); 802 } 803 804 /*@ 805 PetscMallocTraceGet - Determine whether all calls to PetscMalloc() are being traced 806 807 Not Collective 808 809 Output Parameter: 810 . logging - PETSC_TRUE if logging is active 811 812 Options Database Key: 813 . -malloc_view <optional filename> - Activates PetscMallocView() 814 815 Level: advanced 816 817 .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()` 818 @*/ 819 PetscErrorCode PetscMallocTraceGet(PetscBool *logging) { 820 PetscFunctionBegin; 821 *logging = (PetscBool)(PetscLogMallocTrace >= 0); 822 PetscFunctionReturn(0); 823 } 824 825 /*@C 826 PetscMallocView - Saves the log of all calls to PetscMalloc(); also calls 827 PetscMemoryGetMaximumUsage() 828 829 Not Collective 830 831 Input Parameter: 832 . fp - file pointer; or NULL 833 834 Options Database Key: 835 . -malloc_view <optional filename> - Activates PetscMallocView() in PetscFinalize() 836 837 Level: advanced 838 839 Fortran Note: 840 The calling sequence in Fortran is PetscMallocView(integer ierr) 841 The fp defaults to stdout. 842 843 Notes: 844 PetscMallocDump() dumps only the currently unfreed memory, this dumps all memory ever allocated 845 846 PetscMemoryView() gives a brief summary of current memory usage 847 848 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()` 849 @*/ 850 PetscErrorCode PetscMallocView(FILE *fp) { 851 PetscInt i, j, n, *perm; 852 size_t *shortlength; 853 int *shortcount, err; 854 PetscMPIInt rank; 855 PetscBool match; 856 const char **shortfunction; 857 PetscLogDouble rss; 858 859 PetscFunctionBegin; 860 PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 861 err = fflush(fp); 862 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 863 864 PetscCheck(PetscLogMalloc >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "PetscMallocView() called without call to PetscMallocViewSet() this is often due to\n setting the option -malloc_view AFTER PetscInitialize() with PetscOptionsInsert() or PetscOptionsInsertFile()"); 865 866 if (!fp) fp = PETSC_STDOUT; 867 PetscCall(PetscMemoryGetMaximumUsage(&rss)); 868 if (rss) { 869 (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss); 870 } else { 871 (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem); 872 } 873 shortcount = (int *)malloc(PetscLogMalloc * sizeof(int)); 874 PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 875 shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t)); 876 PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 877 shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *)); 878 PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 879 for (i = 0, n = 0; i < PetscLogMalloc; i++) { 880 for (j = 0; j < n; j++) { 881 PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match)); 882 if (match) { 883 shortlength[j] += PetscLogMallocLength[i]; 884 shortcount[j]++; 885 goto foundit; 886 } 887 } 888 shortfunction[n] = PetscLogMallocFunction[i]; 889 shortlength[n] = PetscLogMallocLength[i]; 890 shortcount[n] = 1; 891 n++; 892 foundit:; 893 } 894 895 perm = (PetscInt *)malloc(n * sizeof(PetscInt)); 896 PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 897 for (i = 0; i < n; i++) perm[i] = i; 898 PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm)); 899 900 (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank); 901 for (i = 0; i < n; i++) (void)fprintf(fp, "[%d] %d %.0f %s()\n", rank, shortcount[perm[i]], (PetscLogDouble)shortlength[perm[i]], shortfunction[perm[i]]); 902 free(perm); 903 free(shortlength); 904 free(shortcount); 905 free((char **)shortfunction); 906 err = fflush(fp); 907 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fflush() failed on file"); 908 PetscFunctionReturn(0); 909 } 910 911 /* ---------------------------------------------------------------------------- */ 912 913 /*@ 914 PetscMallocSetDebug - Set's PETSc memory debugging 915 916 Not Collective 917 918 Input Parameters: 919 + eachcall - checks the entire heap of allocated memory for issues on each call to PetscMalloc() and PetscFree() 920 - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays 921 922 Options Database: 923 + -malloc_debug <true or false> - turns on or off debugging 924 . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored 925 . -malloc_view_threshold t - log only allocations larger than t 926 . -malloc_dump <filename> - print a list of all memory that has not been freed 927 . -malloc no - (deprecated) same as -malloc_debug no 928 - -malloc_log - (deprecated) same as -malloc_view 929 930 Level: developer 931 932 Notes: This is called in PetscInitialize() and should not be called elsewhere 933 934 .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()` 935 @*/ 936 PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) { 937 PetscFunctionBegin; 938 PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()"); 939 PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault)); 940 941 TRallocated = 0; 942 TRfrags = 0; 943 TRhead = NULL; 944 TRid = 0; 945 TRdebugLevel = eachcall; 946 TRMaxMem = 0; 947 PetscLogMallocMax = 10000; 948 PetscLogMalloc = -1; 949 TRdebugIinitializenan = initializenan; 950 PetscFunctionReturn(0); 951 } 952 953 /*@ 954 PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing. 955 956 Not Collective 957 958 Output Parameters: 959 + basic - doing basic debugging 960 . eachcall - checks the entire memory heap at each PetscMalloc()/PetscFree() 961 - initializenan - initializes memory with NaN 962 963 Level: intermediate 964 965 Notes: 966 By default, the debug version always does some debugging unless you run with -malloc_debug no 967 968 .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()` 969 @*/ 970 PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) { 971 PetscFunctionBegin; 972 if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE; 973 if (eachcall) *eachcall = TRdebugLevel; 974 if (initializenan) *initializenan = TRdebugIinitializenan; 975 PetscFunctionReturn(0); 976 } 977 978 /*@ 979 PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size 980 981 Not Collective 982 983 Input Parameter: 984 . flg - PETSC_TRUE to log the requested memory size 985 986 Options Database: 987 . -malloc_requested_size <bool> - Sets this flag 988 989 Level: developer 990 991 .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()` 992 @*/ 993 PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) { 994 PetscFunctionBegin; 995 TRrequestedSize = flg; 996 PetscFunctionReturn(0); 997 } 998 999 /*@ 1000 PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size 1001 1002 Not Collective 1003 1004 Output Parameter: 1005 . flg - PETSC_TRUE if we log the requested memory size 1006 1007 Level: developer 1008 1009 .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()` 1010 @*/ 1011 PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) { 1012 PetscFunctionBegin; 1013 *flg = TRrequestedSize; 1014 PetscFunctionReturn(0); 1015 } 1016