void post_receive(boost::system::error_code &ec) { util::spinlock::scoped_lock lk(mtx_); if(!id_) { HPX_IBVERBS_THROWS_IF(ec, boost::asio::error::not_connected); return; } struct ibv_recv_wr wr, *bad_wr = NULL; struct ibv_sge sge; std::memset(&wr, 0, sizeof(ibv_recv_wr)); HPX_ASSERT(id_); wr.wr_id = (uintptr_t)id_; wr.sg_list = &sge; wr.num_sge = 1; sge.addr = (uintptr_t)client_msg_; sge.length = sizeof(message); sge.lkey = client_msg_mr_->lkey; int ret = 0; HPX_ASSERT(id_); ret = ibv_post_recv(id_->qp, &wr, &bad_wr); if(ret) { int verrno = errno; boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); } }
void on_preconnect(rdma_cm_id * id, ibv_pd * pd, boost::system::error_code &ec) { close(); { util::spinlock::scoped_lock lk(mtx_); HPX_ASSERT(buffer_); buffer_mr_ = ibv_reg_mr( pd , buffer_ , buffer_size_ , IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE ); if(!buffer_mr_) { int verrno = errno; boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); } server_msg_mr_ = ibv_reg_mr( pd , server_msg_ , sizeof(hpx::parcelset::policies::ibverbs::message) , IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE ); if(!server_msg_mr_) { int verrno = errno; boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); } client_msg_mr_ = ibv_reg_mr( pd , client_msg_ , sizeof(hpx::parcelset::policies::ibverbs::message) , IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE ); if(!client_msg_mr_) { int verrno = errno; boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); } id_ = id; } //post_receive(); }
ibv_pd *connection_handler::get_pd(ibv_context *context, boost::system::error_code & ec) { hpx::lcos::local::spinlock::scoped_lock l(pd_map_mtx_); typedef pd_map_type::iterator iterator; iterator it = pd_map_.find(context); if(it == pd_map_.end()) { ibv_pd *pd = ibv_alloc_pd(context); if(pd == 0) { int verrno = errno; boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); return 0; } memory_pool_.register_chunk(pd); pd_map_.insert(std::make_pair(context, pd)); mr_map_.insert(std::make_pair(pd, mr_cache_type())); return pd; } return it->second; }
inline bool get_next_event( rdma_event_channel *event_channel, rdma_cm_event & event_copy, Connection * c , boost::system::error_code &ec ) { if(!event_channel) { HPX_IBVERBS_THROWS_IF(ec, boost::asio::error::not_connected); return false; } rdma_cm_event * event = NULL; if(rdma_get_cm_event(event_channel, &event) == 0) { std::memcpy(&event_copy, event, sizeof(rdma_cm_event)); rdma_ack_cm_event(event); if(event_copy.event == RDMA_CM_EVENT_DISCONNECTED) { c->on_disconnect(event_copy.id); return get_next_event(event_channel, event_copy, c, ec); } return true; } else { int verrno = errno; if(verrno == EBADF) return false; if(verrno == EAGAIN) return false; if(verrno == EWOULDBLOCK) return false; boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); return false; } HPX_ASSERT(false); return false; }
void send_message(message_type m, boost::system::error_code &ec) { util::spinlock::scoped_lock lk(mtx_); if(!id_) { HPX_IBVERBS_THROWS_IF(ec, boost::asio::error::not_connected); return; } struct ibv_send_wr wr, *bad_wr = NULL; struct ibv_sge sge; std::memset(&wr, 0, sizeof(ibv_recv_wr)); HPX_ASSERT(id_); wr.wr_id = (uintptr_t)id_; wr.opcode = IBV_WR_SEND; wr.sg_list = &sge; wr.num_sge = 1; wr.send_flags = IBV_SEND_SIGNALED; server_msg_->id = m; sge.addr = (uintptr_t)server_msg_; sge.length = sizeof(message); sge.lkey = server_msg_mr_->lkey; int ret = 0; HPX_ASSERT(id_); ret = ibv_post_send(id_->qp, &wr, &bad_wr); if(ret) { int verrno = errno; boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); } }
inline void set_nonblocking(int fd, boost::system::error_code &ec) { int flags = fcntl(fd, F_GETFL); int rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK | FASYNC); if(rc < 0) { int verrno = errno; boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); } }
message_type on_completion(ibv_wc * wc, boost::system::error_code &ec) { util::spinlock::scoped_lock lk(mtx_); if(!id_) { HPX_IBVERBS_THROWS_IF(ec, boost::asio::error::not_connected); return MSG_SHUTDOWN; } if(wc->opcode == IBV_WC_RECV) { switch(client_msg_->id) { case MSG_DATA: return MSG_DATA; case MSG_SHUTDOWN: return MSG_SHUTDOWN; default: return MSG_INVALID; } } if(wc->opcode == IBV_WC_SEND) { switch(server_msg_->id) { case MSG_DONE: return MSG_DONE; case MSG_DATA: return MSG_DATA; case MSG_MR: return MSG_MR; case MSG_SHUTDOWN: return MSG_SHUTDOWN; default: return MSG_INVALID; } return MSG_INVALID; } return MSG_RETRY; }
void close(boost::system::error_code &ec) { if(!event_channel_) { HPX_IBVERBS_RESET_EC(ec); return; } if(event_channel_) { rdma_destroy_event_channel(event_channel_); event_channel_ = 0; } else { HPX_IBVERBS_THROWS_IF(ec, boost::asio::error::not_connected); } if(listener_) { rdma_destroy_id(listener_); listener_ = 0; } HPX_IBVERBS_RESET_EC(ec); }
void bind( boost::asio::ip::tcp::endpoint const & ep , boost::system::error_code &ec) { if(event_channel_) { HPX_IBVERBS_THROWS_IF(ec, boost::asio::error::already_connected); } else { event_channel_ = rdma_create_event_channel(); if(!event_channel_) { int verrno = errno; close(ec); boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); return; } set_nonblocking(event_channel_->fd, ec); if(ec) { close(ec); return; } int ret = 0; ret = rdma_create_id(event_channel_, &listener_, NULL, RDMA_PS_TCP); if(ret) { int verrno = errno; close(ec); boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); return; } std::string host = ep.address().to_string(); std::string port = boost::lexical_cast<std::string>(ep.port()); addrinfo *addr; getaddrinfo(host.c_str(), port.c_str(), NULL, &addr); ret = rdma_bind_addr(listener_, addr->ai_addr); freeaddrinfo(addr); if(ret) { int verrno = errno; close(ec); boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); return; } ret = rdma_listen(listener_, 10); /* backlog = 10 is arbitrary */ if(ret) { int verrno = errno; close(ec); boost::system::error_code err(verrno, boost::system::system_category()); HPX_IBVERBS_THROWS_IF( ec , err ); return; } HPX_IBVERBS_RESET_EC(ec); } }