root/ompi/errhandler/errhandler.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. ompi_errhandler_is_intrinsic

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2011 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
  10  *                         University of Stuttgart.  All rights reserved.
  11  * Copyright (c) 2004-2005 The Regents of the University of California.
  12  *                         All rights reserved.
  13  * Copyright (c) 2008-2018 Cisco Systems, Inc.  All rights reserved
  14  * Copyright (c) 2008-2009 Sun Microsystems, Inc.  All rights reserved.
  15  * Copyright (c) 2015-2016 Intel, Inc. All rights reserved.
  16  * Copyright (c) 2016      Los Alamos National Security, LLC. All rights
  17  *                         reserved.
  18  * Copyright (c) 2016      Research Organization for Information Science
  19  *                         and Technology (RIST). All rights reserved.
  20  * $COPYRIGHT$
  21  *
  22  * Additional copyrights may follow
  23  *
  24  * $HEADER$
  25  */
  26 /** @file **/
  27 
  28 #ifndef OMPI_ERRHANDLER_H
  29 #define OMPI_ERRHANDLER_H
  30 
  31 #include "ompi_config.h"
  32 
  33 #include "mpi.h"
  34 
  35 #include "opal/prefetch.h"
  36 #include "opal/class/opal_object.h"
  37 #include "opal/class/opal_pointer_array.h"
  38 #include "opal/mca/pmix/pmix.h"
  39 
  40 #include "ompi/runtime/mpiruntime.h"
  41 #include "ompi/errhandler/errhandler_predefined.h"
  42 #include "ompi/errhandler/errcode-internal.h"
  43 
  44 BEGIN_C_DECLS
  45 
  46 /*
  47  * These must correspond to the fortran handle indices
  48  */
  49 enum {
  50   OMPI_ERRHANDLER_NULL_FORTRAN = 0,
  51   OMPI_ERRORS_ARE_FATAL_FORTRAN,
  52   OMPI_ERRORS_RETURN_FORTRAN
  53 };
  54 
  55 
  56 /**
  57  * Typedef for all fortran errhandler functions
  58  */
  59 typedef void (ompi_errhandler_fortran_handler_fn_t)(MPI_Fint *,
  60                                                     MPI_Fint *, ...);
  61 
  62 /**
  63  * Typedef for generic errhandler function
  64  */
  65 typedef void (ompi_errhandler_generic_handler_fn_t)(void *, int *, ...);
  66 
  67 /**
  68  * Enum to denote what language the error handler was created from
  69  */
  70 enum ompi_errhandler_lang_t {
  71     OMPI_ERRHANDLER_LANG_C,
  72     OMPI_ERRHANDLER_LANG_CXX,
  73     OMPI_ERRHANDLER_LANG_FORTRAN
  74 };
  75 typedef enum ompi_errhandler_lang_t ompi_errhandler_lang_t;
  76 
  77 
  78 /**
  79  * Enum used to describe what kind MPI object an error handler is used for
  80  */
  81 enum ompi_errhandler_type_t {
  82     OMPI_ERRHANDLER_TYPE_PREDEFINED,
  83     OMPI_ERRHANDLER_TYPE_COMM,
  84     OMPI_ERRHANDLER_TYPE_WIN,
  85     OMPI_ERRHANDLER_TYPE_FILE
  86 };
  87 typedef enum ompi_errhandler_type_t ompi_errhandler_type_t;
  88 
  89 
  90 /*
  91  * Need to forward declare this for use in ompi_errhandle_cxx_dispatch_fn_t.
  92  */
  93 struct ompi_errhandler_t;
  94 
  95 /**
  96  * C++ invocation function signature
  97  */
  98 typedef void (ompi_errhandler_cxx_dispatch_fn_t)(void *handle, int *err_code,
  99                                                  const char *message, ompi_errhandler_generic_handler_fn_t *fn);
 100 
 101 /**
 102  * Back-end type for MPI_Errorhandler.
 103  */
 104 struct ompi_errhandler_t {
 105     opal_object_t super;
 106 
 107     char eh_name[MPI_MAX_OBJECT_NAME];
 108     /* Type of MPI object that this handler is for */
 109 
 110     ompi_errhandler_type_t eh_mpi_object_type;
 111 
 112     /* What language was the error handler created in */
 113     ompi_errhandler_lang_t eh_lang;
 114 
 115     /* Function pointers.  Note that we *have* to have all 4 types
 116        (vs., for example, a union) because the predefined errhandlers
 117        can be invoked on any MPI object type, so we need callbacks for
 118        all of three. */
 119     MPI_Comm_errhandler_function *eh_comm_fn;
 120     ompi_file_errhandler_function *eh_file_fn;
 121     MPI_Win_errhandler_function *eh_win_fn;
 122     ompi_errhandler_fortran_handler_fn_t *eh_fort_fn;
 123 
 124     /* Have separate callback for C++ errhandlers.  This pointer is
 125        initialized to NULL and will be set explicitly by the C++
 126        bindings for Create_errhandler.  This function is invoked
 127        when eh_lang==OMPI_ERRHANDLER_LANG_CXX so that the user's
 128        callback function can be invoked with the right language
 129        semantics. */
 130     ompi_errhandler_cxx_dispatch_fn_t *eh_cxx_dispatch_fn;
 131 
 132     /* index in Fortran <-> C translation array */
 133     int eh_f_to_c_index;
 134 };
 135 typedef struct ompi_errhandler_t ompi_errhandler_t;
 136 
 137 /**
 138  * Padded struct to maintain back compatibiltiy.
 139  * See ompi/communicator/communicator.h comments with struct ompi_communicator_t
 140  * for full explanation why we chose the following padding construct for predefines.
 141  */
 142 #define PREDEFINED_ERRHANDLER_PAD 1024
 143 
 144 struct ompi_predefined_errhandler_t {
 145     struct ompi_errhandler_t eh;
 146     char padding[PREDEFINED_ERRHANDLER_PAD - sizeof(ompi_errhandler_t)];
 147 };
 148 
 149 typedef struct ompi_predefined_errhandler_t ompi_predefined_errhandler_t;
 150 
 151 
 152 /**
 153  * Global variable for MPI_ERRHANDLER_NULL (_addr flavor is for F03 bindings)
 154  */
 155 OMPI_DECLSPEC extern ompi_predefined_errhandler_t ompi_mpi_errhandler_null;
 156 OMPI_DECLSPEC extern ompi_predefined_errhandler_t *ompi_mpi_errhandler_null_addr;
 157 
 158 /**
 159  * Global variable for MPI_ERRORS_ARE_FATAL (_addr flavor is for F03 bindings)
 160  */
 161 OMPI_DECLSPEC extern ompi_predefined_errhandler_t ompi_mpi_errors_are_fatal;
 162 OMPI_DECLSPEC extern ompi_predefined_errhandler_t *ompi_mpi_errors_are_fatal_addr;
 163 
 164 /**
 165  * Global variable for MPI_ERRORS_RETURN (_addr flavor is for F03 bindings)
 166  */
 167 OMPI_DECLSPEC extern ompi_predefined_errhandler_t ompi_mpi_errors_return;
 168 OMPI_DECLSPEC extern ompi_predefined_errhandler_t *ompi_mpi_errors_return_addr;
 169 
 170 /**
 171  * Global variable for MPI::ERRORS_THROW_EXCEPTIONS.  Will abort if
 172  * MPI_INIT wasn't called as MPI::INIT (_addr flavor is for F03 bindings)
 173  */
 174 OMPI_DECLSPEC extern ompi_predefined_errhandler_t ompi_mpi_errors_throw_exceptions;
 175 
 176 /**
 177  * Table for Fortran <-> C errhandler handle conversion
 178  */
 179 OMPI_DECLSPEC extern opal_pointer_array_t ompi_errhandler_f_to_c_table;
 180 
 181 
 182 /**
 183  * Forward declaration so that we don't have to include
 184  * request/request.h here.
 185  */
 186 struct ompi_request_t;
 187 
 188 
 189 /**
 190  * This is the macro to check the state of MPI and determine whether
 191  * it was properly initialized and not yet finalized.
 192  *
 193  * This macro directly invokes the ompi_mpi_errors_are_fatal_handler()
 194  * when an error occurs because MPI_COMM_WORLD does not exist (because
 195  * we're before MPI_Init() or after MPI_Finalize()).
 196  *
 197  * NOTE: The ompi_mpi_state variable is a volatile that is set
 198  * atomically in ompi_mpi_init() and ompi_mpi_finalize().  The
 199  * appropriate memory barriers are done in those 2 functions such that
 200  * we do not need to do a read memory barrier here (in
 201  * potentially-performance-critical code paths) before reading the
 202  * variable.
 203  */
 204 #define OMPI_ERR_INIT_FINALIZE(name)                                    \
 205     {                                                                   \
 206         int32_t state = ompi_mpi_state;                                 \
 207         if (OPAL_UNLIKELY(state < OMPI_MPI_STATE_INIT_COMPLETED ||      \
 208                           state > OMPI_MPI_STATE_FINALIZE_PAST_COMM_SELF_DESTRUCT)) { \
 209             ompi_mpi_errors_are_fatal_comm_handler(NULL, NULL, name);   \
 210         }                                                               \
 211     }
 212 
 213 /**
 214  * This is the macro to invoke to directly invoke an MPI error
 215  * handler.
 216  *
 217  * @param mpi_object The MPI object to invoke the errhandler on (a
 218  *    comm, win, or win)
 219  * @param err_code The error code
 220  * @param message Any additional message; typically the name of the
 221  *    MPI function that is invoking the error.
 222  *
 223  * This macro is used when you want to directly invoke the error
 224  * handler.  It is exactly equivalent to calling
 225  * ompi_errhandler_invoke() directly, but is provided to have a
 226  * parallel invocation to OMPI_ERRHANDLER_CHECK() and OMPI_ERRHANDLER_RETURN().
 227  */
 228 #define OMPI_ERRHANDLER_INVOKE(mpi_object, err_code, message) \
 229   ompi_errhandler_invoke((mpi_object)->error_handler, \
 230                          (mpi_object), \
 231                          (int)(mpi_object)->errhandler_type, \
 232                          ompi_errcode_get_mpi_code(err_code), \
 233                          (message));
 234 
 235 /**
 236  * Conditionally invoke an MPI error handler.
 237  *
 238  * @param rc The return code to check
 239  * @param mpi_object The MPI object to invoke the errhandler on (a
 240  *    comm, win, or win)
 241  * @param err_code The error code
 242  * @param message Any additional message; typically the name of the
 243  *    MPI function that is invoking the error.
 244  *
 245  * This macro will invoke the error handler if the return code is not
 246  * OMPI_SUCCESS.
 247  */
 248 #define OMPI_ERRHANDLER_CHECK(rc, mpi_object, err_code, message) \
 249   if( OPAL_UNLIKELY(rc != OMPI_SUCCESS) ) { \
 250     int __mpi_err_code = ompi_errcode_get_mpi_code(err_code);         \
 251     OPAL_CR_EXIT_LIBRARY() \
 252     ompi_errhandler_invoke((mpi_object)->error_handler, \
 253                            (mpi_object), \
 254                            (int) (mpi_object)->errhandler_type, \
 255                            (__mpi_err_code), \
 256                            (message)); \
 257     return (__mpi_err_code); \
 258   }
 259 
 260 /**
 261  * Conditionally invoke an MPI error handler; if there is no error,
 262  * return MPI_SUCCESS.
 263  *
 264  * @param rc The return code to check
 265  * @param mpi_object The MPI object to invoke the errhandler on (a
 266  *    comm, win, or win)
 267  * @param err_code The error code
 268  * @param message Any additional message; typically the name of the
 269  *    MPI function that is invoking the error.
 270  *
 271  * This macro will invoke the error handler if the return code is not
 272  * OMPI_SUCCESS.  If the return code is OMPI_SUCCESS, then return
 273  * MPI_SUCCESS.
 274  */
 275 #define OMPI_ERRHANDLER_RETURN(rc, mpi_object, err_code, message) \
 276   OPAL_CR_EXIT_LIBRARY() \
 277   if ( OPAL_UNLIKELY(OMPI_SUCCESS != rc) ) { \
 278     int __mpi_err_code = ompi_errcode_get_mpi_code(err_code);         \
 279     ompi_errhandler_invoke((mpi_object)->error_handler, \
 280                            (mpi_object), \
 281                            (int)(mpi_object)->errhandler_type, \
 282                            (__mpi_err_code), \
 283                            (message)); \
 284     return (__mpi_err_code); \
 285   } else { \
 286     return MPI_SUCCESS; \
 287   }
 288 
 289 
 290 
 291   /**
 292    * Initialize the error handler interface.
 293    *
 294    * @returns OMPI_SUCCESS Upon success
 295    * @returns OMPI_ERROR Otherwise
 296    *
 297    * Invoked from ompi_mpi_init(); sets up the error handler interface,
 298    * creates the predefined MPI errorhandlers, and creates the
 299    * corresopnding F2C translation table.
 300    */
 301   int ompi_errhandler_init(void);
 302 
 303   /**
 304    * Finalize the error handler interface.
 305    *
 306    * @returns OMPI_SUCCESS Always
 307    *
 308    * Invokes from ompi_mpi_finalize(); tears down the error handler
 309    * interface, and destroys the F2C translation table.
 310    */
 311   int ompi_errhandler_finalize(void);
 312 
 313   /**
 314    * \internal
 315    *
 316    * This function should not be invoked directly; it should only be
 317    * invoked by OMPI_ERRHANDLER_INVOKE(), OMPI_ERRHANDLER_CHECK(), or
 318    * OMPI_ERRHANDLER_RETURN().
 319    *
 320    * @param errhandler The MPI_Errhandler to invoke
 321    * @param mpi_object The MPI object to invoke the errhandler on (a
 322    *    comm, win, or win)
 323    * @param type       The type of the MPI object. Necessary, since
 324    *                   you can not assign a single type to the predefined
 325    *                   error handlers. This information is therefore
 326    *                   stored on the MPI object itself.
 327    * @param err_code The error code
 328    * @param message Any additional message; typically the name of the
 329    *    MPI function that is invoking the error.
 330    *
 331    * @returns err_code The same value as the parameter
 332    *
 333    * This function invokes the MPI exception function on the error
 334    * handler.  If the errhandler was created from fortran, the error
 335    * handler will be invoked with fortran linkage.  Otherwise, it is
 336    * invoked with C linkage.
 337    *
 338    * If this function returns, it returns the err_code.  Note that it
 339    * may not return (e.g., for MPI_ERRORS_ARE_FATAL).
 340    */
 341   OMPI_DECLSPEC int ompi_errhandler_invoke(ompi_errhandler_t *errhandler, void *mpi_object,
 342                                            int type, int err_code, const char *message);
 343 
 344 
 345   /**
 346    * Invoke an MPI exception on the first request found in the array
 347    * that has a non-MPI_SUCCESS value for MPI_ERROR in its status.  It
 348    * is safe to invoke this function if none of the requests have an
 349    * outstanding error; MPI_SUCCESS will be returned.
 350    */
 351   int ompi_errhandler_request_invoke(int count,
 352                                      struct ompi_request_t **requests,
 353                                      const char *message);
 354 
 355   /**
 356    * Create a ompi_errhandler_t
 357    *
 358    * @param object_type Enum of the type of MPI object
 359    * @param func Function pointer of the error handler
 360    *
 361    * @returns errhandler Pointer to the ompi_errorhandler_t that will be
 362    *   created and returned
 363    *
 364    * This function is called as the back-end of all the
 365    * MPI_*_CREATE_ERRHANDLER functions.  It creates a new
 366    * ompi_errhandler_t object, initializes it to the correct object
 367    * type, and sets the callback function on it.
 368    *
 369    * The type of the function pointer is (arbitrarily) the fortran
 370    * function handler type.  Since this function has to accept 4
 371    * different function pointer types (lest we have 4 different
 372    * functions to create errhandlers), the fortran one was picked
 373    * arbitrarily.  Note that (void*) is not sufficient because at
 374    * least theoretically, a sizeof(void*) may not necessarily be the
 375    * same as sizeof(void(*)).
 376    */
 377   OMPI_DECLSPEC ompi_errhandler_t *ompi_errhandler_create(ompi_errhandler_type_t object_type,
 378                                             ompi_errhandler_generic_handler_fn_t *func,
 379                                             ompi_errhandler_lang_t language);
 380 
 381 /**
 382  * Callback function to alert the MPI layer of an error or notification
 383  * from the internal RTE and/or the resource manager.
 384  *
 385  * This function is used to alert the MPI layer to a specific fault detected by the
 386  * runtime layer or host RM. This could be a process failure, a lost connection, or the inability
 387  * to send an OOB message. The MPI layer has the option to perform whatever actions it
 388  * needs to stabilize itself and continue running, abort, etc.
 389  */
 390 typedef struct {
 391     volatile bool active;
 392     int status;
 393 } ompi_errhandler_errtrk_t;
 394 
 395 OMPI_DECLSPEC void ompi_errhandler_callback(int status,
 396                                             const opal_process_name_t *source,
 397                                             opal_list_t *info, opal_list_t *results,
 398                                             opal_pmix_notification_complete_fn_t cbfunc,
 399                                             void *cbdata);
 400 
 401 OMPI_DECLSPEC void ompi_errhandler_registration_callback(int status,
 402                                                          size_t errhandler_ref,
 403                                                          void *cbdata);
 404 /**
 405  * Check to see if an errhandler is intrinsic.
 406  *
 407  * @param errhandler The errhandler to check
 408  *
 409  * @returns true If the errhandler is intrinsic
 410  * @returns false If the errhandler is not intrinsic
 411  *
 412  * Self-explanitory.  This is needed in a few top-level MPI functions;
 413  * this function is provided to hide the internal structure field
 414  * names.
 415  */
 416 static inline bool ompi_errhandler_is_intrinsic(ompi_errhandler_t *errhandler)
 417 {
 418     if ( OMPI_ERRHANDLER_TYPE_PREDEFINED == errhandler->eh_mpi_object_type )
 419         return true;
 420 
 421     return false;
 422 }
 423 
 424 END_C_DECLS
 425 
 426 #endif /* OMPI_ERRHANDLER_H */

/* [<][>][^][v][top][bottom][index][help] */