xref: /petsc/src/sys/error/checkptr.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
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