int psmx_am_process_send(struct psmx_fid_domain *domain, struct psmx_am_request *req) { psm_amarg_t args[8]; int am_flags = PSM_AM_FLAG_ASYNC; int chunk_size; size_t len; uint64_t offset; int err; req->state = PSMX_AM_STATE_PROCESSED; offset = req->send.len_sent; len = req->send.len - offset; chunk_size = MIN(PSMX_AM_CHUNK_SIZE, psmx_am_param.max_request_short); while (len > chunk_size) { args[0].u32w0 = PSMX_AM_REQ_SEND; args[0].u32w1 = chunk_size; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = (uint64_t)(uintptr_t)req->send.peer_context; args[3].u64 = offset; err = psm_am_request_short((psm_epaddr_t) req->send.dest_addr, PSMX_AM_MSG_HANDLER, args, 4, req->send.buf+offset, chunk_size, am_flags | PSM_AM_FLAG_NOREPLY, NULL, NULL); len -= chunk_size; offset += chunk_size; } args[0].u32w0 = PSMX_AM_REQ_SEND | PSMX_AM_EOM; args[0].u32w1 = len; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = (uint64_t)(uintptr_t)req->send.peer_context; args[3].u64 = offset; req->send.len_sent = offset + len; err = psm_am_request_short((psm_epaddr_t) req->send.dest_addr, PSMX_AM_MSG_HANDLER, args, 4, (void *)req->send.buf+offset, len, am_flags, NULL, NULL); free(req); return psmx_errno(err); }
void psmx_am_ack_rma(struct psmx_am_request *req) { psm_amarg_t args[8]; if ((req->op & PSMX_AM_OP_MASK) != PSMX_AM_REQ_WRITE_LONG) return; args[0].u32w0 = PSMX_AM_REP_WRITE | PSMX_AM_EOM; args[0].u32w1 = req->error; args[1].u64 = (uint64_t)(uintptr_t)req->write.peer_context; psm_am_request_short(req->write.peer_addr, PSMX_AM_RMA_HANDLER, args, 2, NULL, 0, PSM_AM_FLAG_NOREPLY, NULL, NULL); }
ssize_t _psmx_writeto(struct fid_ep *ep, const void *buf, size_t len, void *desc, fi_addr_t dest_addr, uint64_t addr, uint64_t key, void *context, uint64_t flags, uint64_t data) { struct psmx_fid_ep *ep_priv; struct psmx_fid_av *av; struct psmx_epaddr_context *epaddr_context; struct psmx_am_request *req; psm_amarg_t args[8]; int nargs; int am_flags = PSM_AM_FLAG_ASYNC; int err; int chunk_size; psm_mq_req_t psm_req; uint64_t psm_tag; size_t idx; if (flags & FI_TRIGGER) { struct psmx_trigger *trigger; struct fi_triggered_context *ctxt = context; trigger = calloc(1, sizeof(*trigger)); if (!trigger) return -ENOMEM; trigger->op = PSMX_TRIGGERED_WRITE; trigger->cntr = container_of(ctxt->threshold.cntr, struct psmx_fid_cntr, cntr); trigger->threshold = ctxt->threshold.threshold; trigger->write.ep = ep; trigger->write.buf = buf; trigger->write.len = len; trigger->write.desc = desc; trigger->write.dest_addr = dest_addr; trigger->write.addr = addr; trigger->write.key = key; trigger->write.context = context; trigger->write.flags = flags & ~FI_TRIGGER; trigger->write.data = data; psmx_cntr_add_trigger(trigger->cntr, trigger); return 0; } ep_priv = container_of(ep, struct psmx_fid_ep, ep); assert(ep_priv->domain); if (!buf) return -EINVAL; av = ep_priv->av; if (av && av->type == FI_AV_TABLE) { idx = dest_addr; if (idx >= av->last) return -EINVAL; dest_addr = (fi_addr_t) av->psm_epaddrs[idx]; } else if (!dest_addr) { return -EINVAL; } epaddr_context = psm_epaddr_getctxt((void *)dest_addr); if (epaddr_context->epid == ep_priv->domain->psm_epid) return psmx_rma_self(PSMX_AM_REQ_WRITE, ep_priv, (void *)buf, len, desc, addr, key, context, flags, data); if (flags & FI_INJECT) { req = malloc(sizeof(*req) + len); if (!req) return -ENOMEM; memset((void *)req, 0, sizeof(*req)); memcpy((void *)req + sizeof(*req), (void *)buf, len); buf = (void *)req + sizeof(*req); PSMX_CTXT_TYPE(&req->fi_context) = PSMX_INJECT_WRITE_CONTEXT; req->no_event = 1; } else { req = calloc(1, sizeof(*req)); if (!req) return -ENOMEM; if (ep_priv->send_cq_event_flag && !(flags & FI_EVENT)) { PSMX_CTXT_TYPE(&req->fi_context) = PSMX_NOCOMP_WRITE_CONTEXT; req->no_event = 1; } else { PSMX_CTXT_TYPE(&req->fi_context) = PSMX_WRITE_CONTEXT; } } req->op = PSMX_AM_REQ_WRITE; req->write.buf = (void *)buf; req->write.len = len; req->write.addr = addr; /* needed? */ req->write.key = key; /* needed? */ req->write.context = context; req->ep = ep_priv; PSMX_CTXT_USER(&req->fi_context) = context; chunk_size = MIN(PSMX_AM_CHUNK_SIZE, psmx_am_param.max_request_short); if (psmx_env.tagged_rma && len > chunk_size) { psm_tag = PSMX_RMA_BIT | ep_priv->domain->psm_epid; args[0].u32w0 = PSMX_AM_REQ_WRITE_LONG; args[0].u32w1 = len; args[1].u64 = (uint64_t)req; args[2].u64 = addr; args[3].u64 = key; args[4].u64 = psm_tag; nargs = 5; if (flags & FI_REMOTE_CQ_DATA) { args[5].u64 = data; args[0].u32w0 |= PSMX_AM_DATA; nargs++; } err = psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_RMA_HANDLER, args, nargs, NULL, 0, am_flags | PSM_AM_FLAG_NOREPLY, NULL, NULL); psm_mq_isend(ep_priv->domain->psm_mq, (psm_epaddr_t) dest_addr, 0, psm_tag, buf, len, (void *)&req->fi_context, &psm_req); return 0; } nargs = 4; while (len > chunk_size) { args[0].u32w0 = PSMX_AM_REQ_WRITE; args[0].u32w1 = chunk_size; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = addr; args[3].u64 = key; err = psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_RMA_HANDLER, args, nargs, (void *)buf, chunk_size, am_flags | PSM_AM_FLAG_NOREPLY, NULL, NULL); buf += chunk_size; addr += chunk_size; len -= chunk_size; } args[0].u32w0 = PSMX_AM_REQ_WRITE | PSMX_AM_EOM; args[0].u32w1 = len; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = addr; args[3].u64 = key; if (flags & FI_REMOTE_CQ_DATA) { args[4].u64 = data; args[0].u32w0 |= PSMX_AM_DATA; nargs++; } err = psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_RMA_HANDLER, args, nargs, (void *)buf, len, am_flags, NULL, NULL); return 0; }
ssize_t _psmx_readfrom(struct fid_ep *ep, void *buf, size_t len, void *desc, fi_addr_t src_addr, uint64_t addr, uint64_t key, void *context, uint64_t flags) { struct psmx_fid_ep *ep_priv; struct psmx_fid_av *av; struct psmx_epaddr_context *epaddr_context; struct psmx_am_request *req; psm_amarg_t args[8]; int err; int chunk_size; size_t offset = 0; uint64_t psm_tag; psm_mq_req_t psm_req; size_t idx; if (flags & FI_TRIGGER) { struct psmx_trigger *trigger; struct fi_triggered_context *ctxt = context; trigger = calloc(1, sizeof(*trigger)); if (!trigger) return -ENOMEM; trigger->op = PSMX_TRIGGERED_READ; trigger->cntr = container_of(ctxt->threshold.cntr, struct psmx_fid_cntr, cntr); trigger->threshold = ctxt->threshold.threshold; trigger->read.ep = ep; trigger->read.buf = buf; trigger->read.len = len; trigger->read.desc = desc; trigger->read.src_addr = src_addr; trigger->read.addr = addr; trigger->read.key = key; trigger->read.context = context; trigger->read.flags = flags & ~FI_TRIGGER; psmx_cntr_add_trigger(trigger->cntr, trigger); return 0; } ep_priv = container_of(ep, struct psmx_fid_ep, ep); assert(ep_priv->domain); if (!buf) return -EINVAL; av = ep_priv->av; if (av && av->type == FI_AV_TABLE) { idx = src_addr; if (idx >= av->last) return -EINVAL; src_addr = (fi_addr_t) av->psm_epaddrs[idx]; } else if (!src_addr) { return -EINVAL; } epaddr_context = psm_epaddr_getctxt((void *)src_addr); if (epaddr_context->epid == ep_priv->domain->psm_epid) return psmx_rma_self(PSMX_AM_REQ_READ, ep_priv, buf, len, desc, addr, key, context, flags, 0); req = calloc(1, sizeof(*req)); if (!req) return -ENOMEM; req->op = PSMX_AM_REQ_READ; req->read.buf = buf; req->read.len = len; req->read.addr = addr; /* needed? */ req->read.key = key; /* needed? */ req->read.context = context; req->ep = ep_priv; PSMX_CTXT_TYPE(&req->fi_context) = PSMX_READ_CONTEXT; PSMX_CTXT_USER(&req->fi_context) = context; if (ep_priv->send_cq_event_flag && !(flags & FI_EVENT)) { PSMX_CTXT_TYPE(&req->fi_context) = PSMX_NOCOMP_READ_CONTEXT; req->no_event = 1; } chunk_size = MIN(PSMX_AM_CHUNK_SIZE, psmx_am_param.max_reply_short); if (psmx_env.tagged_rma && len > chunk_size) { psm_tag = PSMX_RMA_BIT | ep_priv->domain->psm_epid; err = psm_mq_irecv(ep_priv->domain->psm_mq, psm_tag, -1ULL, 0, buf, len, (void *)&req->fi_context, &psm_req); args[0].u32w0 = PSMX_AM_REQ_READ_LONG; args[0].u32w1 = len; args[1].u64 = (uint64_t)req; args[2].u64 = addr; args[3].u64 = key; args[4].u64 = psm_tag; err = psm_am_request_short((psm_epaddr_t) src_addr, PSMX_AM_RMA_HANDLER, args, 5, NULL, 0, PSM_AM_FLAG_NOREPLY, NULL, NULL); return 0; } args[0].u32w0 = PSMX_AM_REQ_READ; args[1].u64 = (uint64_t)(uintptr_t)req; args[3].u64 = key; while (len > chunk_size) { args[0].u32w1 = chunk_size; args[2].u64 = addr; args[4].u64 = offset; err = psm_am_request_short((psm_epaddr_t) src_addr, PSMX_AM_RMA_HANDLER, args, 5, NULL, 0, 0, NULL, NULL); addr += chunk_size; len -= chunk_size; offset += chunk_size; } args[0].u32w0 = PSMX_AM_REQ_READ | PSMX_AM_EOM; args[0].u32w1 = len; args[2].u64 = addr; args[4].u64 = offset; err = psm_am_request_short((psm_epaddr_t) src_addr, PSMX_AM_RMA_HANDLER, args, 5, NULL, 0, 0, NULL, NULL); return 0; }
ssize_t _psmx_atomic_readwrite(struct fid_ep *ep, const void *buf, size_t count, void *desc, void *result, void *result_desc, fi_addr_t dest_addr, uint64_t addr, uint64_t key, enum fi_datatype datatype, enum fi_op op, void *context, uint64_t flags) { struct psmx_fid_ep *ep_priv; struct psmx_fid_av *av; struct psmx_epaddr_context *epaddr_context; struct psmx_am_request *req; psm_amarg_t args[8]; int am_flags = PSM_AM_FLAG_ASYNC; int chunk_size, len; size_t idx; ep_priv = container_of(ep, struct psmx_fid_ep, ep); if (flags & FI_TRIGGER) { struct psmx_trigger *trigger; struct fi_triggered_context *ctxt = context; trigger = calloc(1, sizeof(*trigger)); if (!trigger) return -FI_ENOMEM; trigger->op = PSMX_TRIGGERED_ATOMIC_READWRITE; trigger->cntr = container_of(ctxt->trigger.threshold.cntr, struct psmx_fid_cntr, cntr); trigger->threshold = ctxt->trigger.threshold.threshold; trigger->atomic_readwrite.ep = ep; trigger->atomic_readwrite.buf = buf; trigger->atomic_readwrite.count = count; trigger->atomic_readwrite.desc = desc; trigger->atomic_readwrite.result = result; trigger->atomic_readwrite.result_desc = result_desc; trigger->atomic_readwrite.dest_addr = dest_addr; trigger->atomic_readwrite.addr = addr; trigger->atomic_readwrite.key = key; trigger->atomic_readwrite.datatype = datatype; trigger->atomic_readwrite.atomic_op = op; trigger->atomic_readwrite.context = context; trigger->atomic_readwrite.flags = flags & ~FI_TRIGGER; psmx_cntr_add_trigger(trigger->cntr, trigger); return 0; } if (!buf && op != FI_ATOMIC_READ) return -FI_EINVAL; if (datatype < 0 || datatype >= FI_DATATYPE_LAST) return -FI_EINVAL; if (op < 0 || op >= FI_ATOMIC_OP_LAST) return -FI_EINVAL; av = ep_priv->av; if (av && av->type == FI_AV_TABLE) { idx = dest_addr; if (idx >= av->last) return -FI_EINVAL; dest_addr = (fi_addr_t) av->psm_epaddrs[idx]; } else if (!dest_addr) { return -FI_EINVAL; } epaddr_context = psm_epaddr_getctxt((void *)dest_addr); if (epaddr_context->epid == ep_priv->domain->psm_epid) return psmx_atomic_self(PSMX_AM_REQ_ATOMIC_READWRITE, ep_priv, buf, count, desc, NULL, NULL, result, result_desc, addr, key, datatype, op, context, flags); chunk_size = MIN(PSMX_AM_CHUNK_SIZE, psmx_am_param.max_request_short); len = fi_datatype_size(datatype) * count; if (len > chunk_size) return -FI_EMSGSIZE; if ((flags & FI_INJECT) && op != FI_ATOMIC_READ) { req = malloc(sizeof(*req) + len); if (!req) return -FI_ENOMEM; memset((void *)req, 0, sizeof(*req)); memcpy((void *)req+sizeof(*req), (void *)buf, len); buf = (void *)req + sizeof(*req); } else { req = calloc(1, sizeof(*req)); if (!req) return -FI_ENOMEM; } req->no_event = (flags & PSMX_NO_COMPLETION) || (ep_priv->send_selective_completion && !(flags & FI_COMPLETION)); req->op = PSMX_AM_REQ_ATOMIC_READWRITE; req->atomic.buf = (void *)buf; req->atomic.len = len; req->atomic.addr = addr; req->atomic.key = key; req->atomic.context = context; req->atomic.result = result; req->ep = ep_priv; if (op == FI_ATOMIC_READ) req->cq_flags = FI_READ | FI_ATOMIC; else req->cq_flags = FI_WRITE | FI_ATOMIC; args[0].u32w0 = PSMX_AM_REQ_ATOMIC_READWRITE; args[0].u32w1 = count; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = addr; args[3].u64 = key; args[4].u32w0 = datatype; args[4].u32w1 = op; psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_ATOMIC_HANDLER, args, 5, (void *)buf, (buf?len:0), am_flags, NULL, NULL); return 0; }
ssize_t _psmx_write(struct fid_ep *ep, const void *buf, size_t len, void *desc, fi_addr_t dest_addr, uint64_t addr, uint64_t key, void *context, uint64_t flags, uint64_t data) { struct psmx_fid_ep *ep_priv; struct psmx_fid_av *av; struct psmx_epaddr_context *epaddr_context; struct psmx_am_request *req; psm_amarg_t args[8]; int nargs; int am_flags = PSM_AM_FLAG_ASYNC; int chunk_size; psm_mq_req_t psm_req; uint64_t psm_tag; size_t idx; void *psm_context; int no_event; ep_priv = container_of(ep, struct psmx_fid_ep, ep); if (flags & FI_TRIGGER) { struct psmx_trigger *trigger; struct fi_triggered_context *ctxt = context; trigger = calloc(1, sizeof(*trigger)); if (!trigger) return -FI_ENOMEM; trigger->op = PSMX_TRIGGERED_WRITE; trigger->cntr = container_of(ctxt->trigger.threshold.cntr, struct psmx_fid_cntr, cntr); trigger->threshold = ctxt->trigger.threshold.threshold; trigger->write.ep = ep; trigger->write.buf = buf; trigger->write.len = len; trigger->write.desc = desc; trigger->write.dest_addr = dest_addr; trigger->write.addr = addr; trigger->write.key = key; trigger->write.context = context; trigger->write.flags = flags & ~FI_TRIGGER; trigger->write.data = data; psmx_cntr_add_trigger(trigger->cntr, trigger); return 0; } if (!buf) return -FI_EINVAL; av = ep_priv->av; if (av && av->type == FI_AV_TABLE) { idx = dest_addr; if (idx >= av->last) return -FI_EINVAL; dest_addr = (fi_addr_t) av->psm_epaddrs[idx]; } else if (!dest_addr) { return -FI_EINVAL; } epaddr_context = psm_epaddr_getctxt((void *)dest_addr); if (epaddr_context->epid == ep_priv->domain->psm_epid) return psmx_rma_self(PSMX_AM_REQ_WRITE, ep_priv, (void *)buf, len, desc, addr, key, context, flags, data); no_event = (flags & PSMX_NO_COMPLETION) || (ep_priv->send_selective_completion && !(flags & FI_COMPLETION)); if (flags & FI_INJECT) { if (len > PSMX_INJECT_SIZE) return -FI_EMSGSIZE; req = malloc(sizeof(*req) + len); if (!req) return -FI_ENOMEM; memset((void *)req, 0, sizeof(*req)); memcpy((void *)req + sizeof(*req), (void *)buf, len); buf = (void *)req + sizeof(*req); } else { req = calloc(1, sizeof(*req)); if (!req) return -FI_ENOMEM; PSMX_CTXT_TYPE(&req->fi_context) = no_event ? PSMX_NOCOMP_WRITE_CONTEXT : PSMX_WRITE_CONTEXT; } req->no_event = no_event; req->op = PSMX_AM_REQ_WRITE; req->write.buf = (void *)buf; req->write.len = len; req->write.addr = addr; /* needed? */ req->write.key = key; /* needed? */ req->write.context = context; req->ep = ep_priv; req->cq_flags = FI_WRITE | FI_RMA; PSMX_CTXT_USER(&req->fi_context) = context; PSMX_CTXT_EP(&req->fi_context) = ep_priv; chunk_size = MIN(PSMX_AM_CHUNK_SIZE, psmx_am_param.max_request_short); if (psmx_env.tagged_rma && len > chunk_size) { void *payload = NULL; int payload_len = 0; psm_tag = PSMX_RMA_BIT | ep_priv->domain->psm_epid; args[0].u32w0 = PSMX_AM_REQ_WRITE_LONG; args[0].u32w1 = len; args[1].u64 = (uint64_t)req; args[2].u64 = addr; args[3].u64 = key; args[4].u64 = psm_tag; nargs = 5; if (flags & FI_REMOTE_CQ_DATA) { args[0].u32w0 |= PSMX_AM_DATA; payload = &data; payload_len = sizeof(data); am_flags = 0; } if (flags & FI_DELIVERY_COMPLETE) { args[0].u32w0 |= PSMX_AM_FORCE_ACK; psm_context = NULL; } else { psm_context = (void *)&req->fi_context; } /* NOTE: if nargs is greater than 5, the following psm_mq_isend * would hang if the destination is on the same node (i.e. going * through the shared memory path). As the result, the immediate * data is sent as payload instead of args[5]. */ psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_RMA_HANDLER, args, nargs, payload, payload_len, am_flags, NULL, NULL); psm_mq_isend(ep_priv->domain->psm_mq, (psm_epaddr_t) dest_addr, 0, psm_tag, buf, len, psm_context, &psm_req); return 0; } nargs = 4; while (len > chunk_size) { args[0].u32w0 = PSMX_AM_REQ_WRITE; args[0].u32w1 = chunk_size; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = addr; args[3].u64 = key; psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_RMA_HANDLER, args, nargs, (void *)buf, chunk_size, am_flags, NULL, NULL); buf += chunk_size; addr += chunk_size; len -= chunk_size; } args[0].u32w0 = PSMX_AM_REQ_WRITE | PSMX_AM_EOM; args[0].u32w1 = len; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = addr; args[3].u64 = key; if (flags & FI_REMOTE_CQ_DATA) { args[4].u64 = data; args[0].u32w0 |= PSMX_AM_DATA; nargs++; } psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_RMA_HANDLER, args, nargs, (void *)buf, len, am_flags, NULL, NULL); return 0; }
static ssize_t _psmx_send2(struct fid_ep *ep, const void *buf, size_t len, void *desc, fi_addr_t dest_addr, void *context, uint64_t flags) { struct psmx_fid_ep *ep_priv; struct psmx_fid_av *av; struct psmx_am_request *req; psm_amarg_t args[8]; int am_flags = PSM_AM_FLAG_ASYNC; int err; int chunk_size, msg_size; size_t idx; ep_priv = container_of(ep, struct psmx_fid_ep, ep); if (!buf) return -FI_EINVAL; av = ep_priv->av; if (av && av->type == FI_AV_TABLE) { idx = dest_addr; if (idx >= av->last) return -FI_EINVAL; dest_addr = (fi_addr_t) av->psm_epaddrs[idx]; } else if (!dest_addr) { return -FI_EINVAL; } chunk_size = MIN(PSMX_AM_CHUNK_SIZE, psmx_am_param.max_request_short); msg_size = MIN(len, chunk_size); req = calloc(1, sizeof(*req)); if (!req) return -FI_ENOMEM; req->op = PSMX_AM_REQ_SEND; req->send.buf = (void *)buf; req->send.len = len; req->send.context = context; req->send.len_sent = msg_size; req->send.dest_addr = (void *)dest_addr; req->ep = ep_priv; req->cq_flags = FI_SEND | FI_MSG; if ((flags & PSMX_NO_COMPLETION) || (ep_priv->send_selective_completion && !(flags & FI_COMPLETION))) req->no_event = 1; args[0].u32w0 = PSMX_AM_REQ_SEND | (msg_size == len ? PSMX_AM_EOM : 0); args[0].u32w1 = msg_size; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = 0; args[3].u64 = 0; err = psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_MSG_HANDLER, args, 4, (void *)buf, msg_size, am_flags, NULL, NULL); return psmx_errno(err); }
static ssize_t _psmx_recv2(struct fid_ep *ep, void *buf, size_t len, void *desc, fi_addr_t src_addr, void *context, uint64_t flags) { psm_amarg_t args[8]; struct psmx_fid_ep *ep_priv; struct psmx_fid_av *av; struct psmx_am_request *req; struct psmx_unexp *unexp; struct psmx_cq_event *event; int recv_done; int err = 0; size_t idx; ep_priv = container_of(ep, struct psmx_fid_ep, ep); if ((ep_priv->caps & FI_DIRECTED_RECV) && src_addr != FI_ADDR_UNSPEC) { av = ep_priv->av; if (av && av->type == FI_AV_TABLE) { idx = (size_t)src_addr; if (idx >= av->last) return -FI_EINVAL; src_addr = (fi_addr_t)av->psm_epaddrs[idx]; } } else { src_addr = 0; } req = calloc(1, sizeof(*req)); if (!req) return -FI_ENOMEM; req->op = PSMX_AM_REQ_SEND; req->recv.buf = (void *)buf; req->recv.len = len; req->recv.context = context; req->recv.src_addr = (void *)src_addr; req->ep = ep_priv; req->cq_flags = FI_RECV | FI_MSG; if (ep_priv->recv_selective_completion && !(flags & FI_COMPLETION)) req->no_event = 1; unexp = psmx_am_search_and_dequeue_unexp(ep_priv->domain, (const void *)src_addr); if (!unexp) { psmx_am_enqueue_recv(ep_priv->domain, req); return 0; } req->recv.len_received = MIN(req->recv.len, unexp->len_received); memcpy(req->recv.buf, unexp->buf, req->recv.len_received); recv_done = (req->recv.len_received >= req->recv.len); if (unexp->done) { recv_done = 1; } else { args[0].u32w0 = PSMX_AM_REP_SEND; args[0].u32w1 = 0; args[1].u64 = unexp->sender_context; args[2].u64 = recv_done ? 0 : (uint64_t)(uintptr_t)req; err = psm_am_request_short(unexp->sender_addr, PSMX_AM_MSG_HANDLER, args, 3, NULL, 0, 0, NULL, NULL ); } free(unexp); if (recv_done) { if (req->ep->recv_cq && !req->no_event) { event = psmx_cq_create_event( req->ep->recv_cq, req->recv.context, req->recv.buf, req->cq_flags, req->recv.len_received, 0, /* data */ 0, /* tag */ req->recv.len - req->recv.len_received, 0 /* err */); if (event) psmx_cq_enqueue_event(req->ep->recv_cq, event); else err = -FI_ENOMEM; } if (req->ep->recv_cntr) psmx_cntr_inc(req->ep->recv_cntr); free(req); } return err; }
static ssize_t _psmx_sendto2(struct fid_ep *ep, const void *buf, size_t len, void *desc, fi_addr_t dest_addr, void *context, uint64_t flags) { struct psmx_fid_ep *ep_priv; struct psmx_fid_av *av; struct psmx_am_request *req; psm_amarg_t args[8]; int am_flags = PSM_AM_FLAG_ASYNC; int err; int chunk_size, msg_size; size_t idx; ep_priv = container_of(ep, struct psmx_fid_ep, ep); assert(ep_priv->domain); if (!buf) return -EINVAL; av = ep_priv->av; if (av && av->type == FI_AV_TABLE) { idx = dest_addr; if (idx >= av->last) return -EINVAL; dest_addr = (fi_addr_t) av->psm_epaddrs[idx]; } else if (!dest_addr) { return -EINVAL; } chunk_size = MIN(PSMX_AM_CHUNK_SIZE, psmx_am_param.max_request_short); msg_size = MIN(len, chunk_size); req = calloc(1, sizeof(*req)); if (!req) return -ENOMEM; req->op = PSMX_AM_REQ_SEND; req->send.buf = (void *)buf; req->send.len = len; req->send.context = context; req->send.len_sent = msg_size; req->send.dest_addr = (void *)dest_addr; req->ep = ep_priv; if ((ep_priv->send_cq_event_flag && !(flags & FI_EVENT)) || (context == &ep_priv->sendimm_context)) req->no_event = 1; args[0].u32w0 = PSMX_AM_REQ_SEND | (msg_size == len ? PSMX_AM_EOM : 0); args[0].u32w1 = msg_size; args[1].u64 = (uint64_t)(uintptr_t)req; args[2].u64 = 0; args[3].u64 = 0; err = psm_am_request_short((psm_epaddr_t) dest_addr, PSMX_AM_MSG_HANDLER, args, 4, (void *)buf, msg_size, am_flags, NULL, NULL); #if ! PSMX_AM_USE_SEND_QUEUE if (len > msg_size) { while (!req->send.peer_ready) psm_poll(ep_priv->domain->psm_ep); psmx_am_process_send(ep_priv->domain, req); } #endif return psmx_errno(err); }