1 #include <petsc/private/petscimpl.h> 2 3 static PetscInt petsc_checkpointer_intensity = 1; 4 5 /*@ 6 PetscCheckPointerSetIntensity - Set the intensity of debug pointer checks 7 8 Not Collective 9 10 Input Parameter: 11 . intensity - how much to check pointers for validity 12 13 Options Database Key: 14 . -check_pointer_intensity - intensity (0, 1, or 2) 15 16 Level: advanced 17 18 Notes: 19 An intense pointer check registers a signal handler and attempts to dereference to confirm 20 whether the address is valid. An intensity of 0 never uses signal handlers, 1 uses them when 21 not in a "hot" function, and intensity of 2 always uses a signal handler. 22 23 .seealso: `PetscCheckPointer()`, `PetscFunctionBeginHot()` 24 @*/ 25 PetscErrorCode PetscCheckPointerSetIntensity(PetscInt intensity) 26 { 27 PetscFunctionBegin; 28 PetscCheck((intensity >= 0) && (intensity <= 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Intensity %" PetscInt_FMT " not in [0,2]", intensity); 29 petsc_checkpointer_intensity = intensity; 30 PetscFunctionReturn(PETSC_SUCCESS); 31 } 32 33 #if PetscDefined(HAVE_SETJMP_H) 34 #include <setjmp.h> 35 static jmp_buf PetscSegvJumpBuf; 36 static PetscBool PetscSegvJumpBuf_set; 37 38 /*@C 39 PetscSignalSegvCheckPointerOrMpi - To be called from a signal handler for SIGSEGV. 40 41 Not Collective, No Fortran Support 42 43 Level: developer 44 45 Note: 46 If the signal was received while executing `PetscCheckPointer()`, this function longjmps back 47 there, otherwise it returns with no effect. This function is called automatically by 48 `PetscSignalHandlerDefault()`. 49 50 .seealso: `PetscPushSignalHandler()` 51 @*/ 52 void PetscSignalSegvCheckPointerOrMpi(void) 53 { 54 if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf, 1); 55 } 56 57 /*@C 58 PetscCheckPointer - Returns `PETSC_TRUE` if a pointer points to accessible data 59 60 Not Collective, No Fortran Support 61 62 Input Parameters: 63 + ptr - the pointer 64 - dtype - the type of data the pointer is suppose to point to 65 66 Level: developer 67 68 Notes: 69 This is a non-standard PETSc function in that it returns the result and does not return an error code. 70 71 This function always returns true when running under Valgrind, or when compiled with asan options. 72 73 .seealso: `PetscCheckPointerSetIntensity()` 74 @*/ 75 PetscBool PetscCheckPointer(const void *ptr, PetscDataType dtype) 76 { 77 if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE; 78 if (!ptr) return PETSC_FALSE; 79 if (petsc_checkpointer_intensity < 1) return PETSC_TRUE; 80 if (PetscDefined(HAVE_SANITIZER)) return PETSC_TRUE; 81 82 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY) 83 /* Skip the verbose check if we are inside a hot function. */ 84 if (petscstack.hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE; 85 #endif 86 87 PetscSegvJumpBuf_set = PETSC_TRUE; 88 89 if (setjmp(PetscSegvJumpBuf)) { 90 /* A segv was triggered in the code below hence we return with an error code */ 91 PetscSegvJumpBuf_set = PETSC_FALSE; 92 return PETSC_FALSE; 93 } else { 94 switch (dtype) { 95 case PETSC_INT: { 96 PETSC_UNUSED PetscInt x = *(volatile PetscInt *)ptr; 97 break; 98 } 99 #if defined(PETSC_USE_COMPLEX) 100 case PETSC_SCALAR: { /* C++ is seriously dysfunctional with volatile std::complex. */ 101 #if defined(PETSC_USE_CXXCOMPLEX) 102 PetscReal xreal = ((volatile PetscReal *)ptr)[0], ximag = ((volatile PetscReal *)ptr)[1]; 103 PETSC_UNUSED volatile PetscScalar x = xreal + PETSC_i * ximag; 104 #else 105 PETSC_UNUSED PetscScalar x = *(volatile PetscScalar *)ptr; 106 #endif 107 break; 108 } 109 #endif 110 case PETSC_REAL: { 111 PETSC_UNUSED PetscReal x = *(volatile PetscReal *)ptr; 112 break; 113 } 114 case PETSC_BOOL: { 115 PETSC_UNUSED PetscBool x = *(volatile PetscBool *)ptr; 116 break; 117 } 118 case PETSC_ENUM: { 119 PETSC_UNUSED PetscEnum x = *(volatile PetscEnum *)ptr; 120 break; 121 } 122 case PETSC_CHAR: { 123 PETSC_UNUSED char x = *(volatile char *)ptr; 124 break; 125 } 126 case PETSC_OBJECT: { 127 PETSC_UNUSED volatile PetscClassId classid = ((PetscObject)ptr)->classid; 128 break; 129 } 130 default:; 131 } 132 } 133 PetscSegvJumpBuf_set = PETSC_FALSE; 134 return PETSC_TRUE; 135 } 136 #endif 137