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