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