xref: /petsc/src/sys/error/checkptr.c (revision dfb7d7afc6419f3665b48978fc015eb4d33caed1)
1af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
205035670SJunchao Zhang 
328559dc8SJed Brown static PetscInt petsc_checkpointer_intensity = 1;
428559dc8SJed Brown 
528559dc8SJed Brown /*@
628559dc8SJed Brown    PetscCheckPointerSetIntensity - An intense pointer check registers a signal handler and attempts to dereference to
728559dc8SJed Brown    confirm whether the address is valid.  An intensity of 0 never uses signal handlers, 1 uses them when not in a "hot"
828559dc8SJed Brown    function, and intensity of 2 always uses a signal handler.
928559dc8SJed Brown 
1028559dc8SJed Brown    Not Collective
1128559dc8SJed Brown 
124165533cSJose E. Roman    Input Parameter:
1328559dc8SJed Brown .  intensity - how much to check pointers for validity
1428559dc8SJed Brown 
15811af0c4SBarry Smith    Options Database Key:
165789d1f5SJed Brown .  -check_pointer_intensity - intensity (0, 1, or 2)
17c2f74817SBarry Smith 
1828559dc8SJed Brown    Level: advanced
1928559dc8SJed Brown 
20db781477SPatrick Sanan .seealso: `PetscCheckPointer()`, `PetscFunctionBeginHot()`
2128559dc8SJed Brown @*/
22d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscCheckPointerSetIntensity(PetscInt intensity)
23d71ae5a4SJacob Faibussowitsch {
2428559dc8SJed Brown   PetscFunctionBegin;
250e6b6b59SJacob Faibussowitsch   PetscCheck((intensity >= 0) && (intensity <= 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Intensity %" PetscInt_FMT " not in [0,2]", intensity);
260e6b6b59SJacob Faibussowitsch   petsc_checkpointer_intensity = intensity;
2728559dc8SJed Brown   PetscFunctionReturn(0);
2828559dc8SJed Brown }
2928559dc8SJed Brown 
30d96cc911SJed Brown /* ---------------------------------------------------------------------------------------*/
31718fc407SJed Brown 
320e6b6b59SJacob Faibussowitsch #if PetscDefined(HAVE_SETJMP_H)
33d96cc911SJed Brown   #include <setjmp.h>
34f8a67e6dSJed Brown static jmp_buf   PetscSegvJumpBuf;
35f8a67e6dSJed Brown static PetscBool PetscSegvJumpBuf_set;
36f8a67e6dSJed Brown 
37f8a67e6dSJed Brown /*@C
380e6b6b59SJacob Faibussowitsch   PetscSignalSegvCheckPointerOrMpi - To be called from a signal handler for SIGSEGV.
39f8a67e6dSJed Brown 
40f8a67e6dSJed Brown   Not Collective
41f8a67e6dSJed Brown 
420e6b6b59SJacob Faibussowitsch   Notes:
430e6b6b59SJacob Faibussowitsch   If the signal was received while executing PetscCheckPointer(), this function longjmps back
440e6b6b59SJacob Faibussowitsch   there, otherwise returns with no effect. This function is called automatically by
450e6b6b59SJacob Faibussowitsch   PetscSignalHandlerDefault().
460e6b6b59SJacob Faibussowitsch 
47f8a67e6dSJed Brown   Level: developer
48f8a67e6dSJed Brown 
49db781477SPatrick Sanan .seealso: `PetscPushSignalHandler()`
50f8a67e6dSJed Brown @*/
51d71ae5a4SJacob Faibussowitsch void PetscSignalSegvCheckPointerOrMpi(void)
52d71ae5a4SJacob Faibussowitsch {
53f8a67e6dSJed Brown   if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf, 1);
54f8a67e6dSJed Brown }
55d076d156SJed Brown 
56d96cc911SJed Brown /*@C
57811af0c4SBarry Smith      PetscCheckPointer - Returns `PETSC_TRUE` if a pointer points to accessible data
58d96cc911SJed Brown 
59d96cc911SJed Brown    Not Collective
60d96cc911SJed Brown 
61d96cc911SJed Brown    Input Parameters:
62d96cc911SJed Brown +     ptr - the pointer
63d96cc911SJed Brown -     dtype - the type of data the pointer is suppose to point to
64d96cc911SJed Brown 
65d96cc911SJed Brown    Level: developer
66d96cc911SJed Brown 
67811af0c4SBarry Smith    Note:
68811af0c4SBarry Smith    This is a non-standard PETSc function in that it returns the result as the return code and does not return an error code
69811af0c4SBarry Smith 
70db781477SPatrick Sanan .seealso: `PetscCheckPointerSetIntensity()`
71d96cc911SJed Brown @*/
72d71ae5a4SJacob Faibussowitsch PetscBool PetscCheckPointer(const void *ptr, PetscDataType dtype)
73d71ae5a4SJacob Faibussowitsch {
74d96cc911SJed Brown   if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE;
75d96cc911SJed Brown   if (!ptr) return PETSC_FALSE;
7628559dc8SJed Brown   if (petsc_checkpointer_intensity < 1) return PETSC_TRUE;
77d96cc911SJed Brown 
78*dfb7d7afSStefano Zampini   #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
79a2f94806SJed Brown   /* Skip the verbose check if we are inside a hot function. */
8027104ee2SJacob Faibussowitsch   if (petscstack.hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE;
8127104ee2SJacob Faibussowitsch   #endif
82a2f94806SJed Brown 
83718fc407SJed Brown   PetscSegvJumpBuf_set = PETSC_TRUE;
84d96cc911SJed Brown 
85d96cc911SJed Brown   if (setjmp(PetscSegvJumpBuf)) {
86d96cc911SJed Brown     /* A segv was triggered in the code below hence we return with an error code */
87718fc407SJed Brown     PetscSegvJumpBuf_set = PETSC_FALSE;
88d96cc911SJed Brown     return PETSC_FALSE;
89d96cc911SJed Brown   } else {
90d96cc911SJed Brown     switch (dtype) {
91d96cc911SJed Brown     case PETSC_INT: {
92d96cc911SJed Brown       PETSC_UNUSED PetscInt x = (PetscInt) * (volatile PetscInt *)ptr;
93d96cc911SJed Brown       break;
94d96cc911SJed Brown     }
95d96cc911SJed Brown   #if defined(PETSC_USE_COMPLEX)
96d96cc911SJed Brown     case PETSC_SCALAR: { /* C++ is seriously dysfunctional with volatile std::complex. */
9796d2aba5SSatish Balay     #if defined(PETSC_USE_CXXCOMPLEX)
98d96cc911SJed Brown       PetscReal                         xreal = ((volatile PetscReal *)ptr)[0], ximag = ((volatile PetscReal *)ptr)[1];
99d96cc911SJed Brown       PETSC_UNUSED volatile PetscScalar x = xreal + PETSC_i * ximag;
10096d2aba5SSatish Balay     #else
10196d2aba5SSatish Balay       PETSC_UNUSED PetscScalar x = *(volatile PetscScalar *)ptr;
10296d2aba5SSatish Balay     #endif
103d96cc911SJed Brown       break;
104d96cc911SJed Brown     }
105d96cc911SJed Brown   #endif
106d96cc911SJed Brown     case PETSC_REAL: {
107d96cc911SJed Brown       PETSC_UNUSED PetscReal x = *(volatile PetscReal *)ptr;
108d96cc911SJed Brown       break;
109d96cc911SJed Brown     }
110d96cc911SJed Brown     case PETSC_BOOL: {
111d96cc911SJed Brown       PETSC_UNUSED PetscBool x = *(volatile PetscBool *)ptr;
112d96cc911SJed Brown       break;
113d96cc911SJed Brown     }
114d96cc911SJed Brown     case PETSC_ENUM: {
115d96cc911SJed Brown       PETSC_UNUSED PetscEnum x = *(volatile PetscEnum *)ptr;
116d96cc911SJed Brown       break;
117d96cc911SJed Brown     }
118d96cc911SJed Brown     case PETSC_CHAR: {
119f4e06bcbSJed Brown       PETSC_UNUSED char x = *(volatile char *)ptr;
120d96cc911SJed Brown       break;
121d96cc911SJed Brown     }
122d96cc911SJed Brown     case PETSC_OBJECT: {
123d96cc911SJed Brown       PETSC_UNUSED volatile PetscClassId classid = ((PetscObject)ptr)->classid;
124d96cc911SJed Brown       break;
125d96cc911SJed Brown     }
126d96cc911SJed Brown     default:;
127d96cc911SJed Brown     }
128d96cc911SJed Brown   }
129718fc407SJed Brown   PetscSegvJumpBuf_set = PETSC_FALSE;
130d96cc911SJed Brown   return PETSC_TRUE;
131d96cc911SJed Brown }
13205035670SJunchao Zhang #endif
133