int psmx_eq_poll_mq(struct psmx_fid_eq *eq, struct psmx_fid_domain *domain_if_null_eq) { psm_mq_req_t psm_req; psm_mq_status_t psm_status; struct fi_context *fi_context; struct psmx_fid_domain *domain; struct psmx_fid_ep *tmp_ep; struct psmx_fid_eq *tmp_eq; struct psmx_fid_cntr *tmp_cntr; struct psmx_event *event; int multi_recv; int err; if (eq) domain = eq->domain; else domain = domain_if_null_eq; while (1) { err = psm_mq_ipeek(domain->psm_mq, &psm_req, NULL); if (err == PSM_OK) { err = psm_mq_test(&psm_req, &psm_status); fi_context = psm_status.context; tmp_ep = PSMX_CTXT_EP(fi_context); tmp_eq = NULL; tmp_cntr = NULL; multi_recv = 0; switch (PSMX_CTXT_TYPE(fi_context)) { case PSMX_NOCOMP_SEND_CONTEXT: tmp_ep->pending_sends--; if (!tmp_ep->send_cntr_event_flag) tmp_cntr = tmp_ep->send_cntr; break; case PSMX_NOCOMP_RECV_CONTEXT: if (!tmp_ep->recv_cntr_event_flag) tmp_cntr = tmp_ep->recv_cntr; break; case PSMX_NOCOMP_WRITE_CONTEXT: tmp_ep->pending_writes--; if (!tmp_ep->write_cntr_event_flag) tmp_cntr = tmp_ep->write_cntr; break; case PSMX_NOCOMP_READ_CONTEXT: tmp_ep->pending_reads--; if (!tmp_ep->read_cntr_event_flag) tmp_cntr = tmp_ep->read_cntr; break; case PSMX_INJECT_CONTEXT: tmp_ep->pending_sends--; if (!tmp_ep->send_cntr_event_flag) tmp_cntr = tmp_ep->send_cntr; free(fi_context); break; case PSMX_INJECT_WRITE_CONTEXT: tmp_ep->pending_writes--; if (!tmp_ep->write_cntr_event_flag) tmp_cntr = tmp_ep->write_cntr; free(fi_context); break; case PSMX_SEND_CONTEXT: tmp_ep->pending_sends--; tmp_eq = tmp_ep->send_eq; tmp_cntr = tmp_ep->send_cntr; break; case PSMX_RECV_CONTEXT: tmp_eq = tmp_ep->recv_eq; tmp_cntr = tmp_ep->recv_cntr; break; case PSMX_MULTI_RECV_CONTEXT: multi_recv = 1; tmp_eq = tmp_ep->recv_eq; tmp_cntr = tmp_ep->recv_cntr; break; case PSMX_READ_CONTEXT: tmp_ep->pending_reads--; tmp_eq = tmp_ep->send_eq; tmp_cntr = tmp_ep->read_cntr; break; case PSMX_WRITE_CONTEXT: tmp_ep->pending_writes--; tmp_eq = tmp_ep->send_eq; tmp_cntr = tmp_ep->write_cntr; break; } if (tmp_eq) { event = psmx_eq_create_event_from_status(tmp_eq, &psm_status); if (!event) return -ENOMEM; psmx_eq_enqueue_event(tmp_eq, event); } if (tmp_cntr) tmp_cntr->cntr.ops->add(&tmp_cntr->cntr, 1); if (multi_recv) { struct psmx_multi_recv *req; psm_mq_req_t psm_req; req = PSMX_CTXT_USER(fi_context); req->offset += psm_status.nbytes; if (req->offset + req->min_buf_size <= req->len) { err = psm_mq_irecv(tmp_ep->domain->psm_mq, req->tag, req->tagsel, req->flag, req->buf + req->offset, req->len - req->offset, (void *)fi_context, &psm_req); if (err != PSM_OK) return psmx_errno(err); PSMX_CTXT_REQ(fi_context) = psm_req; } else { if (tmp_eq) { event = psmx_eq_create_event( tmp_eq, req->context, req->buf, FI_MULTI_RECV, req->len, req->len - req->offset, /* data */ 0, /* tag */ 0, /* olen */ 0); /* err */ if (!event) return -ENOMEM; psmx_eq_enqueue_event(tmp_eq, event); } free(req); } } if (!eq || tmp_eq == eq) return 1; } else if (err == PSM_MQ_NO_COMPLETIONS) { return 0; } else { return psmx_errno(err); } } }
static int psmx_av_insert(struct fid_av *av, const void *addr, size_t count, fi_addr_t *fi_addr, uint64_t flags, void *context) { struct psmx_fid_av *av_priv; psm_error_t *errors; int error_count = 0; int *mask; int i, j; fi_addr_t *result = NULL; struct psmx_epaddr_context *epaddr_context; struct psmx_eq_event *event; av_priv = container_of(av, struct psmx_fid_av, av); if ((av_priv->flags & FI_EVENT) && !av_priv->eq) return -FI_ENOEQ; errors = (psm_error_t *) calloc(count, sizeof *errors); if (!errors) return -FI_ENOMEM; mask = (int *) calloc(count, sizeof *mask); if (!mask) { free(errors); return -FI_ENOMEM; } if (av_priv->type == FI_AV_TABLE) { if (psmx_av_check_table_size(av_priv, count)) { free(mask); free(errors); return -FI_ENOMEM; } for (i=0; i<count; i++) av_priv->psm_epids[av_priv->last + i] = ((psm_epid_t *)addr)[i]; result = fi_addr; addr = (const void *)(av_priv->psm_epids + av_priv->last); fi_addr = (fi_addr_t *)(av_priv->psm_epaddrs + av_priv->last); } /* prevent connecting to the same ep twice, which is fatal in PSM */ for (i=0; i<count; i++) { psm_epconn_t epconn; if (psm_ep_epid_lookup(((psm_epid_t *) addr)[i], &epconn) == PSM_OK) { epaddr_context = psm_epaddr_getctxt(epconn.addr); if (epaddr_context && epaddr_context->epid == ((psm_epid_t *) addr)[i]) ((psm_epaddr_t *) fi_addr)[i] = epconn.addr; else mask[i] = 1; } else { mask[i] = 1; } } psm_ep_connect(av_priv->domain->psm_ep, count, (psm_epid_t *) addr, mask, errors, (psm_epaddr_t *) fi_addr, 30*1e9); for (i=0; i<count; i++){ if (!mask[i]) continue; if (errors[i] == PSM_OK || errors[i] == PSM_EPID_ALREADY_CONNECTED) { psmx_set_epaddr_context(av_priv->domain, ((psm_epid_t *) addr)[i], ((psm_epaddr_t *) fi_addr)[i]); } else { FI_INFO(&psmx_prov, FI_LOG_AV, "%d: psm_ep_connect returned %s. remote epid=%lx.\n", i, psm_error_get_string(errors[i]), ((psm_epid_t *)addr)[i]); if (((psm_epid_t *)addr)[i] == 0) FI_INFO(&psmx_prov, FI_LOG_AV, "does the application depend on the provider" "to resolve IP address into endpoint id? if so" "check if the name server has started correctly" "at the other side.\n"); fi_addr[i] = FI_ADDR_NOTAVAIL; error_count++; if (av_priv->flags & FI_EVENT) { event = psmx_eq_create_event(av_priv->eq, FI_AV_COMPLETE, /* event */ context, /* context */ i, /* data: failed index */ psmx_errno(errors[i]), /* err */ errors[i], /* prov_errno */ NULL, /* err_data */ 0); /* err_data_size */ if (!event) return -FI_ENOMEM; psmx_eq_enqueue_event(av_priv->eq, event); } } } free(mask); free(errors); if (av_priv->type == FI_AV_TABLE) { /* NOTE: unresolved addresses are left in the AV table */ if (result) { for (i=0; i<count; i++) { j = av_priv->last + i; if ((fi_addr_t)av_priv->psm_epaddrs[j] == FI_ADDR_NOTAVAIL) result[i] = FI_ADDR_NOTAVAIL; else result[i] = j; } } av_priv->last += count; } if (!(av_priv->flags & FI_EVENT)) return count - error_count; event = psmx_eq_create_event(av_priv->eq, FI_AV_COMPLETE, /* event */ context, /* context */ count - error_count, /* data: succ count */ 0, /* err */ 0, /* prov_errno */ NULL, /* err_data */ 0); /* err_data_size */ if (!event) return -FI_ENOMEM; psmx_eq_enqueue_event(av_priv->eq, event); return 0; }