/* returnvalue like write(), except on error errno is negative return */ static int _pselan_sendv(pselan_con_info_t *ci, struct iovec *iov, int size, unsigned int magic) { int len; int pselanlen; pselan_msg_t *msg; if (ci->con_broken) goto err_broken; /* Its allowed to send, if At least 2 tokens left or (1 token left AND n_tosend > 0) */ if ((ci->n_send_toks < 2) && ((ci->n_send_toks < 1) || (ci->n_tosend_toks == 0))) goto err_busy; len = (size <= (int)ELAN_BUFSIZE_PAYLOAD) ? size : (int)ELAN_BUFSIZE_PAYLOAD; pselanlen = PSELAN_LEN(len); msg = ci->send_bufs + ci->send_pos; msg->tail.token = ci->n_tosend_toks; msg->tail.payload = len; msg->tail.magic = magic; char *buf = msg->data - pselanlen; /* copy to registerd send buffer */ pscom_memcpy_from_iov(buf, iov, len); pselan_flush_sendbuf(ci, buf, ci->remote_r_buf[ci->send_pos].data - pselanlen, pselanlen + sizeof(pselan_msgheader_t)); pscom_forward_iov(iov, len); ci->n_tosend_toks = 0; ci->send_pos = (ci->send_pos + 1) % SIZE_SR_QUEUE; ci->n_send_toks--; pselan_flush_event(ci); return len; err_busy: pselan_get_fresh_tokens(ci); pselan_flush_event(ci); return -EAGAIN; err_broken: return -EPIPE; }
/* send iov. Call only if shm_cansend() == true (no check inside)! len must be smaller or equal SHM_BUFLEN! */ static void shm_iovsend(shm_conn_t *shm, struct iovec *iov, int len) { int cur = shm->send_cur; shm_buf_t *shmbuf = &shm->remote_com->buf[cur]; /* copy to sharedmem */ pscom_memcpy_from_iov(SHM_DATA(shmbuf, len), iov, len); shmbuf->header.len = len; shm_mb(); /* Notification about the new message */ shmbuf->header.msg_type = SHM_MSGTYPE_STD; shm->send_cur = (shm->send_cur + 1) % SHM_BUFS; }
/* sends an iov. FIXME: returns 0 if the send is complete, -EAGAIN if it created one or more requests for it, and -EPIPE in case of an error. */ static int _pspsm_sendv(pspsm_con_info_t *con_info, uint64_t magic) { uint64_t tag = con_info->send_id | magic; unsigned int i=0; psm_error_t ret; size_t len = con_info->iov[0].iov_len + con_info->iov[1].iov_len; if (len <= pscom.env.readahead){ pscom_memcpy_from_iov(sendbuf, con_info->iov, len); /* we hope that doesn't block - it shouldn't, as the * message is sufficiently small */ ret = psm_mq_send(pspsm_mq, con_info->epaddr, /* flags*/ 0, tag, sendbuf, len); if (ret != PSM_OK) goto err; return 0; } for (i=0; i<2; i++){ if (con_info->iov[i].iov_len){ /* pspsm_dprint(0, "Send part[%d], %p len %d to con %s\n", i, con_info->iov[i].iov_base, (int)con_info->iov[i].iov_len, con_info->con->pub.remote_con_info.name); */ if (_pspsm_send_buf(con_info, con_info->iov[i].iov_base, con_info->iov[i].iov_len, tag, &con_info->sreqs[i], i)){ return -EPIPE; } /* inc for each outstanding send request */ poll_user_inc(); } } return -EAGAIN; err: pspsm_err(psm_error_get_string(ret)); pspsm_dprint(1, "_pspsm_send_buf: %s", pspsm_err_str); return -EPIPE; }
/* returnvalue like write(), except on error errno is negative return */ static int _psex_sendv(psex_con_info_t *con_info, struct iovec *iov, int size, unsigned int magic) { int len; int psex_len; psex_msg_t *_msg; int rc; psex_msgheader_t *tail; hca_info_t *hca_info = con_info->hca_info; if (con_info->con_broken) goto err_broken; /* Its allowed to send, if At least 2 tokens left or (1 token left AND n_tosend > 0) */ if ((con_info->n_send_toks < 2) && ((con_info->n_send_toks < 1) || (con_info->n_tosend_toks == 0))) { psex_stat.busy_notokens++; goto err_busy; } if (psex_global_sendq && psex_pending_global_sends >= psex_sendq_size && psex_event_count) { // printf("Busy global\n"); usleep(10*1000); psex_stat.busy_global_cq++; goto err_busy; } len = (size <= (int)PSEX_RMA2_PAYLOAD) ? size : (int)PSEX_RMA2_PAYLOAD; psex_len = PSEX_LEN(len); ringbuf_t *send = (con_info->send.bufs.mr) ? &con_info->send : &hca_info->send; _msg = ((psex_msg_t *)send->bufs.ptr) + send->pos; tail = (psex_msgheader_t *)((char*)_msg + psex_len - sizeof(psex_msgheader_t)); tail->token = con_info->n_tosend_toks; tail->payload = len; tail->magic = magic; /* copy to registerd send buffer */ pscom_memcpy_from_iov((void *)_msg, iov, len); rc = rma2_post_put_bt(con_info->rma2_port, con_info->rma2_handle, send->bufs.mr, ((char*)_msg - (char *)send->bufs.ptr), psex_len, PSEX_DATA(con_info->remote_rbuf_nla + con_info->remote_recv_pos * sizeof(psex_msg_t), psex_len), 0, 0); if (rc != 0) goto err_rma2_post_cl; psex_pending_global_sends++; // ToDo: Decrease the counter somewhere! pscom_forward_iov(iov, len); con_info->n_tosend_toks = 0; con_info->remote_recv_pos = (con_info->remote_recv_pos + 1) % psex_recvq_size; send->pos = (send->pos + 1) % psex_sendq_size; con_info->n_send_toks--; return len; /* --- */ err_busy: return -EAGAIN; /* --- */ err_rma2_post_cl: if (0 /*rc == ???EAGAIN Too many posted work requests ? */) { psex_stat.post_send_eagain++; return -EAGAIN; } else { psex_stat.post_send_error++; psex_err_rma2_error("rma2_post_put_cl()", rc); con_info->con_broken = 1; return -EPIPE; } /* --- */ err_broken: return -EPIPE; }
/* returnvalue like write(), except on error errno is negative return */ static int _psdapl_sendv(psdapl_con_info_t *ci, struct iovec *iov, int size, unsigned int magic) { int len; int psdapllen; psdapl_msg_t *msg; int rc; psdapl_msgheader_t *tail; if (ci->con_broken) goto err_broken; /* Its allowed to send, if At least 2 tokens left or (1 token left AND n_tosend > 0) */ if ((ci->n_send_toks < 2) && ((ci->n_send_toks < 1) || (ci->n_tosend_toks == 0))) { psdapl_stat.busy_notokens++; goto err_busy; } if (ci->outstanding_cq_entries >= EVD_MIN_QLEN) { psdapl_stat.busy_local_cq++; goto err_busy; } /* if (psdapl_outstanding_cq_entries >= ???) { psdapl_stat.busy_global_cq++; goto err_busy; } */ len = (size <= (int)DAPL_BUFSIZE_PAYLOAD) ? size : (int)DAPL_BUFSIZE_PAYLOAD; psdapllen = PSDAPL_LEN(len); msg = ((psdapl_msg_t *)ci->send_bufs.lmr_mem) + ci->send_pos; tail = (psdapl_msgheader_t *)((char*)msg + psdapllen); tail->token = ci->n_tosend_toks; tail->payload = len; tail->magic = magic; /* copy to registerd send buffer */ pscom_memcpy_from_iov((void *)msg, iov, len); rc = psdapl_flush_sendbuf(ci, (char *)msg, PSDAPL_DATA_OFFSET(ci->send_pos, psdapllen), psdapllen + sizeof(psdapl_msgheader_t)); if (rc != 0) goto err_send; ci->outstanding_cq_entries++; pscom_forward_iov(iov, len); ci->n_tosend_toks = 0; ci->send_pos = (ci->send_pos + 1) % SIZE_SR_QUEUE; ci->n_send_toks--; psdapl_flush_evd(ci); return len; err_busy: psdapl_get_fresh_tokens(ci); psdapl_flush_evd(ci); return -EAGAIN; err_send: psdapl_stat.post_send_error++; /* ToDo: Check for EAGAIN ? */ ci->con_broken = 1; return -EPIPE; err_broken: return -EPIPE; }