/* Process a mq_status. return 1, if a read made progress. 0 else */ static int pscom_psm_process(psm_mq_status_t *status) { uintptr_t c = (uintptr_t)status->context & 7; pspsm_con_info_t *ci = (pspsm_con_info_t *)((uintptr_t)status->context & ~(uintptr_t)7); pscom_con_t *con = ci->con; assert(ci->magic == UINTMAX_C(0xdeadbeefcafebabe)); switch (c) { case 0: /* first send request */ assert(ci->sreqs[0] != PSM_MQ_REQINVALID); poll_user_dec(); ci->sreqs[0] = PSM_MQ_REQINVALID; /* pspsm_dprint(0, "Send0 done %p len %d con %s\n", ci->iov[0].iov_base, (int)ci->iov[0].iov_len, ci->con->pub.remote_con_info.name); */ if (ci->sreqs[1] == PSM_MQ_REQINVALID){ pscom_write_done(con, ci->req, ci->iov[0].iov_len + ci->iov[1].iov_len); ci->req = NULL; } break; case 1: /* second send request */ assert(ci->sreqs[1] != PSM_MQ_REQINVALID); poll_user_dec(); ci->sreqs[1] = PSM_MQ_REQINVALID; /* pspsm_dprint(0, "Send1 done %p len %d con %s\n", ci->iov[1].iov_base, (int)ci->iov[1].iov_len, ci->con->pub.remote_con_info.name); */ if (ci->sreqs[0] == PSM_MQ_REQINVALID){ pscom_write_done(con, ci->req, ci->iov[0].iov_len + ci->iov[1].iov_len); ci->req = NULL; } break; case 2: /* receive request */ assert(ci->rbuf); assert(status->msg_length == status->nbytes); ci->rreq = PSM_MQ_REQINVALID; /* pspsm_dprint(0, "read done %p len %d con %s\n", ci->rbuf, (int)status->msg_length, ci->con->pub.remote_con_info.name); */ pscom_read_done_unlock(con, ci->rbuf, status->msg_length); ci->rbuf = NULL; if (con->arch.psm.reading) { /* There is more to read. Post the next receive request */ pscom_psm_do_read(con); } return 1; break; default: /* this shouldn't happen */ assert(0); } return 0; }
static void pscom_openib_do_write(pscom_con_t *con) { size_t len; struct iovec iov[2]; pscom_req_t *req; req = pscom_write_get_iov(con, iov); if (req) { psoib_con_info_t *mcon = con->arch.openib.mcon; len = iov[0].iov_len + iov[1].iov_len; perf_add("openib_sendv"); ssize_t rlen = psoib_sendv(mcon, iov, len); if (rlen >= 0) { pscom_write_done(con, req, rlen); pscom_check_cq_poll(); } else if ((rlen == -EINTR) || (rlen == -EAGAIN)) { // Busy: Maybe out of tokens? try to read more tokens: _pscom_openib_do_read(con, mcon); } else { // Error pscom_con_error(con, PSCOM_OP_WRITE, PSCOM_ERR_STDERROR); } } }
static void pscom_psm_do_write(pscom_con_t *con) { pspsm_con_info_t *ci = con->arch.psm.ci; if (ci->req) { /* send in progress. wait for completion before transmiting the next message. */ return; } /* FIXME: we might want to send more than one message at a time. */ /* get and post a new write request */ pscom_req_t *req = pscom_write_get_iov(con, ci->iov); if (req) { int ret = pspsm_sendv(ci); if (ret == 0){ /* was a direct send */ size_t size = ci->iov[0].iov_len + ci->iov[1].iov_len; pscom_write_done(con, req, size); } else if (ret == -EAGAIN){ /* pspsm_sendv was successful */ ci->req = req; } else if (ret == -EPIPE){ errno = -ret; pscom_con_error(con, PSCOM_OP_WRITE, PSCOM_ERR_STDERROR); } } }
static void pscom_extoll_rma2_do_write(pscom_con_t *con) { unsigned int len; struct iovec iov[2]; pscom_req_t *req; req = pscom_write_get_iov(con, iov); if (req) { psex_con_info_t *ci = con->arch.extoll.ci; len = iov[0].iov_len + iov[1].iov_len; int rlen = psex_sendv(ci, iov, len); if (rlen >= 0) { pscom_write_done(con, req, rlen); } else if ((rlen == -EINTR) || (rlen == -EAGAIN)) { // Busy: Maybe out of tokens? try to read more tokens: _pscom_extoll_rma2_do_read(con, ci); } else { // Error pscom_con_error(con, PSCOM_OP_WRITE, PSCOM_ERR_STDERROR); } } }
static void shm_do_write(pscom_con_t *con) { unsigned int len; struct iovec iov[2]; pscom_req_t *req; req = pscom_write_get_iov(con, iov); if (req && shm_cansend(&con->arch.shm)) { len = iov[0].iov_len + iov[1].iov_len; len = pscom_min(len, SHM_BUFLEN); shm_iovsend(&con->arch.shm, iov, len); pscom_write_done(con, req, len); } }
static void pscom_mxm_do_write(pscom_con_t *con) { struct iovec iov[2]; psmxm_con_info_t *ci = con->arch.mxm.ci; pscom_req_t *req = con->arch.mxm.sreq; int polling = 0; if (req) { // proceed with the send from the last iteration. polling = 1; unsigned sent = psmxm_send_progress(ci); if (sent) { pscom_write_done(con, req, sent); } else { /* FIXME: we might want to send more than one message at a time. */ /* send in progress. wait for completion before transmitting the next message. */ return; } } /* get and post a new write request */ req = pscom_write_get_iov(con, iov); if (req) { int ret = psmxm_sendv(ci, iov, iov[0].iov_len + iov[1].iov_len); if (ret > 0){ /* sending ret bytes. Complete this request in the next iteration. */ if (!polling) poll_user_inc(); } else if (ret == -EAGAIN){ /* Try again later. */ req = NULL; } else { assert(ret == -EPIPE); errno = -ret; pscom_con_error(con, PSCOM_OP_WRITE, PSCOM_ERR_STDERROR); req = NULL; } } if (!req && polling) poll_user_dec(); // Remember the current request or NULL in the case of EAGAIN. con->arch.mxm.sreq = req; }
static void _tcp_do_write(pscom_con_t *con) { struct iovec iov[2]; struct msghdr msg; pscom_req_t *req; req = pscom_write_get_iov(con, iov); if (req) { assert(req->magic == MAGIC_REQUEST); ssize_t len; // len = writev(con->arch.tcp.con_fd, // con->out.iov, con->out.count); msg.msg_iov = iov; msg.msg_iovlen = 2; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT; len = sendmsg(con->arch.tcp.ufd_info.fd, &msg, MSG_NOSIGNAL | MSG_DONTWAIT); if (len >= 0) { pscom_write_done(con, req, len); } else if ((errno != EINTR) && (errno != EAGAIN)) { goto err_con_broken; } } return; /* error code */ err_con_broken: pscom_con_error(con, PSCOM_OP_WRITE, PSCOM_ERR_STDERROR); return; }