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