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