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