static int send_xfer(int size) { struct fi_cq_entry comp; int ret; while (!credits) { ret = fi_cq_read(scq, &comp, 1); if (ret > 0) { goto post; } else if (ret < 0 && ret != -FI_EAGAIN) { if (ret == -FI_EAVAIL) { cq_readerr(scq, "scq"); } else { FT_PRINTERR("fi_cq_read", ret); } return ret; } } credits--; post: ret = fi_tsend(ep, buf, (size_t) size, fi_mr_desc(mr), remote_fi_addr, tag_data, &fi_ctx_tsend); if (ret) FT_PRINTERR("fi_tsend", ret); return ret; }
void api_tagged_send_recv(int len) { ssize_t sz; uint64_t caps = fi[0]->caps; rdm_api_init_data(source, len, 0xab); rdm_api_init_data(target, len, 0); sz = fi_tsend(ep[0], source, len, loc_mr, gni_addr[1], len, target); if (TAG_SEND_ALLOWED(caps)) { cr_assert(sz == 0, "fi_tsend failed caps:0x%lx err:%ld", caps, sz); } else { cr_assert(sz < 0, "fi_tsend should fail caps:0x%lx err:%ld", caps, sz); } sz = fi_trecv(ep[1], target, len, rem_mr, gni_addr[0], len, 0, source); if (TAG_RECV_ALLOWED(caps)) { cr_assert(sz == 0, "fi_trecv failed caps:0x%lx err:%ld", caps, sz); } else { cr_assert(sz < 0, "fi_trecv should fail caps:0x%lx err:%ld", caps, sz); } }
/* * ssize_t fi_tsend(struct fid_ep *ep, void *buf, size_t len, * void *desc, fi_addr_t dest_addr, uint64_t tag, void *context); * * ssize_t fi_trecv(struct fid_ep *ep, void * buf, size_t len, * void *desc, fi_addr_t src_addr, uint64_t tag, uint64_t ignore, * void *context); */ void do_tsend(int len) { int ret; ssize_t sz; int source_done = 0, dest_done = 0; struct fi_cq_tagged_entry s_cqe, d_cqe; rdm_tagged_sr_init_data(source, len, 0xab); rdm_tagged_sr_init_data(target, len, 0); sz = fi_tsend(ep[0], source, len, loc_mr, gni_addr[1], len, target); cr_assert_eq(sz, 0); sz = fi_trecv(ep[1], target, len, rem_mr, gni_addr[0], len, 0, source); cr_assert_eq(sz, 0); /* need to progress both CQs simultaneously for rendezvous */ do { ret = fi_cq_read(msg_cq[0], &s_cqe, 1); if (ret == 1) { source_done = 1; } ret = fi_cq_read(msg_cq[1], &d_cqe, 1); if (ret == 1) { dest_done = 1; } } while (!(source_done && dest_done)); dbg_printf("got context events!\n"); cr_assert(rdm_tagged_sr_check_data(source, target, len), "Data mismatch"); }
Test(rdm_tagged_sr, multi_tsend_trecv) { int i, it, ridx, ret; const int iters = 37; const int num_msgs = 17; const int slen = 256; uint64_t tags[num_msgs]; uint64_t rtag = 0x01000000; uint64_t ignore = 0xf0ffffff; char msg[num_msgs][slen]; struct fi_cq_tagged_entry cqe; srand(time(NULL)); for (it = 0; it < iters; it++) { for (i = 0; i < num_msgs; i++) { tags[i] = 0x01010abc + it*iters + i; sprintf(msg[i], "%d\n", i); ret = fi_tsend(ep[1], msg[i], strlen(msg[i]), NULL, gni_addr[0], tags[i], NULL); cr_assert(ret == FI_SUCCESS); do { ret = fi_cq_read(msg_cq[1], &cqe, 1); cr_assert((ret == 1) || (ret == -FI_EAGAIN)); } while (ret == -FI_EAGAIN); cr_assert(cqe.len == 0); cr_assert(cqe.tag == 0); } for (i = 0; i < num_msgs; i++) { ret = fi_trecv(ep[0], target, BUF_SZ, fi_mr_desc(loc_mr), gni_addr[1], rtag, ignore, NULL); cr_assert(ret == FI_SUCCESS); do { ret = fi_cq_read(msg_cq[0], &cqe, 1); cr_assert((ret == 1) || (ret == -FI_EAGAIN)); } while (ret == -FI_EAGAIN); cr_assert(rtag != cqe.tag); ret = sscanf(target, "%d", &ridx); cr_assert(ret == 1); cr_assert(cqe.len == strlen(msg[ridx])); /* zero out the tag for error checking below */ tags[ridx] = 0; } /* Make sure we got everything */ for (i = 0; i < num_msgs; i++) cr_assert(tags[i] == 0); } }
static int send_msg(int size, uint64_t tag) { int ret; ret = fi_tsend(ep, buf, (size_t) size, fi_mr_desc(mr), remote_fi_addr, tag, &fi_ctx_send); if (ret) FT_PRINTERR("fi_tsend", ret); ret = wait_for_tagged_completion(scq, 1); return ret; }
static int send_msg(int size) { int ret; ret = fi_tsend(ep, buf, (size_t) size, fi_mr_desc(mr), remote_fi_addr, tag_control, &fi_ctx_tsend); if (ret) { FT_PRINTERR("fi_tsend", ret); return ret; } ret = wait_for_completion_tagged(scq, 1); return ret; }
/* ssize_t (*recvmsg)(struct fid_ep *ep, const struct fi_msg *msg, uint64_t flags); */ void do_trecvmsg(int len) { int ret; ssize_t sz; int source_done = 0, dest_done = 0; struct fi_cq_tagged_entry s_cqe, d_cqe; struct fi_msg_tagged msg; struct iovec iov; rdm_tagged_sr_init_data(source, len, 0xab); rdm_tagged_sr_init_data(target, len, 0); sz = fi_tsend(ep[0], source, len, loc_mr, gni_addr[1], len, target); cr_assert_eq(sz, 0); iov.iov_base = target; iov.iov_len = len; msg.msg_iov = &iov; msg.desc = (void **)&rem_mr; msg.iov_count = 1; msg.addr = gni_addr[0]; msg.context = source; msg.data = (uint64_t)source; msg.tag = len; msg.ignore = 0; sz = fi_trecvmsg(ep[1], &msg, 0); cr_assert_eq(sz, 0); /* need to progress both CQs simultaneously for rendezvous */ do { ret = fi_cq_read(msg_cq[0], &s_cqe, 1); if (ret == 1) { source_done = 1; } ret = fi_cq_read(msg_cq[1], &d_cqe, 1); if (ret == 1) { dest_done = 1; } } while (!(source_done && dest_done)); dbg_printf("got context events!\n"); cr_assert(rdm_tagged_sr_check_data(source, target, len), "Data mismatch"); }
ssize_t ft_post_tx(size_t size) { ssize_t ret; if (hints->caps & FI_TAGGED) { ret = fi_tsend(ep, tx_buf, size + ft_tx_prefix_size(), fi_mr_desc(mr), remote_fi_addr, tx_seq, &tx_ctx); } else { ret = fi_send(ep, tx_buf, size + ft_tx_prefix_size(), fi_mr_desc(mr), remote_fi_addr, &tx_ctx); } if (ret) { FT_PRINTERR("transmit", ret); return ret; } tx_seq++; return 0; }
/* * The general strategy here is that we call send_loop and do as many sends * in a row as we can until we get FI_EAGAIN which prevents us from continuing and * we have to drain the send_cq. Then we do it again, until we've sent * all the messages we were going to send. */ static int send_loop(size_t size) { int q_opts = 0; int ret; struct fi_context send_ctx[max_opts]; while (q_opts < max_opts) { do { ft_tag = q_opts + 1; if (tagged) ret = fi_tsend(ep, tx_buf, size, NULL, remote_fi_addr, ft_tag, (void *) &send_ctx[q_opts]); else ret = fi_send(ep, tx_buf, size, NULL, remote_fi_addr, (void *) &send_ctx[q_opts]); if (ret == FI_SUCCESS) { tx_seq++; q_opts++; } } while (!ret && (q_opts != max_opts)); if (ret < 0) { if (ret == -FI_EAGAIN) { ret = ft_get_tx_comp(tx_seq); if (ret) return ret; } else { FT_PRINTERR("Send OP", ret); return ret; } } } ret = ft_get_tx_comp(tx_seq); if (ret) return ret; if (opts.verbose) printf("Success: Completed %d queued ops\n", q_opts); return 0; }
static void do_tagged_sr_pipelined(void) { int i, it, s, ret; const int iters = 37; const int num_msgs = 61; const int msgs_per_stage = 17; const int num_stages = num_msgs/msgs_per_stage + (num_msgs%msgs_per_stage != 0); const int slen = 256; uint64_t tags[num_msgs]; uint64_t rtag = 0x01000000; uint64_t ignore = 0xf0ffffff; char msg[num_msgs][slen]; struct fi_cq_tagged_entry cqe; srand(time(NULL)); for (it = 0; it < iters; it++) { dbg_printf("iter %d\n", it); for (s = 0; s < num_stages; s++) { dbg_printf("\tsending stage %d\n", s); for (i = s*msgs_per_stage; i < (s+1)*msgs_per_stage && i < num_msgs; i++) { tags[i] = 0x01010abc + it*iters + i; sprintf(msg[i], "%d\n", i%10); ret = fi_tsend(ep[1], msg[i], strlen(msg[i]), NULL, gni_addr[0], tags[i], NULL); cr_assert(ret == FI_SUCCESS); } for (i = s*msgs_per_stage; i < (s+1)*msgs_per_stage && i < num_msgs; i++) { do { ret = fi_cq_read(msg_cq[1], &cqe, 1); cr_assert((ret == 1) || (ret == -FI_EAGAIN)); } while (ret == -FI_EAGAIN); cr_assert(cqe.tag == 0); } cr_assert(cqe.len == 0); } for (s = 0; s < num_stages; s++) { dbg_printf("\treceiving stage %d\n", s); for (i = s*msgs_per_stage; i < (s+1)*msgs_per_stage && i < num_msgs; i++) { ret = fi_trecv(ep[0], &target[i], BUF_SZ, fi_mr_desc(loc_mr), gni_addr[1], rtag, ignore, NULL); cr_assert(ret == FI_SUCCESS); } for (i = s*msgs_per_stage; i < (s+1)*msgs_per_stage && i < num_msgs; i++) { do { ret = fi_cq_read(msg_cq[0], &cqe, 1); cr_assert((ret == 1) || (ret == -FI_EAGAIN)); } while (ret == -FI_EAGAIN); cr_assert(rtag != cqe.tag); cr_assert(ret == 1); cr_assert(cqe.len == 2); /* zero out the tag for error checking below */ tags[cqe.tag - (0x01010abc + it*iters)] = 0; } } /* Make sure we got everything */ for (i = 0; i < num_msgs; i++) { cr_assert(tags[i] == 0); } } }
static int run(void) { int ret; ret = init_fabric(); if (ret) return ret; ret = ft_init_av(); if (ret) return ret; if (opts.dst_addr) { printf("Searching for a bad msg\n"); ret = tagged_peek(0xbad); if (ret != -FI_ENOMSG) { FT_PRINTERR("FI_PEEK", ret); return ret; } printf("Synchronizing with sender..\n"); ret = ft_sync(); if (ret) return ret; printf("Searching for a good msg\n"); ret = tagged_peek(0x900d); if (ret != 1) { FT_PRINTERR("FI_PEEK", ret); return ret; } printf("Receiving msg\n"); ret = fi_trecv(ep, buf, rx_size, fi_mr_desc(mr), remote_fi_addr, 0x900d, 0, &rx_ctx); if (ret) { FT_PRINTERR("fi_trecv", ret); return ret; } printf("Completing recv\n"); ret = ft_get_rx_comp(++rx_seq); if (ret) return ret; } else { printf("Sending tagged message\n"); ret = fi_tsend(ep, tx_buf, tx_size, fi_mr_desc(mr), remote_fi_addr, 0x900d, &tx_ctx); if (ret) return ret; printf("Synchronizing with receiver..\n"); ret = ft_sync(); if (ret) return ret; printf("Getting send completion\n"); ret = ft_get_tx_comp(tx_seq + 1); if (ret) return ret; } ft_finalize(); return 0; }