xref: /petsc/src/sys/error/checkptr.c (revision 73fdd05bb67e49f40fd8fd311695ff6fdf0b9b8a)
1 #include <petsc/private/petscimpl.h>
2 
3 static PetscInt petsc_checkpointer_intensity = 1;
4 
5 /*@
6    PetscCheckPointerSetIntensity - An intense pointer check registers a signal handler and attempts to dereference to
7    confirm whether the address is valid.  An intensity of 0 never uses signal handlers, 1 uses them when not in a "hot"
8    function, and intensity of 2 always uses a signal handler.
9 
10    Not Collective
11 
12    Input Parameter:
13 .  intensity - how much to check pointers for validity
14 
15    Options Database Key:
16 .  -check_pointer_intensity - intensity (0, 1, or 2)
17 
18    Level: advanced
19 
20 .seealso: `PetscCheckPointer()`, `PetscFunctionBeginHot()`
21 @*/
22 PetscErrorCode PetscCheckPointerSetIntensity(PetscInt intensity)
23 {
24   PetscFunctionBegin;
25   PetscCheck((intensity >= 0) && (intensity <= 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Intensity %" PetscInt_FMT " not in [0,2]", intensity);
26   petsc_checkpointer_intensity = intensity;
27   PetscFunctionReturn(PETSC_SUCCESS);
28 }
29 
30 /* ---------------------------------------------------------------------------------------*/
31 
32 #if PetscDefined(HAVE_SETJMP_H)
33   #include <setjmp.h>
34 static jmp_buf   PetscSegvJumpBuf;
35 static PetscBool PetscSegvJumpBuf_set;
36 
37 /*@C
38   PetscSignalSegvCheckPointerOrMpi - To be called from a signal handler for SIGSEGV.
39 
40   Not Collective
41 
42   Notes:
43   If the signal was received while executing PetscCheckPointer(), this function longjmps back
44   there, otherwise returns with no effect. This function is called automatically by
45   PetscSignalHandlerDefault().
46 
47   Level: developer
48 
49 .seealso: `PetscPushSignalHandler()`
50 @*/
51 void PetscSignalSegvCheckPointerOrMpi(void)
52 {
53   if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf, 1);
54 }
55 
56 /*@C
57      PetscCheckPointer - Returns `PETSC_TRUE` if a pointer points to accessible data
58 
59    Not Collective
60 
61    Input Parameters:
62 +     ptr - the pointer
63 -     dtype - the type of data the pointer is suppose to point to
64 
65    Level: developer
66 
67    Note:
68    This is a non-standard PETSc function in that it returns the result as the return code and does not return an error code
69 
70 .seealso: `PetscCheckPointerSetIntensity()`
71 @*/
72 PetscBool PetscCheckPointer(const void *ptr, PetscDataType dtype)
73 {
74   if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE;
75   if (!ptr) return PETSC_FALSE;
76   if (petsc_checkpointer_intensity < 1) return PETSC_TRUE;
77 
78   #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
79   /* Skip the verbose check if we are inside a hot function. */
80   if (petscstack.hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE;
81   #endif
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 #endif
133