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 /* ---------------------------------------------------------------------------------------*/ 34 35 #if PetscDefined(HAVE_SETJMP_H) 36 #include <setjmp.h> 37 static jmp_buf PetscSegvJumpBuf; 38 static PetscBool PetscSegvJumpBuf_set; 39 40 /*@C 41 PetscSignalSegvCheckPointerOrMpi - To be called from a signal handler for SIGSEGV. 42 43 Not Collective, No Fortran Support 44 45 Level: developer 46 47 Note: 48 If the signal was received while executing `PetscCheckPointer()`, this function longjmps back 49 there, otherwise it returns with no effect. This function is called automatically by 50 `PetscSignalHandlerDefault()`. 51 52 .seealso: `PetscPushSignalHandler()` 53 @*/ 54 void PetscSignalSegvCheckPointerOrMpi(void) 55 { 56 if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf, 1); 57 } 58 59 /*@C 60 PetscCheckPointer - Returns `PETSC_TRUE` if a pointer points to accessible data 61 62 Not Collective, No Fortran Support 63 64 Input Parameters: 65 + ptr - the pointer 66 - dtype - the type of data the pointer is suppose to point to 67 68 Level: developer 69 70 Notes: 71 This is a non-standard PETSc function in that it returns the result and does not return an error code. 72 73 This function always returns true when running under Valgrind, or when compiled with asan options. 74 75 .seealso: `PetscCheckPointerSetIntensity()` 76 @*/ 77 PetscBool PetscCheckPointer(const void *ptr, PetscDataType dtype) 78 { 79 if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE; 80 if (!ptr) return PETSC_FALSE; 81 if (petsc_checkpointer_intensity < 1) return PETSC_TRUE; 82 if (PetscDefined(HAVE_SANITIZER)) return PETSC_TRUE; 83 84 #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY) 85 /* Skip the verbose check if we are inside a hot function. */ 86 if (petscstack.hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE; 87 #endif 88 89 PetscSegvJumpBuf_set = PETSC_TRUE; 90 91 if (setjmp(PetscSegvJumpBuf)) { 92 /* A segv was triggered in the code below hence we return with an error code */ 93 PetscSegvJumpBuf_set = PETSC_FALSE; 94 return PETSC_FALSE; 95 } else { 96 switch (dtype) { 97 case PETSC_INT: { 98 PETSC_UNUSED PetscInt x = *(volatile PetscInt *)ptr; 99 break; 100 } 101 #if defined(PETSC_USE_COMPLEX) 102 case PETSC_SCALAR: { /* C++ is seriously dysfunctional with volatile std::complex. */ 103 #if defined(PETSC_USE_CXXCOMPLEX) 104 PetscReal xreal = ((volatile PetscReal *)ptr)[0], ximag = ((volatile PetscReal *)ptr)[1]; 105 PETSC_UNUSED volatile PetscScalar x = xreal + PETSC_i * ximag; 106 #else 107 PETSC_UNUSED PetscScalar x = *(volatile PetscScalar *)ptr; 108 #endif 109 break; 110 } 111 #endif 112 case PETSC_REAL: { 113 PETSC_UNUSED PetscReal x = *(volatile PetscReal *)ptr; 114 break; 115 } 116 case PETSC_BOOL: { 117 PETSC_UNUSED PetscBool x = *(volatile PetscBool *)ptr; 118 break; 119 } 120 case PETSC_ENUM: { 121 PETSC_UNUSED PetscEnum x = *(volatile PetscEnum *)ptr; 122 break; 123 } 124 case PETSC_CHAR: { 125 PETSC_UNUSED char x = *(volatile char *)ptr; 126 break; 127 } 128 case PETSC_OBJECT: { 129 PETSC_UNUSED volatile PetscClassId classid = ((PetscObject)ptr)->classid; 130 break; 131 } 132 default:; 133 } 134 } 135 PetscSegvJumpBuf_set = PETSC_FALSE; 136 return PETSC_TRUE; 137 } 138 #endif 139