root/oshmem/request/request.h

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. oshmem_request_cancel
  2. oshmem_request_free
  3. oshmem_request_wait_any_completion
  4. oshmem_request_wait_completion
  5. oshmem_request_complete

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2013      Mellanox Technologies, Inc.
   4  *                         All rights reserved.
   5  * Copyright (c) 2015      Los Alamos National Security, LLC. All rights
   6  *                         reserved.
   7  * $COPYRIGHT$
   8  *
   9  * Additional copyrights may follow
  10  *
  11  * $HEADER$
  12  */
  13 /**
  14  * @file
  15  *
  16  * Top-level description of requests
  17  */
  18 
  19 #ifndef OSHMEM_REQUEST_H
  20 #define OSHMEM_REQUEST_H
  21 
  22 #include "oshmem_config.h"
  23 #include "oshmem/constants.h"
  24 
  25 #include "opal/class/opal_free_list.h"
  26 #include "opal/class/opal_pointer_array.h"
  27 #include "opal/threads/condition.h"
  28 
  29 BEGIN_C_DECLS
  30 
  31 /**
  32  * Request class
  33  */
  34 /*OSHMEM_DECLSPEC OBJ_CLASS_DECLARATION(oshmem_request_t);*/
  35 OSHMEM_DECLSPEC OBJ_CLASS_DECLARATION(oshmem_request_t);
  36 
  37 /*
  38  * The following include pulls in shared typedefs with debugger plugins.
  39  * For more information on why we do this see the Notice to developers
  40  * comment at the top of the oshmem_msgq_dll.c file.
  41  */
  42 
  43 #include "request_dbg.h"
  44 
  45 struct oshmem_request_t;
  46 
  47 typedef struct oshmem_request_t *SHMEM_Request;
  48 typedef struct oshmem_status_public_t SHMEM_Status;
  49 
  50 /* This constants are used to check status of  request->req_status.SHMEM_ERROR */
  51 #define SHMEM_SUCCESS                   0
  52 #define SHMEM_ERR_IN_STATUS             18
  53 
  54 /*
  55  * SHMEM_Status
  56  */
  57 struct oshmem_status_public_t {
  58     int SHMEM_SOURCE;
  59     /*int MPI_TAG;*/
  60     int SHMEM_ERROR;
  61     int _count;
  62     int _cancelled;
  63 };
  64 typedef struct oshmem_status_public_t oshmem_status_public_t;
  65 
  66 typedef int (SHMEM_Grequest_query_function)(void *, SHMEM_Status *);
  67 typedef int (SHMEM_Grequest_free_function)(void *);
  68 typedef int (SHMEM_Grequest_cancel_function)(void *, int);
  69 
  70 #define SHMEM_REQUEST_NULL OSHMEM_PREDEFINED_GLOBAL(SHMEM_Request, oshmem_request_null)
  71 
  72 /*
  73  * Required function to free the request and any associated resources.
  74  */
  75 typedef int (*oshmem_request_free_fn_t)(struct oshmem_request_t** rptr);
  76 
  77 /*
  78  * Optional function to cancel a pending request.
  79  */
  80 typedef int (*oshmem_request_cancel_fn_t)(struct oshmem_request_t* request,
  81                                           int flag);
  82 
  83 /*
  84  * Optional function called when the request is completed from the SHMEM
  85  * library perspective. This function is not allowed to release any
  86  * ressources related to the request.
  87  */
  88 typedef int (*oshmem_request_complete_fn_t)(struct oshmem_request_t* request);
  89 
  90 /* TODO: decide whether to remove comm */
  91 /**
  92  * Forward declaration
  93  */
  94 struct oshmem_group_t;
  95 
  96 /**
  97  * Forward declaration
  98  */
  99 /*struct oshmem_file_t;*/
 100 
 101 /**
 102  * Union for holding several different SHMEM pointer types on the request
 103  */
 104 typedef union oshmem_shmem_object_t {
 105     struct oshmem_group_t *comm;
 106 /*    struct oshmem_file_t *file;*/
 107 } oshmem_shmem_object_t;
 108 
 109 /**
 110  * Main top-level request struct definition
 111  */
 112 struct oshmem_request_t {
 113     opal_free_list_item_t super; /**< Base type *//*TODO: Implement in shmem */
 114     oshmem_request_type_t req_type; /**< Enum indicating the type of the request */
 115     oshmem_status_public_t req_status; /**< Completion status */
 116     volatile bool req_complete; /**< Flag indicating completion on a request */
 117     volatile oshmem_request_state_t req_state; /**< enum indicate the state of the request */
 118     bool req_persistent; /* TODO: NOT Required */
 119     /**< flag indicating if this is a persistent request */
 120     int req_f_to_c_index; /* TODO: NOT Required */
 121     /**< Index in Fortran <-> C translation array */
 122     oshmem_request_free_fn_t req_free; /**< Called by free */
 123     oshmem_request_cancel_fn_t req_cancel; /* TODO: Not Required */
 124     /**< Optional function to cancel the request */
 125     oshmem_request_complete_fn_t req_complete_cb; /**< Called when the request is SHMEM completed */
 126     void *req_complete_cb_data;
 127     oshmem_shmem_object_t req_shmem_object; /**< Pointer to SHMEM object that created this request */
 128 };
 129 
 130 /**
 131  * Convenience typedef
 132  */
 133 typedef struct oshmem_request_t oshmem_request_t;
 134 
 135 /**
 136  * Padded struct to maintain back compatibiltiy.
 137  * See oshmem/communicator/communicator.h comments with struct oshmem_group_t
 138  * for full explanation why we chose the following padding construct for predefines.
 139  */
 140 #define PREDEFINED_REQUEST_PAD 256
 141 
 142 struct oshmem_predefined_request_t {
 143     struct oshmem_request_t request;
 144     char padding[PREDEFINED_REQUEST_PAD - sizeof(oshmem_request_t)];
 145 };
 146 
 147 typedef struct oshmem_predefined_request_t oshmem_predefined_request_t;
 148 
 149 /**
 150  * Initialize a request.  This is a macro to avoid function call
 151  * overhead, since this is typically invoked in the critical
 152  * performance path (since requests may be re-used, it is possible
 153  * that we will have to initialize a request multiple times).
 154  */
 155 #define OSHMEM_REQUEST_INIT(request, persistent)        \
 156     do {                                              \
 157         (request)->req_complete = false;              \
 158         (request)->req_state = OSHMEM_REQUEST_INACTIVE; \
 159         (request)->req_persistent = (persistent);     \
 160     } while (0);
 161 
 162 /**
 163  * Finalize a request.  This is a macro to avoid function call
 164  * overhead, since this is typically invoked in the critical
 165  * performance path (since requests may be re-used, it is possible
 166  * that we will have to finalize a request multiple times).
 167  *
 168  * When finalizing a request, if MPI_Request_f2c() was previously
 169  * invoked on that request, then this request was added to the f2c
 170  * table, and we need to remove it
 171  *
 172  * This function should be called only from the SHMEM layer. It should
 173  * never be called from the SPML. It take care of the upper level clean-up.
 174  * When the user call MPI_Request_free we should release all SHMEM level
 175  * ressources, so we have to call this function too.
 176  */
 177 #define OSHMEM_REQUEST_FINI(request)                                      \
 178 do {                                                                    \
 179     (request)->req_state = OSHMEM_REQUEST_INVALID;                        \
 180     if (SHMEM_UNDEFINED != (request)->req_f_to_c_index) {                 \
 181         opal_pointer_array_set_item(&oshmem_request_f_to_c_table,         \
 182                                     (request)->req_f_to_c_index, NULL); \
 183         (request)->req_f_to_c_index = SHMEM_UNDEFINED;                    \
 184     }                                                                   \
 185 } while (0);
 186 
 187 /**
 188  * Non-blocking test for request completion.
 189  *
 190  * @param request (IN)   Array of requests
 191  * @param complete (OUT) Flag indicating if index is valid (a request completed).
 192  * @param status (OUT)   Status of completed request.
 193  * @return               OSHMEM_SUCCESS or failure status.
 194  *
 195  * Note that upon completion, the request is freed, and the
 196  * request handle at index set to NULL.
 197  */
 198 typedef int (*oshmem_request_test_fn_t)(oshmem_request_t ** rptr,
 199                                         int *completed,
 200                                         oshmem_status_public_t * status);
 201 /**
 202  * Non-blocking test for request completion.
 203  *
 204  * @param count (IN)     Number of requests
 205  * @param request (IN)   Array of requests
 206  * @param index (OUT)    Index of first completed request.
 207  * @param complete (OUT) Flag indicating if index is valid (a request completed).
 208  * @param status (OUT)   Status of completed request.
 209  * @return               OSHMEM_SUCCESS or failure status.
 210  *
 211  * Note that upon completion, the request is freed, and the
 212  * request handle at index set to NULL.
 213  */
 214 typedef int (*oshmem_request_test_any_fn_t)(size_t count,
 215                                             oshmem_request_t ** requests,
 216                                             int *index,
 217                                             int *completed,
 218                                             oshmem_status_public_t * status);
 219 /**
 220  * Non-blocking test for request completion.
 221  *
 222  * @param count (IN)      Number of requests
 223  * @param requests (IN)   Array of requests
 224  * @param completed (OUT) Flag indicating wether all requests completed.
 225  * @param statuses (OUT)  Array of completion statuses.
 226  * @return                OSHMEM_SUCCESS or failure status.
 227  *
 228  * This routine returns completed==true if all requests have completed.
 229  * The statuses parameter is only updated if all requests completed. Likewise,
 230  * the requests array is not modified (no requests freed), unless all requests
 231  * have completed.
 232  */
 233 typedef int (*oshmem_request_test_all_fn_t)(size_t count,
 234                                             oshmem_request_t ** requests,
 235                                             int *completed,
 236                                             oshmem_status_public_t * statuses);
 237 /**
 238  * Non-blocking test for some of N requests to complete.
 239  *
 240  * @param count (IN)        Number of requests
 241  * @param requests (INOUT)  Array of requests
 242  * @param outcount (OUT)    Number of finished requests
 243  * @param indices (OUT)     Indices of the finished requests
 244  * @param statuses (OUT)    Array of completion statuses.
 245  * @return                  OSHMEM_SUCCESS, OSHMEM_ERR_IN_STATUS or failure status.
 246  *
 247  */
 248 typedef int (*oshmem_request_test_some_fn_t)(size_t count,
 249                                              oshmem_request_t ** requests,
 250                                              int * outcount,
 251                                              int * indices,
 252                                              oshmem_status_public_t * statuses);
 253 /**
 254  * Wait (blocking-mode) for one requests to complete.
 255  *
 256  * @param request (IN)    Pointer to request.
 257  * @param status (OUT)    Status of completed request.
 258  * @return                OSHMEM_SUCCESS or failure status.
 259  *
 260  */
 261 typedef int (*oshmem_request_wait_fn_t)(oshmem_request_t ** req_ptr,
 262                                         oshmem_status_public_t * status);
 263 /**
 264  * Wait (blocking-mode) for one of N requests to complete.
 265  *
 266  * @param count (IN)      Number of requests
 267  * @param requests (IN)   Array of requests
 268  * @param index (OUT)     Index into request array of completed request.
 269  * @param status (OUT)    Status of completed request.
 270  * @return                OSHMEM_SUCCESS or failure status.
 271  *
 272  */
 273 typedef int (*oshmem_request_wait_any_fn_t)(size_t count,
 274                                             oshmem_request_t ** requests,
 275                                             int *index,
 276                                             oshmem_status_public_t * status);
 277 /**
 278  * Wait (blocking-mode) for all of N requests to complete.
 279  *
 280  * @param count (IN)      Number of requests
 281  * @param requests (IN)   Array of requests
 282  * @param statuses (OUT)  Array of completion statuses.
 283  * @return                OSHMEM_SUCCESS or failure status.
 284  *
 285  */
 286 typedef int (*oshmem_request_wait_all_fn_t)(size_t count,
 287                                             oshmem_request_t ** requests,
 288                                             oshmem_status_public_t * statuses);
 289 /**
 290  * Wait (blocking-mode) for some of N requests to complete.
 291  *
 292  * @param count (IN)        Number of requests
 293  * @param requests (INOUT)  Array of requests
 294  * @param outcount (OUT)    Number of finished requests
 295  * @param indices (OUT)     Indices of the finished requests
 296  * @param statuses (OUT)    Array of completion statuses.
 297  * @return                  OSHMEM_SUCCESS, OSHMEM_ERR_IN_STATUS or failure status.
 298  *
 299  */
 300 typedef int (*oshmem_request_wait_some_fn_t)(size_t count,
 301                                              oshmem_request_t ** requests,
 302                                              int * outcount,
 303                                              int * indices,
 304                                              oshmem_status_public_t * statuses);
 305 
 306 /**
 307  * Replaceable request functions
 308  */
 309 typedef struct oshmem_request_fns_t {
 310     oshmem_request_test_fn_t req_test;
 311     oshmem_request_test_any_fn_t req_test_any;
 312     oshmem_request_test_all_fn_t req_test_all;
 313     oshmem_request_test_some_fn_t req_test_some;
 314     oshmem_request_wait_fn_t req_wait;
 315     oshmem_request_wait_any_fn_t req_wait_any;
 316     oshmem_request_wait_all_fn_t req_wait_all;
 317     oshmem_request_wait_some_fn_t req_wait_some;
 318 } oshmem_request_fns_t;
 319 
 320 /**
 321  * Globals used for tracking requests and request completion.
 322  */
 323 OSHMEM_DECLSPEC extern opal_pointer_array_t oshmem_request_f_to_c_table;
 324 OSHMEM_DECLSPEC extern size_t oshmem_request_waiting;
 325 OSHMEM_DECLSPEC extern size_t oshmem_request_completed;
 326 OSHMEM_DECLSPEC extern int32_t oshmem_request_poll;
 327 OSHMEM_DECLSPEC extern opal_mutex_t oshmem_request_lock;
 328 OSHMEM_DECLSPEC extern opal_condition_t oshmem_request_cond;
 329 OSHMEM_DECLSPEC extern oshmem_predefined_request_t oshmem_request_null;
 330 OSHMEM_DECLSPEC extern oshmem_request_t oshmem_request_empty;
 331 OSHMEM_DECLSPEC extern oshmem_status_public_t oshmem_status_empty;
 332 OSHMEM_DECLSPEC extern oshmem_request_fns_t oshmem_request_functions;
 333 
 334 /**
 335  * Initialize the OSHMEM_Request subsystem; invoked during SHMEM_INIT.
 336  */
 337 int oshmem_request_init(void);
 338 
 339 /**
 340  * Free a persistent request to a MPI_PROC_NULL peer (there's no
 341  * freelist to put it back to, so we have to actually OBJ_RELEASE it).
 342  */
 343 OSHMEM_DECLSPEC int oshmem_request_persistent_proc_null_free(oshmem_request_t **request);
 344 
 345 /**
 346  * Shut down the SHMEM_Request subsystem; invoked during SHMEM_FINALIZE.
 347  */
 348 int oshmem_request_finalize(void);
 349 
 350 /**
 351  * Cancel a pending request.
 352  */
 353 static inline int oshmem_request_cancel(oshmem_request_t* request)
 354 {
 355     if (request->req_cancel != NULL ) {
 356         return request->req_cancel(request, true);
 357     }
 358     return OSHMEM_SUCCESS;
 359 }
 360 
 361 /**
 362  * Free a request.
 363  *
 364  * @param request (INOUT)   Pointer to request.
 365  */
 366 static inline int oshmem_request_free(oshmem_request_t** request)
 367 {
 368     return (*request)->req_free(request);
 369 }
 370 
 371 #define oshmem_request_test       (oshmem_request_functions.req_test)
 372 #define oshmem_request_test_any   (oshmem_request_functions.req_test_any)
 373 #define oshmem_request_test_all   (oshmem_request_functions.req_test_all)
 374 #define oshmem_request_test_some  (oshmem_request_functions.req_test_some)
 375 #define oshmem_request_wait       (oshmem_request_functions.req_wait)
 376 #define oshmem_request_wait_any   (oshmem_request_functions.req_wait_any)
 377 #define oshmem_request_wait_all   (oshmem_request_functions.req_wait_all)
 378 #define oshmem_request_wait_some  (oshmem_request_functions.req_wait_some)
 379 
 380 /**
 381  * Wait for any completion. It is a caller responsibility to check for
 382  * condition and call us again if needed.
 383  */
 384 static inline void oshmem_request_wait_any_completion(void)
 385 {
 386     OPAL_THREAD_LOCK(&oshmem_request_lock);
 387     oshmem_request_waiting++;
 388     opal_condition_wait(&oshmem_request_cond, &oshmem_request_lock);
 389     oshmem_request_waiting--;
 390     OPAL_THREAD_UNLOCK(&oshmem_request_lock);
 391 }
 392 
 393 /**
 394  * Wait a particular request for completion
 395  */
 396 static inline void oshmem_request_wait_completion(oshmem_request_t *req)
 397 {
 398     if (false == req->req_complete) {
 399 #if OPAL_ENABLE_PROGRESS_THREADS
 400         if(opal_progress_spin(&req->req_complete)) {
 401             return;
 402         }
 403 #endif
 404         OPAL_THREAD_LOCK(&oshmem_request_lock);
 405         oshmem_request_waiting++;
 406         while (false == req->req_complete) {
 407             opal_condition_wait(&oshmem_request_cond, &oshmem_request_lock);
 408         }
 409         oshmem_request_waiting--;
 410         OPAL_THREAD_UNLOCK(&oshmem_request_lock);
 411     }
 412 }
 413 
 414 /**
 415  *  Signal or mark a request as complete. If with_signal is true this will
 416  *  wake any thread pending on the request and oshmem_request_lock should be
 417  *  held while calling this function. If with_signal is false, there will
 418  *  signal generated, and no lock required. This is a special case when
 419  *  the function is called from the critical path for small messages, where
 420  *  we know the current execution flow created the request, and is still
 421  *  in the _START macro.
 422  */
 423 static inline int oshmem_request_complete(oshmem_request_t* request,
 424                                           bool with_signal)
 425 {
 426     if (NULL != request->req_complete_cb) {
 427         request->req_complete_cb(request);
 428     }
 429     oshmem_request_completed++;
 430     request->req_complete = true;
 431     if (with_signal && oshmem_request_waiting) {
 432         /* Broadcast the condition, otherwise if there is already a thread
 433          * waiting on another request it can use all signals.
 434          */
 435         opal_condition_broadcast(&oshmem_request_cond);
 436     }
 437     return OSHMEM_SUCCESS;
 438 }
 439 
 440 END_C_DECLS
 441 
 442 #endif

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