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