Esempio n. 1
0
/* 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;
}
Esempio n. 2
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);
		}
	}
}
Esempio n. 3
0
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);
		}
	}
}
Esempio n. 4
0
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);
		}
	}
}
Esempio n. 5
0
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);
	}
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;
}