void Pair::handleCompletion()

in gloo/transport/ibverbs/pair.cc [405:489]


void Pair::handleCompletion(struct ibv_wc* wc) {
  if (wc->opcode == IBV_WC_RECV_RDMA_WITH_IMM) {
    // Incoming RDMA write completed.
    // Slot is encoded in immediate data on receive work completion.
    // It is set in the Pair::send function.
    auto slot = wc->imm_data;
    GLOO_ENFORCE_EQ(
      wc->status,
      IBV_WC_SUCCESS,
      "Recv for slot ",
      slot,
      ": ",
      ibv_wc_status_str(wc->status));

    GLOO_ENFORCE(recvCompletionHandlers_[slot] != nullptr);
    recvCompletionHandlers_[slot]->handleCompletion(wc);

    // Backfill receive work requests.
    postReceive();
  } else if (wc->opcode == IBV_WC_RDMA_WRITE) {
    // Outbound RDMA write completed.
    // Slot is encoded in wr_id fields on send work request. Unlike
    // the receive work completions, the immediate data field on send
    // work requests are not pass to the respective work completion.
    auto slot = wc->wr_id;
    GLOO_ENFORCE_EQ(
      wc->status,
      IBV_WC_SUCCESS,
      "Send for slot ",
      slot,
      ": ",
      ibv_wc_status_str(wc->status));

    GLOO_ENFORCE(sendCompletionHandlers_[slot] != nullptr);
    sendCompletionHandlers_[slot]->handleCompletion(wc);
  } else if (wc->opcode == IBV_WC_RECV) {
    // Memory region recv completed.
    //
    // Only used by the remote side of the pair to pass ibv_mr's.
    // They are written to in FIFO order, so we can pick up
    // and use the first MemoryRegion instance in the list of
    // mapped receive regions.
    //
    // The buffer trying to write to this slot might be waiting for
    // the other side of this pair to send its memory region.
    // Lock access, and notify anybody waiting afterwards.
    //
    // Slot is encoded in immediate data on receive work completion.
    // It is set in the Pair::sendMemoryRegion function.
    auto slot = wc->imm_data;
    GLOO_ENFORCE_EQ(
      wc->status,
      IBV_WC_SUCCESS,
      "Memory region recv for slot ",
      slot,
      ": ",
      ibv_wc_status_str(wc->status));

    // Move ibv_mr from memory region 'inbox' to final slot.
    const auto& mr = mappedRecvRegions_[recvPosted_ % kMaxBuffers];
    peerMemoryRegions_[slot] = mr->mr();

    // Notify any buffer waiting for the details of its remote peer.
    cv_.notify_all();

    // Backfill receive work requests.
    postReceive();
  } else if (wc->opcode == IBV_WC_SEND) {
    // Memory region send completed.
    auto slot = wc->wr_id;
    GLOO_ENFORCE_EQ(
      wc->status,
      IBV_WC_SUCCESS,
      "Memory region send for slot ",
      slot,
      ": ",
      ibv_wc_status_str(wc->status));

    GLOO_ENFORCE_GT(mappedSendRegions_.size(), 0);
    GLOO_ENFORCE_EQ(mappedSendRegions_.count(slot), 1);
    mappedSendRegions_.erase(slot);
  } else {
    GLOO_ENFORCE(false, "Unexpected completion with opcode: ", wc->opcode);
  }
}