/* 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_psm_read_stop(pscom_con_t *con) { if (con->arch.psm.reading) { con->arch.psm.reading = 0; poll_user_dec(); } }
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; }