Actual source code: checkptr.c
petsc-3.13.6 2020-09-29
1: #include <petsc/private/petscimpl.h>
2: #include <petscvalgrind.h>
3: #if defined(PETSC_HAVE_CUDA)
4: #include <cuda_runtime.h>
5: #include <petsccublas.h>
6: #endif
8: static PetscInt petsc_checkpointer_intensity = 1;
10: /*@
12: confirm whether the address is valid. An intensity of 0 never uses signal handlers, 1 uses them when not in a "hot"
13: function, and intensity of 2 always uses a signal handler.
15: Not Collective
17: Input Arguments:
18: . intensity - how much to check pointers for validity
20: Options Database:
21: . -check_pointer_intensity - intensity (0, 1, or 2)
23: Level: advanced
26: @*/
28: {
31: switch (intensity) {
32: case 0:
33: case 1:
34: case 2:
35: petsc_checkpointer_intensity = intensity;
36: break;
37: default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Intensity %D not in 0,1,2",intensity);
38: }
39: return(0);
40: }
42: /* ---------------------------------------------------------------------------------------*/
44: #if defined(PETSC_HAVE_SETJMP_H)
45: #include <setjmp.h>
46: static jmp_buf PetscSegvJumpBuf;
47: static PetscBool PetscSegvJumpBuf_set;
49: /*@C
50: PetscSignalSegvCheckPointerOrMpi - To be called from a signal handler for SIGSEGV. If the signal was received
52: with no effect. This function is called automatically by PetscSignalHandlerDefault().
54: Not Collective
56: Level: developer
58: .seealso: PetscPushSignalHandler()
59: @*/
60: void PetscSignalSegvCheckPointerOrMpi(void) {
61: if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf,1);
62: }
64: /*@C
67: Not Collective
69: Input Parameters:
70: + ptr - the pointer
71: - dtype - the type of data the pointer is suppose to point to
73: Level: developer
76: @*/
78: {
80: if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE;
81: if (!ptr) return PETSC_FALSE;
82: if (petsc_checkpointer_intensity < 1) return PETSC_TRUE;
84: /* Skip the verbose check if we are inside a hot function. */
85: if (petscstack && petscstack->hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE;
87: PetscSegvJumpBuf_set = PETSC_TRUE;
89: if (setjmp(PetscSegvJumpBuf)) {
90: /* A segv was triggered in the code below hence we return with an error code */
91: PetscSegvJumpBuf_set = PETSC_FALSE;
92: return PETSC_FALSE;
93: } else {
94: switch (dtype) {
95: case PETSC_INT:{
96: PETSC_UNUSED PetscInt x = (PetscInt)*(volatile PetscInt*)ptr;
97: break;
98: }
99: #if defined(PETSC_USE_COMPLEX)
100: case PETSC_SCALAR:{ /* C++ is seriously dysfunctional with volatile std::complex. */
101: #if defined(PETSC_USE_CXXCOMPLEX)
102: PetscReal xreal = ((volatile PetscReal*)ptr)[0],ximag = ((volatile PetscReal*)ptr)[1];
103: PETSC_UNUSED volatile PetscScalar x = xreal + PETSC_i*ximag;
104: #else
105: PETSC_UNUSED PetscScalar x = *(volatile PetscScalar*)ptr;
106: #endif
107: break;
108: }
109: #endif
110: case PETSC_REAL:{
111: PETSC_UNUSED PetscReal x = *(volatile PetscReal*)ptr;
112: break;
113: }
114: case PETSC_BOOL:{
115: PETSC_UNUSED PetscBool x = *(volatile PetscBool*)ptr;
116: break;
117: }
118: case PETSC_ENUM:{
119: PETSC_UNUSED PetscEnum x = *(volatile PetscEnum*)ptr;
120: break;
121: }
122: case PETSC_CHAR:{
123: PETSC_UNUSED char x = *(volatile char*)ptr;
124: break;
125: }
126: case PETSC_OBJECT:{
127: PETSC_UNUSED volatile PetscClassId classid = ((PetscObject)ptr)->classid;
128: break;
129: }
130: default:;
131: }
132: }
133: PetscSegvJumpBuf_set = PETSC_FALSE;
134: return PETSC_TRUE;
135: }
137: #if defined (PETSC_HAVE_CUDA)
139: {
140: cudaError_t cerr=cudaSuccess;
141: int ierr,hbuf[2]={1,0},*dbuf=NULL;
142: PetscBool awareness=PETSC_FALSE;
144: cerr = cudaMalloc((void**)&dbuf,sizeof(int)*2);if (cerr != cudaSuccess) return PETSC_FALSE;
145: cerr = cudaMemcpy(dbuf,hbuf,sizeof(int)*2,cudaMemcpyHostToDevice);if (cerr != cudaSuccess) return PETSC_FALSE;
147: PetscSegvJumpBuf_set = PETSC_TRUE;
148: if (setjmp(PetscSegvJumpBuf)) {
149: /* If a segv was triggered in the MPI_Allreduce below, it is very likely due to the MPI is not GPU-aware */
150: awareness = PETSC_FALSE;
151: } else {
152: MPI_Allreduce(dbuf,dbuf+1,1,MPI_INT,MPI_SUM,PETSC_COMM_WORLD);
153: if (!ierr) awareness = PETSC_TRUE;
154: }
155: PetscSegvJumpBuf_set = PETSC_FALSE;
156: cerr = cudaFree(dbuf);if (cerr != cudaSuccess) return PETSC_FALSE;
157: return awareness;
158: }
159: #endif
160: #else
161: void PetscSignalSegvCheckPointerOrMpi(void) {
162: return;
163: }
166: {
167: if (!ptr) return PETSC_FALSE;
168: return PETSC_TRUE;
169: }
172: {
173: /* If no setjmp (rare), return true and let users code run (and segfault if they should) */
174: return PETSC_TRUE;
175: }
176: #endif