/* * Keep progressing sends on this queue until: * a) no more send credits on the queue (it's full) * or * b) all endpoints are complete or blocked awaiting ACKs */ void usdf_msg_tx_progress(struct usdf_tx *tx) { struct usdf_ep *ep; struct usd_qp_impl *qp; qp = to_qpi(tx->tx_qp); while (qp->uq_wq.uwq_send_credits > 1 && !TAILQ_EMPTY(&tx->t.msg.tx_ep_have_acks)) { ep = TAILQ_FIRST(&tx->t.msg.tx_ep_have_acks); TAILQ_REMOVE_MARK(&tx->t.msg.tx_ep_have_acks, ep, e.msg.ep_ack_link); usdf_msg_send_ack(tx, ep); } while (qp->uq_wq.uwq_send_credits > 1 && !TAILQ_EMPTY(&tx->t.msg.tx_ep_ready)) { ep = TAILQ_FIRST(&tx->t.msg.tx_ep_ready); /* * Send next segment on this EP. This will also remove the * current send from the EP send list if it completes */ usdf_msg_send_segment(tx, ep); --ep->e.msg.ep_seq_credits; if (TAILQ_EMPTY(&ep->e.msg.ep_posted_wqe)) { TAILQ_REMOVE_MARK(&tx->t.msg.tx_ep_ready, ep, e.msg.ep_link); } else { --ep->e.msg.ep_fairness_credits; if (ep->e.msg.ep_seq_credits == 0) { TAILQ_REMOVE_MARK(&tx->t.msg.tx_ep_ready, ep, e.msg.ep_link); ep->e.msg.ep_fairness_credits = USDF_MSG_FAIRNESS_CREDITS; /* fairness credits exhausted, go to back of the line */ } else if (ep->e.msg.ep_fairness_credits == 0) { TAILQ_REMOVE(&tx->t.msg.tx_ep_ready, ep, e.msg.ep_link); TAILQ_INSERT_TAIL(&tx->t.msg.tx_ep_ready, ep, e.msg.ep_link); ep->e.msg.ep_fairness_credits = USDF_MSG_FAIRNESS_CREDITS; } } } }
static int usdf_pep_listen_cb(void *v) { struct usdf_pep *pep; struct sockaddr_in sin; struct usdf_connreq *crp; struct epoll_event ev; socklen_t socklen; int ret; int s; pep = v; socklen = sizeof(sin); s = accept(pep->pep_sock, &sin, &socklen); if (s == -1) { /* ignore early failure */ return 0; } crp = NULL; pthread_spin_lock(&pep->pep_cr_lock); if (!TAILQ_EMPTY(&pep->pep_cr_free)) { crp = TAILQ_FIRST(&pep->pep_cr_free); TAILQ_REMOVE_MARK(&pep->pep_cr_free, crp, cr_link); TAILQ_NEXT(crp, cr_link) = NULL; } pthread_spin_unlock(&pep->pep_cr_lock); /* no room for request, just drop it */ if (crp == NULL) { /* XXX send response? */ close(s); return 0; } crp->cr_sockfd = s; crp->cr_pep = pep; crp->cr_ptr = crp->cr_data; crp->cr_resid = sizeof(struct usdf_connreq_msg); crp->cr_pollitem.pi_rtn = usdf_pep_read_connreq; crp->cr_pollitem.pi_context = crp; ev.events = EPOLLIN; ev.data.ptr = &crp->cr_pollitem; ret = epoll_ctl(pep->pep_fabric->fab_epollfd, EPOLL_CTL_ADD, crp->cr_sockfd, &ev); if (ret == -1) { crp->cr_pollitem.pi_rtn = NULL; usdf_cm_msg_connreq_failed(crp, -errno); return 0; } TAILQ_INSERT_TAIL(&pep->pep_cr_pending, crp, cr_link); return 0; }