1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 #include "ofi_impl.h"
7 
8 #define NORMAL_PEEK    0
9 #define CLAIM_PEEK     1
10 
11 /* ------------------------------------------------------------------------ */
12 /* This routine looks up the request that contains a context object         */
13 /* ------------------------------------------------------------------------ */
context_to_req(void * ofi_context)14 static inline MPIR_Request *context_to_req(void *ofi_context)
15 {
16     return (MPIR_Request *) MPL_container_of(ofi_context, MPIR_Request, ch.netmod_area.padding);
17 }
18 
19 #define ADD_SUFFIX(name) name
20 #undef API_SET
21 #define API_SET API_SET_1
22 #include "ofi_probe_template.c"
23 #undef ADD_SUFFIX
24 #define ADD_SUFFIX(name) name##_2
25 #undef API_SET
26 #define API_SET API_SET_2
27 #include "ofi_probe_template.c"
28 
29 
MPID_nem_ofi_poll(int in_blocking_poll)30 int MPID_nem_ofi_poll(int in_blocking_poll)
31 {
32     int complete = 0, mpi_errno = MPI_SUCCESS;
33     ssize_t ret;
34     cq_tagged_entry_t wc;
35     cq_err_entry_t error;
36     MPIDI_VC_t *vc;
37     MPIR_Request *req;
38     req_fn reqFn;
39     MPIR_FUNC_VERBOSE_STATE_DECL(MPID_STATE_MPID_NEM_OFI_POLL);
40     MPIR_FUNC_VERBOSE_ENTER(MPID_STATE_MPID_NEM_OFI_POLL);
41     do {
42         /* ----------------------------------------------------- */
43         /* Poll the completion queue                             */
44         /* The strategy here is                                  */
45         /* ret>0 successfull poll, events returned               */
46         /* ret==0 empty poll, no events/no error                 */
47         /* ret<0, error, but some error instances should not     */
48         /* cause MPI to terminate                                */
49         /* ----------------------------------------------------- */
50         ret = fi_cq_read(gl_data.cq,    /* Tagged completion queue       */
51                          (void *) &wc,  /* OUT:  Tagged completion entry */
52                          1);    /* Number of entries to poll     */
53         if (ret > 0) {
54             if (NULL != wc.op_context) {
55                 req = context_to_req(wc.op_context);
56                 if (REQ_OFI(req)->event_callback) {
57                     MPIDI_CH3I_NM_OFI_RC(REQ_OFI(req)->event_callback(&wc, req));
58                     continue;
59                 }
60                 reqFn = req->dev.OnDataAvail;
61                 if (reqFn) {
62                     MPL_free(REQ_OFI(req)->pack_buffer);
63                     vc = REQ_OFI(req)->vc;
64 
65                     complete = 0;
66                     MPIDI_CH3I_NM_OFI_RC(reqFn(vc, req, &complete));
67                     continue;
68                 } else {
69                     MPIR_Assert(0);
70                 }
71             } else {
72                 MPIR_Assert(0);
73             }
74         } else if (ret == -FI_EAGAIN);
75         else if (ret < 0) {
76             if (ret == -FI_EAVAIL) {
77                 ret = fi_cq_readerr(gl_data.cq, (void *) &error, 0);
78                 if (error.err == FI_ETRUNC) {
79                     /* ----------------------------------------------------- */
80                     /* This error message should only be delivered on send   */
81                     /* events.  We want to ignore truncation errors          */
82                     /* on the sender side, but complete the request anyway   */
83                     /* Other kinds of requests, this is fatal.               */
84                     /* ----------------------------------------------------- */
85                     req = context_to_req(error.op_context);
86                     if (req->kind == MPIR_REQUEST_KIND__SEND) {
87                         mpi_errno = REQ_OFI(req)->event_callback(NULL, req);
88                     } else if (req->kind == MPIR_REQUEST_KIND__RECV) {
89                         mpi_errno = REQ_OFI(req)->event_callback(&wc, req);
90                         req->status.MPI_ERROR = MPI_ERR_TRUNCATE;
91                         req->status.MPI_TAG = error.tag;
92                     } else {
93                         mpi_errno = MPI_ERR_OTHER;
94                     }
95                 } else if (error.err == FI_ECANCELED) {
96                     req = context_to_req(error.op_context);
97                     MPIR_STATUS_SET_CANCEL_BIT(req->status, TRUE);
98                 } else if (error.err == FI_ENOMSG) {
99                     req = context_to_req(error.op_context);
100                     REQ_OFI(req)->match_state = PEEK_NOT_FOUND;
101                 } else {
102                     mpi_errno = MPI_ERR_OTHER;
103                 }
104             } else {
105                 MPIR_ERR_CHKANDJUMP4(1, mpi_errno, MPI_ERR_OTHER, "**ofi_poll",
106                                      "**ofi_poll %s %d %s %s", __SHORT_FILE__,
107                                      __LINE__, __func__, fi_strerror(-ret));
108             }
109         }
110     } while (in_blocking_poll && (ret > 0));
111   fn_exit:
112     MPIR_FUNC_VERBOSE_EXIT(MPID_STATE_MPID_NEM_OFI_POLL);
113     return mpi_errno;
114   fn_fail:
115     goto fn_exit;
116 }
117