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