in prov/psm2/src/psmx2_rma.c [420:575]
static ssize_t psmx2_rma_self(int am_cmd,
struct psmx2_fid_ep *ep,
void *buf, size_t len, void *desc,
uint64_t addr, uint64_t key,
void *context, uint64_t flags, uint64_t data)
{
struct psmx2_fid_mr *mr;
struct psmx2_cq_event *event;
struct psmx2_fid_cntr *cntr = NULL;
struct psmx2_fid_cntr *mr_cntr = NULL;
struct psmx2_fid_cq *cq = NULL;
int no_event;
int err = 0;
int op_error = 0;
int access;
uint8_t *dst, *src;
uint64_t cq_flags;
struct iovec *iov = buf;
size_t iov_count = len;
int i;
switch (am_cmd) {
case PSMX2_AM_REQ_WRITE:
access = FI_REMOTE_WRITE;
cq_flags = FI_WRITE | FI_RMA;
break;
case PSMX2_AM_REQ_WRITEV:
access = FI_REMOTE_WRITE;
cq_flags = FI_WRITE | FI_RMA;
len = 0;
for (i=0; i<iov_count; i++)
len += iov[i].iov_len;
break;
case PSMX2_AM_REQ_READ:
access = FI_REMOTE_READ;
cq_flags = FI_READ | FI_RMA;
break;
case PSMX2_AM_REQ_READV:
access = FI_REMOTE_READ;
cq_flags = FI_READ | FI_RMA;
len = 0;
for (i=0; i<iov_count; i++)
len += iov[i].iov_len;
break;
default:
return -FI_EINVAL;
}
mr = psmx2_mr_get(ep->domain, key);
op_error = mr ? psmx2_mr_validate(mr, addr, len, access) : -FI_EINVAL;
if (!op_error) {
addr += mr->offset;
switch (am_cmd) {
case PSMX2_AM_REQ_WRITE:
cntr = ep->remote_write_cntr;
if (flags & FI_REMOTE_CQ_DATA)
cq = ep->recv_cq;
if (mr->cntr != cntr)
mr_cntr = mr->cntr;
memcpy((void *)addr, buf, len);
break;
case PSMX2_AM_REQ_WRITEV:
cntr = ep->remote_write_cntr;
if (flags & FI_REMOTE_CQ_DATA)
cq = ep->recv_cq;
if (mr->cntr != cntr)
mr_cntr = mr->cntr;
dst = (void *)addr;
for (i=0; i<iov_count; i++)
if (iov[i].iov_len) {
memcpy(dst, iov[i].iov_base, iov[i].iov_len);
dst += iov[i].iov_len;
}
break;
case PSMX2_AM_REQ_READ:
cntr = ep->remote_read_cntr;
memcpy(buf, (void *)addr, len);
break;
case PSMX2_AM_REQ_READV:
cntr = ep->remote_read_cntr;
src = (void *)addr;
for (i=0; i<iov_count; i++)
if (iov[i].iov_len) {
memcpy(iov[i].iov_base, src, iov[i].iov_len);
src += iov[i].iov_len;
}
break;
}
if (cq) {
event = psmx2_cq_create_event(
cq,
0, /* context */
(void *)addr,
FI_REMOTE_WRITE | FI_RMA | FI_REMOTE_CQ_DATA,
len,
data,
0, /* tag */
0, /* olen */
0 /* err */);
if (event)
psmx2_cq_enqueue_event(cq, event);
else
err = -FI_ENOMEM;
}
if (ep->caps & FI_RMA_EVENT) {
if (cntr)
psmx2_cntr_inc(cntr, 0);
if (mr_cntr)
psmx2_cntr_inc(mr_cntr, 0);
}
}
no_event = (flags & PSMX2_NO_COMPLETION) ||
(ep->send_selective_completion && !(flags & FI_COMPLETION));
if (ep->send_cq && (!no_event || op_error)) {
event = psmx2_cq_create_event(
ep->send_cq,
context,
(void *)buf,
cq_flags,
len,
0, /* data */
0, /* tag */
0, /* olen */
op_error);
if (event)
psmx2_cq_enqueue_event(ep->send_cq, event);
else
err = -FI_ENOMEM;
}
switch (am_cmd) {
case PSMX2_AM_REQ_WRITE:
case PSMX2_AM_REQ_WRITEV:
if (ep->write_cntr)
psmx2_cntr_inc(ep->write_cntr, op_error);
break;
case PSMX2_AM_REQ_READ:
case PSMX2_AM_REQ_READV:
if (ep->read_cntr)
psmx2_cntr_inc(ep->read_cntr, op_error);
break;
}
return err;
}