xref: /petsc/src/sys/error/checkptr.c (revision f8a67e6d0d929f3234335ad583eedb7449ee4373)
1af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
2022afb99SBarry Smith #include <petscvalgrind.h>
3d96cc911SJed Brown 
428559dc8SJed Brown static PetscInt petsc_checkpointer_intensity = 1;
528559dc8SJed Brown 
628559dc8SJed Brown /*@
728559dc8SJed Brown    PetscCheckPointerSetIntensity - An intense pointer check registers a signal handler and attempts to dereference to
828559dc8SJed Brown    confirm whether the address is valid.  An intensity of 0 never uses signal handlers, 1 uses them when not in a "hot"
928559dc8SJed Brown    function, and intensity of 2 always uses a signal handler.
1028559dc8SJed Brown 
1128559dc8SJed Brown    Not Collective
1228559dc8SJed Brown 
1328559dc8SJed Brown    Input Arguments:
1428559dc8SJed Brown .  intensity - how much to check pointers for validity
1528559dc8SJed Brown 
16c2f74817SBarry Smith    Options Database:
175789d1f5SJed Brown .  -check_pointer_intensity - intensity (0, 1, or 2)
18c2f74817SBarry Smith 
1928559dc8SJed Brown    Level: advanced
2028559dc8SJed Brown 
215789d1f5SJed Brown .seealso: PetscCheckPointer(), PetscFunctionBeginHot()
2228559dc8SJed Brown @*/
2328559dc8SJed Brown PetscErrorCode PetscCheckPointerSetIntensity(PetscInt intensity)
2428559dc8SJed Brown {
2528559dc8SJed Brown 
2628559dc8SJed Brown   PetscFunctionBegin;
2728559dc8SJed Brown   switch (intensity) {
2828559dc8SJed Brown   case 0:
2928559dc8SJed Brown   case 1:
3028559dc8SJed Brown   case 2:
3128559dc8SJed Brown     petsc_checkpointer_intensity = intensity;
3228559dc8SJed Brown     break;
3328559dc8SJed Brown   default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Intensity %D not in 0,1,2",intensity);
3428559dc8SJed Brown   }
3528559dc8SJed Brown   PetscFunctionReturn(0);
3628559dc8SJed Brown }
3728559dc8SJed Brown 
38d96cc911SJed Brown /* ---------------------------------------------------------------------------------------*/
39718fc407SJed Brown 
40718fc407SJed Brown #if defined(PETSC_HAVE_SETJMP_H)
41d96cc911SJed Brown #include <setjmp.h>
42*f8a67e6dSJed Brown static jmp_buf PetscSegvJumpBuf;
43*f8a67e6dSJed Brown static PetscBool PetscSegvJumpBuf_set;
44*f8a67e6dSJed Brown 
45*f8a67e6dSJed Brown /*@C
46*f8a67e6dSJed Brown    PetscSignalSegvCheckPointer - To be called from a signal handler for SIGSEGV.  If the signal was received while
47*f8a67e6dSJed Brown    executing PetscCheckPointer(), this function longjmps back there, otherwise returns with no effect.  This function is
48*f8a67e6dSJed Brown    called automatically by PetscSignalHandlerDefault().
49*f8a67e6dSJed Brown 
50*f8a67e6dSJed Brown    Not Collective
51*f8a67e6dSJed Brown 
52*f8a67e6dSJed Brown    Level: developer
53*f8a67e6dSJed Brown 
54*f8a67e6dSJed Brown .seealso: PetscPushSignalHandler()
55*f8a67e6dSJed Brown @*/
56*f8a67e6dSJed Brown void PetscSignalSegvCheckPointer() {
57*f8a67e6dSJed Brown   if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf,1);
58*f8a67e6dSJed Brown }
59d076d156SJed Brown 
60d96cc911SJed Brown /*@C
61d96cc911SJed Brown      PetscCheckPointer - Returns PETSC_TRUE if a pointer points to accessible data
62d96cc911SJed Brown 
63d96cc911SJed Brown    Not Collective
64d96cc911SJed Brown 
65d96cc911SJed Brown    Input Parameters:
66d96cc911SJed Brown +     ptr - the pointer
67d96cc911SJed Brown -     dtype - the type of data the pointer is suppose to point to
68d96cc911SJed Brown 
69d96cc911SJed Brown    Level: developer
70d96cc911SJed Brown 
715789d1f5SJed Brown .seealso: PetscCheckPointerSetIntensity()
72d96cc911SJed Brown @*/
73d96cc911SJed Brown PetscBool PetscCheckPointer(const void *ptr,PetscDataType dtype)
74d96cc911SJed Brown {
75d96cc911SJed Brown 
76d96cc911SJed Brown   if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE;
77d96cc911SJed Brown   if (!ptr) return PETSC_FALSE;
7828559dc8SJed Brown   if (petsc_checkpointer_intensity < 1) return PETSC_TRUE;
79d96cc911SJed Brown 
80a2f94806SJed Brown   /* Skip the verbose check if we are inside a hot function. */
815c25fcd7SBarry Smith   if (petscstack && petscstack->hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE;
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 }
132d96cc911SJed Brown #else
133*f8a67e6dSJed Brown void PetscSignalSegvCheckPointer() {
134*f8a67e6dSJed Brown   return;
135*f8a67e6dSJed Brown }
136*f8a67e6dSJed Brown 
137d96cc911SJed Brown PetscBool PetscCheckPointer(const void *ptr,PETSC_UNUSED PetscDataType dtype)
138d96cc911SJed Brown {
139d96cc911SJed Brown   if (!ptr) return PETSC_FALSE;
140d96cc911SJed Brown   return PETSC_TRUE;
141d96cc911SJed Brown }
142d96cc911SJed Brown #endif
143