static int np_fdtrans_recv(Npfcall **fcp, u32 msize, void *a) { Fdtrans *fdt = (Fdtrans *)a; Npfcall *fc = NULL; int n, size, len; if (fdt->fc) { assert (fdt->fc_msize >= msize); fc = fdt->fc; len = fdt->fc->size; fdt->fc = NULL; size = np_peek_size (fc->pkt, len); } else { if (!(fc = np_alloc_fcall (msize))) { np_uerror (ENOMEM); goto error; } len = 0; size = 0; } while (len < size || len < 4) { n = read(fdt->fdin, fc->pkt + len, msize - len); if (n < 0) { np_uerror (errno); goto error; } if (n == 0) { /* EOF */ free (fc); fc = NULL; goto done; } len += n; if (size == 0) size = np_peek_size(fc->pkt, len); if (size > msize) { np_uerror(EPROTO); goto error; } } if (len > size) { if (!(fdt->fc = np_alloc_fcall (msize))) { np_uerror(ENOMEM); goto error; } fdt->fc_msize = msize; memcpy (fdt->fc->pkt, fc->pkt + size, len - size); fdt->fc->size = len - size; } fc->size = size; done: *fcp = fc; return 0; error: if (fc) free (fc); return -1; }
static int rdma_trans_recv(Npfcall **fcp, u32 msize, void *a) { int n, ret, closing = 0; struct ibv_cq *cq; struct ibv_wc wc; void *context; Rdmatrans *rdma = (Rdmatrans *)a; Rdmactx *ctx; Npfcall *fc = NULL; if (!(fc = np_alloc_fcall (msize))) { np_uerror(ENOMEM); return -1; } pthread_mutex_lock(&rdma->lock); again: if (rdma->rfirst) { ctx = rdma->rfirst; n = ctx->len - ctx->pos; if (n > msize) n = msize; memmove(fc->pkt, ctx->buf + ctx->pos, n); ctx->pos += n; if (ctx->pos == ctx->len) { rdma->rfirst = ctx->next; if (ctx == rdma->rlast) rdma->rlast = NULL; rdma_post_recv(rdma, ctx); } pthread_mutex_unlock(&rdma->lock); fc->size = n; *fcp = fc; return 0; } pthread_mutex_unlock(&rdma->lock); poll: ret = ibv_get_cq_event(rdma->ch, &cq, &context); if (ret) { np_uerror(ret); //fprintf(stderr, "Error %d polling cq\n", ret); return -1; } ibv_ack_cq_events(rdma->cq, 1); ibv_req_notify_cq(cq, 0); while ((ret = ibv_poll_cq(rdma->cq, 1, &wc)) > 0) { /* Check if it's a flush */ if (wc.status != IBV_WC_SUCCESS) { //fprintf(stderr, "cq fail: status %d opcode %d\n", // wc.status, wc.opcode); closing = 1; continue; } if (wc.opcode == IBV_WC_RECV) { ctx = (Rdmactx *) wc.wr_id; pthread_mutex_lock(&rdma->lock); ctx->used = 0; ctx->len = wc.byte_len; ctx->pos = 0; if (rdma->rlast) rdma->rlast->next = ctx; else rdma->rfirst = ctx; rdma->rlast = ctx; ctx->next = NULL; goto again; } else if (wc.opcode == IBV_WC_SEND) { ctx = (Rdmactx *) wc.wr_id; pthread_mutex_lock(&rdma->lock); ctx->used = 0; pthread_cond_signal(&rdma->cond); pthread_mutex_unlock(&rdma->lock); } } if (!ret && !closing) goto poll; np_uerror(ret); return -1; }