Actual source code: checkptr.c
1: #include <petsc/private/petscimpl.h>
3: #if defined(PETSC_HAVE_CUDA)
4: #include <cuda_runtime.h>
5: #endif
7: #if defined(PETSC_HAVE_HIP)
8: #include <hip/hip_runtime.h>
9: #endif
11: static PetscInt petsc_checkpointer_intensity = 1;
13: /*@
15: confirm whether the address is valid. An intensity of 0 never uses signal handlers, 1 uses them when not in a "hot"
16: function, and intensity of 2 always uses a signal handler.
18: Not Collective
20: Input Parameter:
21: . intensity - how much to check pointers for validity
23: Options Database:
24: . -check_pointer_intensity - intensity (0, 1, or 2)
26: Level: advanced
29: @*/
31: {
32: switch (intensity) {
33: case 0:
34: case 1:
35: case 2:
36: petsc_checkpointer_intensity = intensity;
37: break;
38: default: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Intensity %" PetscInt_FMT " not in 0,1,2",intensity);
39: }
40: return 0;
41: }
43: /* ---------------------------------------------------------------------------------------*/
45: #if defined(PETSC_HAVE_SETJMP_H)
46: #include <setjmp.h>
47: static jmp_buf PetscSegvJumpBuf;
48: static PetscBool PetscSegvJumpBuf_set;
50: /*@C
51: PetscSignalSegvCheckPointerOrMpi - To be called from a signal handler for SIGSEGV. If the signal was received
53: with no effect. This function is called automatically by PetscSignalHandlerDefault().
55: Not Collective
57: Level: developer
59: .seealso: PetscPushSignalHandler()
60: @*/
61: void PetscSignalSegvCheckPointerOrMpi(void)
62: {
63: if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf,1);
64: }
66: /*@C
69: Not Collective
71: Input Parameters:
72: + ptr - the pointer
73: - dtype - the type of data the pointer is suppose to point to
75: Level: developer
78: @*/
80: {
82: if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE;
83: if (!ptr) return PETSC_FALSE;
84: if (petsc_checkpointer_intensity < 1) return PETSC_TRUE;
86: #if PetscDefined(USE_DEBUG)
87: /* Skip the verbose check if we are inside a hot function. */
88: if (petscstack.hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE;
89: #endif
91: PetscSegvJumpBuf_set = PETSC_TRUE;
93: if (setjmp(PetscSegvJumpBuf)) {
94: /* A segv was triggered in the code below hence we return with an error code */
95: PetscSegvJumpBuf_set = PETSC_FALSE;
96: return PETSC_FALSE;
97: } else {
98: switch (dtype) {
99: case PETSC_INT:{
100: PETSC_UNUSED PetscInt x = (PetscInt)*(volatile PetscInt*)ptr;
101: break;
102: }
103: #if defined(PETSC_USE_COMPLEX)
104: case PETSC_SCALAR:{ /* C++ is seriously dysfunctional with volatile std::complex. */
105: #if defined(PETSC_USE_CXXCOMPLEX)
106: PetscReal xreal = ((volatile PetscReal*)ptr)[0],ximag = ((volatile PetscReal*)ptr)[1];
107: PETSC_UNUSED volatile PetscScalar x = xreal + PETSC_i*ximag;
108: #else
109: PETSC_UNUSED PetscScalar x = *(volatile PetscScalar*)ptr;
110: #endif
111: break;
112: }
113: #endif
114: case PETSC_REAL:{
115: PETSC_UNUSED PetscReal x = *(volatile PetscReal*)ptr;
116: break;
117: }
118: case PETSC_BOOL:{
119: PETSC_UNUSED PetscBool x = *(volatile PetscBool*)ptr;
120: break;
121: }
122: case PETSC_ENUM:{
123: PETSC_UNUSED PetscEnum x = *(volatile PetscEnum*)ptr;
124: break;
125: }
126: case PETSC_CHAR:{
127: PETSC_UNUSED char x = *(volatile char*)ptr;
128: break;
129: }
130: case PETSC_OBJECT:{
131: PETSC_UNUSED volatile PetscClassId classid = ((PetscObject)ptr)->classid;
132: break;
133: }
134: default:;
135: }
136: }
137: PetscSegvJumpBuf_set = PETSC_FALSE;
138: return PETSC_TRUE;
139: }
141: #define PetscMPICUPMAwarnessCheckFunction \
142: PetscBool PetscMPICUPMAwarenessCheck(void) \
143: { \
144: cupmError_t cerr=cupmSuccess; \
145: int ierr,hbuf[2]={1,0},*dbuf=NULL; \
146: PetscBool awareness=PETSC_FALSE; \
147: cerr = cupmMalloc((void**)&dbuf,sizeof(int)*2);if (cerr != cupmSuccess) return PETSC_FALSE; \
148: cerr = cupmMemcpy(dbuf,hbuf,sizeof(int)*2,cupmMemcpyHostToDevice);if (cerr != cupmSuccess) return PETSC_FALSE; \
149: PetscSegvJumpBuf_set = PETSC_TRUE; \
150: if (setjmp(PetscSegvJumpBuf)) { \
151: /* If a segv was triggered in the MPI_Allreduce below, it is very likely due to the MPI is not GPU-aware */ \
152: awareness = PETSC_FALSE; \
153: } else { \
154: MPI_Allreduce(dbuf,dbuf+1,1,MPI_INT,MPI_SUM,PETSC_COMM_SELF); \
155: if (!ierr) awareness = PETSC_TRUE; \
156: } \
157: PetscSegvJumpBuf_set = PETSC_FALSE; \
158: cerr = cupmFree(dbuf);if (cerr != cupmSuccess) return PETSC_FALSE; \
159: return awareness; \
160: }
162: #if defined(PETSC_HAVE_CUDA)
163: #define cupmError_t cudaError_t
164: #define cupmMalloc cudaMalloc
165: #define cupmMemcpy cudaMemcpy
166: #define cupmFree cudaFree
167: #define cupmSuccess cudaSuccess
168: #define cupmMemcpyHostToDevice cudaMemcpyHostToDevice
169: #define PetscMPICUPMAwarenessCheck PetscMPICUDAAwarenessCheck
170: PetscMPICUPMAwarnessCheckFunction
171: #endif
173: #if defined(PETSC_HAVE_HIP)
174: #define cupmError_t hipError_t
175: #define cupmMalloc hipMalloc
176: #define cupmMemcpy hipMemcpy
177: #define cupmFree hipFree
178: #define cupmSuccess hipSuccess
179: #define cupmMemcpyHostToDevice hipMemcpyHostToDevice
180: #define PetscMPICUPMAwarenessCheck PetscMPIHIPAwarenessCheck
181: PetscMPICUPMAwarnessCheckFunction
182: #endif
184: #else
185: void PetscSignalSegvCheckPointerOrMpi(void)
186: {
187: return;
188: }
191: {
192: if (!ptr) return PETSC_FALSE;
193: return PETSC_TRUE;
194: }
196: #if defined (PETSC_HAVE_CUDA)
197: PetscBool PetscMPICUDAAwarenessCheck(void)
198: {
199: /* If no setjmp (rare), return true and let users code run (and segfault if they should) */
200: return PETSC_TRUE;
201: }
202: #endif
204: #if defined (PETSC_HAVE_HIP)
205: PetscBool PetscMPIHIPAwarenessCheck(void)
206: {
207: /* If no setjmp (rare), return true and let users code run (and segfault if they should) */
208: return PETSC_TRUE;
209: }
210: #endif
212: #endif