xref: /petsc/src/sys/error/checkptr.c (revision 7a2f837dfb5b1b0a1e6bb2716a3d28bcaab1482d)
1af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
205035670SJunchao Zhang 
328559dc8SJed Brown static PetscInt petsc_checkpointer_intensity = 1;
428559dc8SJed Brown 
528559dc8SJed Brown /*@
610450e9eSJacob Faibussowitsch   PetscCheckPointerSetIntensity - Set the intensity of debug pointer checks
728559dc8SJed Brown 
828559dc8SJed Brown   Not Collective
928559dc8SJed Brown 
104165533cSJose E. Roman   Input Parameter:
1128559dc8SJed Brown . intensity - how much to check pointers for validity
1228559dc8SJed Brown 
13811af0c4SBarry Smith   Options Database Key:
145789d1f5SJed Brown . -check_pointer_intensity - intensity (0, 1, or 2)
15c2f74817SBarry Smith 
1628559dc8SJed Brown   Level: advanced
1728559dc8SJed Brown 
1810450e9eSJacob Faibussowitsch   Notes:
1910450e9eSJacob Faibussowitsch   An intense pointer check registers a signal handler and attempts to dereference to confirm
2010450e9eSJacob Faibussowitsch   whether the address is valid.  An intensity of 0 never uses signal handlers, 1 uses them when
2110450e9eSJacob Faibussowitsch   not in a "hot" function, and intensity of 2 always uses a signal handler.
2210450e9eSJacob Faibussowitsch 
23db781477SPatrick Sanan .seealso: `PetscCheckPointer()`, `PetscFunctionBeginHot()`
2428559dc8SJed Brown @*/
25d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscCheckPointerSetIntensity(PetscInt intensity)
26d71ae5a4SJacob Faibussowitsch {
2728559dc8SJed Brown   PetscFunctionBegin;
280e6b6b59SJacob Faibussowitsch   PetscCheck((intensity >= 0) && (intensity <= 2), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Intensity %" PetscInt_FMT " not in [0,2]", intensity);
290e6b6b59SJacob Faibussowitsch   petsc_checkpointer_intensity = intensity;
303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3128559dc8SJed Brown }
3228559dc8SJed Brown 
33d96cc911SJed Brown /* ---------------------------------------------------------------------------------------*/
34718fc407SJed Brown 
350e6b6b59SJacob Faibussowitsch #if PetscDefined(HAVE_SETJMP_H)
36d96cc911SJed Brown   #include <setjmp.h>
37f8a67e6dSJed Brown static jmp_buf   PetscSegvJumpBuf;
38f8a67e6dSJed Brown static PetscBool PetscSegvJumpBuf_set;
39f8a67e6dSJed Brown 
40f8a67e6dSJed Brown /*@C
410e6b6b59SJacob Faibussowitsch   PetscSignalSegvCheckPointerOrMpi - To be called from a signal handler for SIGSEGV.
42f8a67e6dSJed Brown 
43f8a67e6dSJed Brown   Not Collective
44f8a67e6dSJed Brown 
450e6b6b59SJacob Faibussowitsch   Notes:
460e6b6b59SJacob Faibussowitsch   If the signal was received while executing PetscCheckPointer(), this function longjmps back
470e6b6b59SJacob Faibussowitsch   there, otherwise returns with no effect. This function is called automatically by
480e6b6b59SJacob Faibussowitsch   PetscSignalHandlerDefault().
490e6b6b59SJacob Faibussowitsch 
50f8a67e6dSJed Brown   Level: developer
51f8a67e6dSJed Brown 
52db781477SPatrick Sanan .seealso: `PetscPushSignalHandler()`
53f8a67e6dSJed Brown @*/
54d71ae5a4SJacob Faibussowitsch void PetscSignalSegvCheckPointerOrMpi(void)
55d71ae5a4SJacob Faibussowitsch {
56f8a67e6dSJed Brown   if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf, 1);
57f8a67e6dSJed Brown }
58d076d156SJed Brown 
59d96cc911SJed Brown /*@C
60811af0c4SBarry Smith   PetscCheckPointer - Returns `PETSC_TRUE` if a pointer points to accessible data
61d96cc911SJed Brown 
62d96cc911SJed Brown   Not Collective
63d96cc911SJed Brown 
64d96cc911SJed Brown   Input Parameters:
65d96cc911SJed Brown + ptr   - the pointer
66d96cc911SJed Brown - dtype - the type of data the pointer is suppose to point to
67d96cc911SJed Brown 
68d96cc911SJed Brown   Level: developer
69d96cc911SJed Brown 
70811af0c4SBarry Smith   Note:
71811af0c4SBarry 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
72811af0c4SBarry Smith 
73db781477SPatrick Sanan .seealso: `PetscCheckPointerSetIntensity()`
74d96cc911SJed Brown @*/
75d71ae5a4SJacob Faibussowitsch PetscBool PetscCheckPointer(const void *ptr, PetscDataType dtype)
76d71ae5a4SJacob Faibussowitsch {
77d96cc911SJed Brown   if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE;
78d96cc911SJed Brown   if (!ptr) return PETSC_FALSE;
7928559dc8SJed Brown   if (petsc_checkpointer_intensity < 1) return PETSC_TRUE;
80d96cc911SJed Brown 
81dfb7d7afSStefano Zampini   #if PetscDefined(USE_DEBUG) && !PetscDefined(HAVE_THREADSAFETY)
82a2f94806SJed Brown   /* Skip the verbose check if we are inside a hot function. */
8327104ee2SJacob Faibussowitsch   if (petscstack.hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE;
8427104ee2SJacob Faibussowitsch   #endif
85a2f94806SJed Brown 
86718fc407SJed Brown   PetscSegvJumpBuf_set = PETSC_TRUE;
87d96cc911SJed Brown 
88d96cc911SJed Brown   if (setjmp(PetscSegvJumpBuf)) {
89d96cc911SJed Brown     /* A segv was triggered in the code below hence we return with an error code */
90718fc407SJed Brown     PetscSegvJumpBuf_set = PETSC_FALSE;
91d96cc911SJed Brown     return PETSC_FALSE;
92d96cc911SJed Brown   } else {
93d96cc911SJed Brown     switch (dtype) {
94d96cc911SJed Brown     case PETSC_INT: {
95*7a2f837dSToby Isaac       PETSC_UNUSED PetscInt x = *(volatile PetscInt *)ptr;
96d96cc911SJed Brown       break;
97d96cc911SJed Brown     }
98d96cc911SJed Brown   #if defined(PETSC_USE_COMPLEX)
99d96cc911SJed Brown     case PETSC_SCALAR: { /* C++ is seriously dysfunctional with volatile std::complex. */
10096d2aba5SSatish Balay     #if defined(PETSC_USE_CXXCOMPLEX)
101d96cc911SJed Brown       PetscReal                         xreal = ((volatile PetscReal *)ptr)[0], ximag = ((volatile PetscReal *)ptr)[1];
102d96cc911SJed Brown       PETSC_UNUSED volatile PetscScalar x = xreal + PETSC_i * ximag;
10396d2aba5SSatish Balay     #else
10496d2aba5SSatish Balay       PETSC_UNUSED PetscScalar x = *(volatile PetscScalar *)ptr;
10596d2aba5SSatish Balay     #endif
106d96cc911SJed Brown       break;
107d96cc911SJed Brown     }
108d96cc911SJed Brown   #endif
109d96cc911SJed Brown     case PETSC_REAL: {
110d96cc911SJed Brown       PETSC_UNUSED PetscReal x = *(volatile PetscReal *)ptr;
111d96cc911SJed Brown       break;
112d96cc911SJed Brown     }
113d96cc911SJed Brown     case PETSC_BOOL: {
114d96cc911SJed Brown       PETSC_UNUSED PetscBool x = *(volatile PetscBool *)ptr;
115d96cc911SJed Brown       break;
116d96cc911SJed Brown     }
117d96cc911SJed Brown     case PETSC_ENUM: {
118d96cc911SJed Brown       PETSC_UNUSED PetscEnum x = *(volatile PetscEnum *)ptr;
119d96cc911SJed Brown       break;
120d96cc911SJed Brown     }
121d96cc911SJed Brown     case PETSC_CHAR: {
122f4e06bcbSJed Brown       PETSC_UNUSED char x = *(volatile char *)ptr;
123d96cc911SJed Brown       break;
124d96cc911SJed Brown     }
125d96cc911SJed Brown     case PETSC_OBJECT: {
126d96cc911SJed Brown       PETSC_UNUSED volatile PetscClassId classid = ((PetscObject)ptr)->classid;
127d96cc911SJed Brown       break;
128d96cc911SJed Brown     }
129d96cc911SJed Brown     default:;
130d96cc911SJed Brown     }
131d96cc911SJed Brown   }
132718fc407SJed Brown   PetscSegvJumpBuf_set = PETSC_FALSE;
133d96cc911SJed Brown   return PETSC_TRUE;
134d96cc911SJed Brown }
13505035670SJunchao Zhang #endif
136