Date: 2022-03-04T17:37:06+00:00

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: {

     34:   switch (intensity) {
     35:   case 0:
     36:   case 1:
     37:   case 2:
     38:     petsc_checkpointer_intensity = intensity;
     39:     break;
     40:   default: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Intensity %D not in 0,1,2",intensity);
     41:   }
     42:   return(0);
     43: }

     45: /* ---------------------------------------------------------------------------------------*/

     47: #if defined(PETSC_HAVE_SETJMP_H)
     48: #include <setjmp.h>
     49: static jmp_buf PetscSegvJumpBuf;
     50: static PetscBool PetscSegvJumpBuf_set;

     52: /*@C
     53:    PetscSignalSegvCheckPointerOrMpi - To be called from a signal handler for SIGSEGV.  If the signal was received
     55:    with no effect. This function is called automatically by PetscSignalHandlerDefault().

     57:    Not Collective

     59:    Level: developer

     61: .seealso: PetscPushSignalHandler()
     62: @*/
     63: void PetscSignalSegvCheckPointerOrMpi(void)
     64: {
     65:   if (PetscSegvJumpBuf_set) longjmp(PetscSegvJumpBuf,1);
     66: }

     68: /*@C

     71:    Not Collective

     73:    Input Parameters:
     74: +     ptr - the pointer
     75: -     dtype - the type of data the pointer is suppose to point to

     77:    Level: developer

     80: @*/
     82: {

     84:   if (PETSC_RUNNING_ON_VALGRIND) return PETSC_TRUE;
     85:   if (!ptr) return PETSC_FALSE;
     86:   if (petsc_checkpointer_intensity < 1) return PETSC_TRUE;

     88: #if PetscDefined(USE_DEBUG)
     89:   /* Skip the verbose check if we are inside a hot function. */
     90:   if (petscstack.hotdepth > 0 && petsc_checkpointer_intensity < 2) return PETSC_TRUE;
     91: #endif

     93:   PetscSegvJumpBuf_set = PETSC_TRUE;

     95:   if (setjmp(PetscSegvJumpBuf)) {
     96:     /* A segv was triggered in the code below hence we return with an error code */
     97:     PetscSegvJumpBuf_set = PETSC_FALSE;
     98:     return PETSC_FALSE;
     99:   } else {
    100:     switch (dtype) {
    101:     case PETSC_INT:{
    102:       PETSC_UNUSED PetscInt x = (PetscInt)*(volatile PetscInt*)ptr;
    103:       break;
    104:     }
    105: #if defined(PETSC_USE_COMPLEX)
    106:     case PETSC_SCALAR:{         /* C++ is seriously dysfunctional with volatile std::complex. */
    107: #if defined(PETSC_USE_CXXCOMPLEX)
    108:       PetscReal xreal = ((volatile PetscReal*)ptr)[0],ximag = ((volatile PetscReal*)ptr)[1];
    109:       PETSC_UNUSED volatile PetscScalar x = xreal + PETSC_i*ximag;
    110: #else
    111:       PETSC_UNUSED PetscScalar x = *(volatile PetscScalar*)ptr;
    112: #endif
    113:       break;
    114:     }
    115: #endif
    116:     case PETSC_REAL:{
    117:       PETSC_UNUSED PetscReal x = *(volatile PetscReal*)ptr;
    118:       break;
    119:     }
    120:     case PETSC_BOOL:{
    121:       PETSC_UNUSED PetscBool x = *(volatile PetscBool*)ptr;
    122:       break;
    123:     }
    124:     case PETSC_ENUM:{
    125:       PETSC_UNUSED PetscEnum x = *(volatile PetscEnum*)ptr;
    126:       break;
    127:     }
    128:     case PETSC_CHAR:{
    129:       PETSC_UNUSED char x = *(volatile char*)ptr;
    130:       break;
    131:     }
    132:     case PETSC_OBJECT:{
    133:       PETSC_UNUSED volatile PetscClassId classid = ((PetscObject)ptr)->classid;
    134:       break;
    135:     }
    136:     default:;
    137:     }
    138:   }
    139:   PetscSegvJumpBuf_set = PETSC_FALSE;
    140:   return PETSC_TRUE;
    141: }

    143: #define PetscMPICUPMAwarnessCheckFunction  \
    144: PetscBool PetscMPICUPMAwarenessCheck(void)  \
    145: { \
    146:   cupmError_t cerr=cupmSuccess; \
    147:   int         ierr,hbuf[2]={1,0},*dbuf=NULL; \
    148:   PetscBool   awareness=PETSC_FALSE; \
    149:   cerr = cupmMalloc((void**)&dbuf,sizeof(int)*2);if (cerr != cupmSuccess) return PETSC_FALSE; \
    150:   cerr = cupmMemcpy(dbuf,hbuf,sizeof(int)*2,cupmMemcpyHostToDevice);if (cerr != cupmSuccess) return PETSC_FALSE; \
    151:   PetscSegvJumpBuf_set = PETSC_TRUE; \
    152:   if (setjmp(PetscSegvJumpBuf)) { \
    153:     /* If a segv was triggered in the MPI_Allreduce below, it is very likely due to the MPI is not GPU-aware */ \
    154:     awareness = PETSC_FALSE; \
    155:   } else { \
    156:     MPI_Allreduce(dbuf,dbuf+1,1,MPI_INT,MPI_SUM,PETSC_COMM_SELF); \
    157:     if (!ierr) awareness = PETSC_TRUE; \
    158:   } \
    159:   PetscSegvJumpBuf_set = PETSC_FALSE; \
    160:   cerr = cupmFree(dbuf);if (cerr != cupmSuccess) return PETSC_FALSE; \
    161:   return awareness; \
    162: }

    164: #if defined(PETSC_HAVE_CUDA)
    165:   #define cupmError_t                   cudaError_t
    166:   #define cupmMalloc                    cudaMalloc
    167:   #define cupmMemcpy                    cudaMemcpy
    168:   #define cupmFree                      cudaFree
    169:   #define cupmSuccess                   cudaSuccess
    170:   #define cupmMemcpyHostToDevice        cudaMemcpyHostToDevice
    171:   #define PetscMPICUPMAwarenessCheck    PetscMPICUDAAwarenessCheck
    172:   PetscMPICUPMAwarnessCheckFunction
    173: #endif

    175: #if defined(PETSC_HAVE_HIP)
    176:   #define cupmError_t                   hipError_t
    177:   #define cupmMalloc                    hipMalloc
    178:   #define cupmMemcpy                    hipMemcpy
    179:   #define cupmFree                      hipFree
    180:   #define cupmSuccess                   hipSuccess
    181:   #define cupmMemcpyHostToDevice        hipMemcpyHostToDevice
    182:   #define PetscMPICUPMAwarenessCheck    PetscMPIHIPAwarenessCheck
    183:   PetscMPICUPMAwarnessCheckFunction
    184: #endif

    186: #else
    187: void PetscSignalSegvCheckPointerOrMpi(void)
    188: {
    189:   return;
    190: }

    193: {
    194:   if (!ptr) return PETSC_FALSE;
    195:   return PETSC_TRUE;
    196: }

    198: #if defined (PETSC_HAVE_CUDA)
    199: PetscBool PetscMPICUDAAwarenessCheck(void)
    200: {
    201:   /* If no setjmp (rare), return true and let users code run (and segfault if they should) */
    202:   return PETSC_TRUE;
    203: }
    204: #endif

    206: #if defined (PETSC_HAVE_HIP)
    207: PetscBool PetscMPIHIPAwarenessCheck(void)
    208: {
    209:   /* If no setjmp (rare), return true and let users code run (and segfault if they should) */
    210:   return PETSC_TRUE;
    211: }
    212: #endif

    214: #endif