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) && !defined(PETSC_HAVE_THREADSAFETY) 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 PETSC_SUCCESS; 114 head = TRhead; 115 lasthead = NULL; 116 if (head && head->prev) { 117 PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 118 PetscCall((*PetscErrorPrintf)("Root memory header %p has invalid back pointer %p\n", (void *)head, (void *)head->prev)); 119 return PETSC_ERR_MEMC; 120 } 121 while (head) { 122 if (head->classid != CLASSID_VALUE) { 123 PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 124 PetscCall((*PetscErrorPrintf)("Memory at address %p is corrupted\n", (void *)head)); 125 PetscCall((*PetscErrorPrintf)("Probably write before beginning of or past end of array\n")); 126 if (lasthead) { 127 a = (char *)(((TrSPACE *)head) + 1); 128 PetscCall((*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 PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 137 if (*nend == ALREADY_FREED) { 138 PetscCall((*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 PetscCall((*PetscErrorPrintf)("Memory [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a)); 142 PetscCall((*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 PetscCall((*PetscErrorPrintf)("PetscMallocValidate: error detected in %s() at %s:%d\n", function, file, line)); 148 PetscCall((*PetscErrorPrintf)("Backpointer %p is invalid, should be %p\n", (void *)head->prev, (void *)lasthead)); 149 PetscCall((*PetscErrorPrintf)("Previous memory originally allocated in %s() at %s:%d\n", lasthead->functionname, lasthead->filename, lasthead->lineno)); 150 PetscCall((*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 PETSC_SUCCESS; 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(PETSC_SUCCESS); 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) && !defined(PETSC_HAVE_THREADSAFETY) 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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 PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 286 PetscCall((*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 PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 293 PetscCall((*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 PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 296 } else { 297 PetscCall((*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 PetscCall((*PetscErrorPrintf)("PetscTrFreeDefault() called from %s() at %s:%d\n", function, filename, lineno)); 303 PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a)); 304 PetscCall((*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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 363 } 364 /* If the original space was NULL just use the regular malloc() */ 365 if (!*result) { 366 PetscCall(PetscTrMallocDefault(len, PETSC_FALSE, lineno, function, filename, result)); 367 PetscFunctionReturn(PETSC_SUCCESS); 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 PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 379 PetscCall((*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 PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 386 PetscCall((*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 PetscCall((*PetscErrorPrintf)("Block freed in %s() at %s:%d\n", head->functionname, head->filename, head->lineno)); 389 } else { 390 PetscCall((*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 PetscCall((*PetscErrorPrintf)("PetscTrReallocDefault() called from %s() at %s:%d\n", function, filename, lineno)); 396 PetscCall((*PetscErrorPrintf)("Block [id=%d(%.0f)] at address %p is corrupted (probably write past end of array)\n", head->id, (PetscLogDouble)head->size, a)); 397 PetscCall((*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) && !defined(PETSC_HAVE_THREADSAFETY) 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(PETSC_SUCCESS); 466 } 467 468 /*@C 469 PetscMemoryView - Shows the amount of memory currently being used in a communicator. 470 471 Collective 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 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(PETSC_SUCCESS); 609 TRMaxMems[NumTRMaxMems - 1] = TRallocated; 610 TRMaxMemsEvents[NumTRMaxMems - 1] = event; 611 PetscFunctionReturn(PETSC_SUCCESS); 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(PETSC_SUCCESS); 635 PetscCheck(TRMaxMemsEvents[NumTRMaxMems] == event, PETSC_COMM_SELF, PETSC_ERR_MEMC, "PetscMallocPush/PopMaximumUsage() are not nested"); 636 *mu = TRMaxMems[NumTRMaxMems]; 637 PetscFunctionReturn(PETSC_SUCCESS); 638 } 639 640 /*@C 641 PetscMallocGetStack - returns a pointer to the stack for the location in the program a call to `PetscMalloc()` was used to obtain that memory 642 643 Collective on `PETSC_COMM_WORLD` 644 645 Input Parameter: 646 . ptr - the memory location 647 648 Output Parameter: 649 . stack - the stack indicating where the program allocated this memory 650 651 Level: intermediate 652 653 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()` 654 @*/ 655 PetscErrorCode PetscMallocGetStack(void *ptr, PetscStack **stack) 656 { 657 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 658 TRSPACE *head; 659 660 PetscFunctionBegin; 661 head = (TRSPACE *)(((char *)ptr) - HEADER_BYTES); 662 *stack = &head->stack; 663 PetscFunctionReturn(PETSC_SUCCESS); 664 #else 665 *stack = NULL; 666 return PETSC_SUCCESS; 667 #endif 668 } 669 670 /*@C 671 PetscMallocDump - Dumps the currently allocated memory blocks to a file. The information 672 printed is: size of space (in bytes), address of space, id of space, 673 file in which space was allocated, and line number at which it was 674 allocated. 675 676 Not Collective 677 678 Input Parameter: 679 . fp - file pointer. If fp is NULL, stdout is assumed. 680 681 Options Database Key: 682 . -malloc_dump <optional filename> - Dumps unfreed memory during call to `PetscFinalize()` 683 684 Level: intermediate 685 686 Fortran Note: 687 The calling sequence in Fortran is PetscMallocDump(integer ierr) 688 The fp defaults to stdout. 689 690 Notes: 691 Uses `MPI_COMM_WORLD` to display rank, because this may be called in `PetscFinalize()` after `PETSC_COMM_WORLD` has been freed. 692 693 When called in `PetscFinalize()` dumps only the allocations that have not been properly freed 694 695 `PetscMallocView()` prints a list of all memory ever allocated 696 697 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocValidate()` 698 @*/ 699 PetscErrorCode PetscMallocDump(FILE *fp) 700 { 701 TRSPACE *head; 702 size_t libAlloc = 0; 703 PetscMPIInt rank; 704 705 PetscFunctionBegin; 706 PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 707 if (!fp) fp = PETSC_STDOUT; 708 head = TRhead; 709 while (head) { 710 libAlloc += TRrequestedSize ? head->rsize : head->size; 711 head = head->next; 712 } 713 if (TRallocated - libAlloc > 0) fprintf(fp, "[%d]Total space allocated %.0f bytes\n", rank, (PetscLogDouble)TRallocated); 714 head = TRhead; 715 while (head) { 716 PetscBool isLib; 717 718 PetscCall(PetscStrcmp(head->functionname, "PetscDLLibraryOpen", &isLib)); 719 if (!isLib) { 720 fprintf(fp, "[%2d] %.0f bytes %s() at %s:%d\n", rank, (PetscLogDouble)(TRrequestedSize ? head->rsize : head->size), head->functionname, head->filename, head->lineno); 721 #if defined(PETSC_USE_DEBUG) && !defined(PETSC_HAVE_THREADSAFETY) 722 PetscCall(PetscStackPrint(&head->stack, fp)); 723 #endif 724 } 725 head = head->next; 726 } 727 PetscFunctionReturn(PETSC_SUCCESS); 728 } 729 730 /*@ 731 PetscMallocViewSet - Activates logging of all calls to `PetscMalloc()` with a minimum size to view 732 733 Not Collective 734 735 Input Parameter: 736 . logmin - minimum allocation size to log, or `PETSC_DEFAULT` 737 738 Options Database Key: 739 + -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 740 . -malloc_view_threshold <min> - Sets a minimum size if -malloc_view is used 741 - -log_view_memory - view the memory usage also with the -log_view option 742 743 Level: advanced 744 745 Notes: 746 Must be called after `PetscMallocSetDebug()` 747 748 Uses `MPI_COMM_WORLD` to determine rank because PETSc communicators may not be available 749 750 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocViewSet()`, `PetscMallocTraceSet()`, `PetscMallocValidate()` 751 @*/ 752 PetscErrorCode PetscMallocViewSet(PetscLogDouble logmin) 753 { 754 PetscFunctionBegin; 755 PetscLogMalloc = 0; 756 PetscCall(PetscMemorySetGetMaximumUsage()); 757 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 758 PetscLogMallocThreshold = (size_t)logmin; 759 PetscFunctionReturn(PETSC_SUCCESS); 760 } 761 762 /*@ 763 PetscMallocViewGet - Determine whether calls to `PetscMalloc()` are being logged 764 765 Not Collective 766 767 Output Parameter 768 . logging - `PETSC_TRUE` if logging is active 769 770 Options Database Key: 771 . -malloc_view <optional filename> - Activates `PetscMallocView()` 772 773 Level: advanced 774 775 .seealso: `PetscMallocDump()`, `PetscMallocView()`, `PetscMallocTraceGet()` 776 @*/ 777 PetscErrorCode PetscMallocViewGet(PetscBool *logging) 778 { 779 PetscFunctionBegin; 780 *logging = (PetscBool)(PetscLogMalloc >= 0); 781 PetscFunctionReturn(PETSC_SUCCESS); 782 } 783 784 /*@ 785 PetscMallocTraceSet - Trace all calls to `PetscMalloc()` 786 787 Not Collective 788 789 Input Parameters: 790 + viewer - The viewer to use for tracing, or NULL to use stdout 791 . active - Flag to activate or deactivate tracing 792 - logmin - The smallest memory size that will be logged 793 794 Note: 795 The viewer should not be collective. 796 797 Level: advanced 798 799 .seealso: `PetscMallocTraceGet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()` 800 @*/ 801 PetscErrorCode PetscMallocTraceSet(PetscViewer viewer, PetscBool active, PetscLogDouble logmin) 802 { 803 PetscFunctionBegin; 804 if (!active) { 805 PetscLogMallocTrace = -1; 806 PetscFunctionReturn(PETSC_SUCCESS); 807 } 808 PetscLogMallocTraceViewer = !viewer ? PETSC_VIEWER_STDOUT_SELF : viewer; 809 PetscLogMallocTrace = 0; 810 PetscCall(PetscMemorySetGetMaximumUsage()); 811 if (logmin < 0) logmin = 0.0; /* PETSC_DEFAULT or PETSC_DECIDE */ 812 PetscLogMallocTraceThreshold = (size_t)logmin; 813 PetscFunctionReturn(PETSC_SUCCESS); 814 } 815 816 /*@ 817 PetscMallocTraceGet - Determine whether all calls to `PetscMalloc()` are being traced 818 819 Not Collective 820 821 Output Parameter: 822 . logging - `PETSC_TRUE` if logging is active 823 824 Options Database Key: 825 . -malloc_view <optional filename> - Activates PetscMallocView() 826 827 Level: advanced 828 829 .seealso: `PetscMallocTraceSet()`, `PetscMallocViewGet()`, `PetscMallocDump()`, `PetscMallocView()` 830 @*/ 831 PetscErrorCode PetscMallocTraceGet(PetscBool *logging) 832 { 833 PetscFunctionBegin; 834 *logging = (PetscBool)(PetscLogMallocTrace >= 0); 835 PetscFunctionReturn(PETSC_SUCCESS); 836 } 837 838 /*@C 839 PetscMallocView - Saves the log of all calls to `PetscMalloc()`; also calls 840 `PetscMemoryGetMaximumUsage()` 841 842 Not Collective 843 844 Input Parameter: 845 . fp - file pointer; or NULL 846 847 Options Database Key: 848 . -malloc_view <optional filename> - Activates `PetscMallocView()` in `PetscFinalize()` 849 850 Level: advanced 851 852 Fortran Note: 853 The calling sequence in Fortran is PetscMallocView(integer ierr) 854 The fp defaults to stdout. 855 856 Notes: 857 `PetscMallocDump()` dumps only the currently unfreed memory, this dumps all memory ever allocated 858 859 `PetscMemoryView()` gives a brief summary of current memory usage 860 861 .seealso: `PetscMallocGetCurrentUsage()`, `PetscMallocDump()`, `PetscMallocViewSet()`, `PetscMemoryView()` 862 @*/ 863 PetscErrorCode PetscMallocView(FILE *fp) 864 { 865 PetscInt i, j, n, *perm; 866 size_t *shortlength; 867 int *shortcount; 868 PetscMPIInt rank; 869 PetscBool match; 870 const char **shortfunction; 871 PetscLogDouble rss; 872 873 PetscFunctionBegin; 874 PetscCallMPI(MPI_Comm_rank(MPI_COMM_WORLD, &rank)); 875 PetscCall(PetscFFlush(fp)); 876 877 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()"); 878 879 if (!fp) fp = PETSC_STDOUT; 880 PetscCall(PetscMemoryGetMaximumUsage(&rss)); 881 if (rss) { 882 (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f maximum size of entire process %.0f\n", rank, (PetscLogDouble)TRMaxMem, rss); 883 } else { 884 (void)fprintf(fp, "[%d] Maximum memory PetscMalloc()ed %.0f OS cannot compute size of entire process\n", rank, (PetscLogDouble)TRMaxMem); 885 } 886 if (PetscLogMalloc > 0) { 887 shortcount = (int *)malloc(PetscLogMalloc * sizeof(int)); 888 PetscCheck(shortcount, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 889 shortlength = (size_t *)malloc(PetscLogMalloc * sizeof(size_t)); 890 PetscCheck(shortlength, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 891 shortfunction = (const char **)malloc(PetscLogMalloc * sizeof(char *)); 892 PetscCheck(shortfunction, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 893 for (i = 0, n = 0; i < PetscLogMalloc; i++) { 894 for (j = 0; j < n; j++) { 895 PetscCall(PetscStrcmp(shortfunction[j], PetscLogMallocFunction[i], &match)); 896 if (match) { 897 shortlength[j] += PetscLogMallocLength[i]; 898 shortcount[j]++; 899 goto foundit; 900 } 901 } 902 shortfunction[n] = PetscLogMallocFunction[i]; 903 shortlength[n] = PetscLogMallocLength[i]; 904 shortcount[n] = 1; 905 n++; 906 foundit:; 907 } 908 909 perm = (PetscInt *)malloc(n * sizeof(PetscInt)); 910 PetscCheck(perm, PETSC_COMM_SELF, PETSC_ERR_MEM, "Out of memory"); 911 for (i = 0; i < n; i++) perm[i] = i; 912 PetscCall(PetscSortStrWithPermutation(n, (const char **)shortfunction, perm)); 913 914 (void)fprintf(fp, "[%d] Memory usage sorted by function\n", rank); 915 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]]); 916 free(perm); 917 free(shortlength); 918 free(shortcount); 919 free((char **)shortfunction); 920 } 921 PetscCall(PetscFFlush(fp)); 922 PetscFunctionReturn(PETSC_SUCCESS); 923 } 924 925 /* ---------------------------------------------------------------------------- */ 926 927 /*@ 928 PetscMallocSetDebug - Set's PETSc memory debugging 929 930 Not Collective 931 932 Input Parameters: 933 + eachcall - checks the entire heap of allocated memory for issues on each call to `PetscMalloc()` and `PetscFree()`, slow 934 - initializenan - initializes all memory with NaN to catch use of uninitialized floating point arrays 935 936 Options Database Keys: 937 + -malloc_debug <true or false> - turns on or off debugging 938 . -malloc_test - turns on all debugging if PETSc was configured with debugging including -malloc_dump, otherwise ignored 939 . -malloc_view_threshold t - log only allocations larger than t 940 . -malloc_dump <filename> - print a list of all memory that has not been freed 941 . -malloc no - (deprecated) same as -malloc_debug no 942 - -malloc_log - (deprecated) same as -malloc_view 943 944 Level: developer 945 946 Note: 947 This is called in `PetscInitialize()` and should not be called elsewhere 948 949 .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocGetDebug()` 950 @*/ 951 PetscErrorCode PetscMallocSetDebug(PetscBool eachcall, PetscBool initializenan) 952 { 953 PetscFunctionBegin; 954 PetscCheck(PetscTrMalloc != PetscTrMallocDefault, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot call this routine more than once, it can only be called in PetscInitialize()"); 955 PetscCall(PetscMallocSet(PetscTrMallocDefault, PetscTrFreeDefault, PetscTrReallocDefault)); 956 957 TRallocated = 0; 958 TRfrags = 0; 959 TRhead = NULL; 960 TRid = 0; 961 TRdebugLevel = eachcall; 962 TRMaxMem = 0; 963 PetscLogMallocMax = 10000; 964 PetscLogMalloc = -1; 965 TRdebugIinitializenan = initializenan; 966 PetscFunctionReturn(PETSC_SUCCESS); 967 } 968 969 /*@ 970 PetscMallocGetDebug - Indicates what PETSc memory debugging it is doing. 971 972 Not Collective 973 974 Output Parameters: 975 + basic - doing basic debugging 976 . eachcall - checks the entire memory heap at each `PetscMalloc()`/`PetscFree()` 977 - initializenan - initializes memory with NaN 978 979 Level: intermediate 980 981 Note: 982 By default, the debug version always does some debugging unless you run with -malloc_debug no 983 984 .seealso: `CHKMEMQ()`, `PetscMallocValidate()`, `PetscMallocSetDebug()` 985 @*/ 986 PetscErrorCode PetscMallocGetDebug(PetscBool *basic, PetscBool *eachcall, PetscBool *initializenan) 987 { 988 PetscFunctionBegin; 989 if (basic) *basic = (PetscTrMalloc == PetscTrMallocDefault) ? PETSC_TRUE : PETSC_FALSE; 990 if (eachcall) *eachcall = TRdebugLevel; 991 if (initializenan) *initializenan = TRdebugIinitializenan; 992 PetscFunctionReturn(PETSC_SUCCESS); 993 } 994 995 /*@ 996 PetscMallocLogRequestedSizeSet - Whether to log the requested or aligned memory size 997 998 Not Collective 999 1000 Input Parameter: 1001 . flg - `PETSC_TRUE` to log the requested memory size 1002 1003 Options Database Key: 1004 . -malloc_requested_size <bool> - Sets this flag 1005 1006 Level: developer 1007 1008 .seealso: `PetscMallocLogRequestedSizeGet()`, `PetscMallocViewSet()` 1009 @*/ 1010 PetscErrorCode PetscMallocLogRequestedSizeSet(PetscBool flg) 1011 { 1012 PetscFunctionBegin; 1013 TRrequestedSize = flg; 1014 PetscFunctionReturn(PETSC_SUCCESS); 1015 } 1016 1017 /*@ 1018 PetscMallocLogRequestedSizeGet - Whether to log the requested or aligned memory size 1019 1020 Not Collective 1021 1022 Output Parameter: 1023 . flg - `PETSC_TRUE` if we log the requested memory size 1024 1025 Level: developer 1026 1027 .seealso: `PetscMallocLogRequestedSizeSetinalSizeSet()`, `PetscMallocViewSet()` 1028 @*/ 1029 PetscErrorCode PetscMallocLogRequestedSizeGet(PetscBool *flg) 1030 { 1031 PetscFunctionBegin; 1032 *flg = TRrequestedSize; 1033 PetscFunctionReturn(PETSC_SUCCESS); 1034 } 1035