xref: /petsc/src/sys/error/checkptr.c (revision 66af8762ec03dbef0e079729eb2a1734a35ed7ff)
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
44 
45   Notes:
46   If the signal was received while executing PetscCheckPointer(), this function longjmps back
47   there, otherwise returns with no effect. This function is called automatically by
48   PetscSignalHandlerDefault().
49 
50   Level: developer
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
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   Note:
71   This is a non-standard PETSc function in that it returns the result as the return code and does not return an error code
72 
73 .seealso: `PetscCheckPointerSetIntensity()`
74 @*/
75 PetscBool PetscCheckPointer(const void *ptr, PetscDataType dtype)
76 {
77   if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE;
78   if (!ptr) return PETSC_FALSE;
79   if (petsc_checkpointer_intensity < 1) return PETSC_TRUE;
80 
81   #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
82   /* Skip the verbose check if we are inside a hot function. */
83   if (petscstack.hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE;
84   #endif
85 
86   PetscSegvJumpBuf_set = PETSC_TRUE;
87 
88   if (setjmp(PetscSegvJumpBuf)) {
89     /* A segv was triggered in the code below hence we return with an error code */
90     PetscSegvJumpBuf_set = PETSC_FALSE;
91     return PETSC_FALSE;
92   } else {
93     switch (dtype) {
94     case PETSC_INT: {
95       PETSC_UNUSED PetscInt x = *(volatile PetscInt *)ptr;
96       break;
97     }
98   #if defined(PETSC_USE_COMPLEX)
99     case PETSC_SCALAR: { /* C++ is seriously dysfunctional with volatile std::complex. */
100     #if defined(PETSC_USE_CXXCOMPLEX)
101       PetscReal                         xreal = ((volatile PetscReal *)ptr)[0], ximag = ((volatile PetscReal *)ptr)[1];
102       PETSC_UNUSED volatile PetscScalar x = xreal + PETSC_i * ximag;
103     #else
104       PETSC_UNUSED PetscScalar x = *(volatile PetscScalar *)ptr;
105     #endif
106       break;
107     }
108   #endif
109     case PETSC_REAL: {
110       PETSC_UNUSED PetscReal x = *(volatile PetscReal *)ptr;
111       break;
112     }
113     case PETSC_BOOL: {
114       PETSC_UNUSED PetscBool x = *(volatile PetscBool *)ptr;
115       break;
116     }
117     case PETSC_ENUM: {
118       PETSC_UNUSED PetscEnum x = *(volatile PetscEnum *)ptr;
119       break;
120     }
121     case PETSC_CHAR: {
122       PETSC_UNUSED char x = *(volatile char *)ptr;
123       break;
124     }
125     case PETSC_OBJECT: {
126       PETSC_UNUSED volatile PetscClassId classid = ((PetscObject)ptr)->classid;
127       break;
128     }
129     default:;
130     }
131   }
132   PetscSegvJumpBuf_set = PETSC_FALSE;
133   return PETSC_TRUE;
134 }
135 #endif
136