ibv_get_cq_event, ibv_ack_cq_events
Gets and acknowledges the completion queue (CQ) events.
Syntax
#include <rdma/verbs.h>
int ibv_get_cq_event(struct ibv_comp_channel *channel, struct ibv_cq **cq, void **cq_context);
void ibv_ack_cq_events(struct ibv_cq *cq, unsigned int nevents);
Description
The ibv_get_cq_event() function waits for the next completion event in the completion event channel. The cq argument is used to return the CQ that caused the event and the cq_context parameter is used to return the context of the CQ.
The ibv_ack_cq_events() function acknowledges the nevents events on the CQ cq parameter.
Notes:
- All completion events that the ibv_get_cq_event() function returns must be acknowledged by using the ibv_ack_cq_events() function.
- To avoid competiiton, when you destroy a CQ, the CQ waits for the completion of the events. This action guarantees a one-to-one correspondence between acknowledgements and successful get operation.
- When you call the ibv_ack_cq_events() function, it is expensive in the datapath because it must take a mutex. To reduce the cost, a count of the number of events requesting acknowledgement and acknowledging several completion events in one call to the ibv_ack_cq_events() function are performed.
Input Parameters
Item | Descriptor |
---|---|
channel | The ibv_comp_channel struct for the ibv_create_comp_channel() function. |
Output Parameters
Item | Descriptor |
---|---|
cq | A pointer to the completion queue (CQ) that is associated with the event. |
cq_context | The user-supplied context that is set in the ibv_create_cq() function. |
Return Value
The ibv_get_cq_event() and ibv_ack_cq_events() functions return 0 on success, and -1 if the request fails.
Examples
- The following code example demonstrates one possible way to work
with completion events. It performs the following steps:
- Preparation:
- Creates a CQ.
- Requests notification after creation of a new (first) completion event.
- Completion handling routine:
- Waits for the completion event and acknowledges it.
- Requests notification for the next completion event.
- Empties the CQ.
Note: An extra event can be triggered without having a corresponding completion entry in the CQ. This occurs if a completion entry is added to the CQ between requesting for notification and emptying the CQ. Then, the CQ is emptied.
cq = ibv_create_cq(ctx, 1, ev_ctx, channel, 0); if (!cq) { fprintf(stderr, "Failed to create CQ\n"); return 1; } /* Request notification before any completion can be created */ if (ibv_req_notify_cq(cq, 0)) { fprintf(stderr, "Could not request CQ notification\n"); return 1; } . . . /* Wait for the completion event */ if (ibv_get_cq_event(channel, &ev_cq, &ev_ctx)) { fprintf(stderr, "Failed to get cq_event\n"); return 1; } /* Ack the event */ ibv_ack_cq_events(ev_cq, 1); /* Request notification upon the next completion event */ if (ibv_req_notify_cq(cq, 0)) { fprintf(stderr, "Could not request CQ notification\n"); return 1; } /* Empty the CQ: poll all of the completions from the CQ (if any exist) */ do { ne = ibv_poll_cq(cq, 1, &wc); if (ne < 0) { fprintf(stderr, "Failed to poll completions from the CQ\n"); return 1; } if (wc.status != IBV_WC_SUCCESS) { fprintf(stderr, "Completion with status 0x%x was found\n", wc.status); return 1; } } while (ne);
- Preparation:
- The following code example demonstrates a possible way to work
with completion events in nonblocking mode. The code performs the
following steps:
- Sets the completion event channel in nonblocked mode.
- Polls the channel until it has a completion event.
- Gets the completion event and acknowledges it.
/* change the blocking mode of the completion channel */ flags = fcntl(channel->fd, F_GETFL); rc = fcntl(channel->fd, F_SETFL, flags | O_NONBLOCK); if (rc < 0) { fprintf(stderr, "Failed to change file descriptor of completion event channel\n"); return 1; } /* * poll the channel until it has an event and sleep ms_timeout * milliseconds between any iteration */ my_pollfd.fd = channel->fd; my_pollfd.events = POLLIN; my_pollfd.revents = 0; do { rc = poll(&my_polfd;, 1, ms_timeout); } while (rc == 0); if (rc < 0){ fprintf(stderr, "poll failed\n"); return 1; } ev_cq = cq; /* Wait for the completion event */ if (ibv_get_cq_event(channel, &ev_cq, &ev_ctx)) { fprintf(stderr, "Failed to get cq_event\n"); return 1; } /* Ack the event */ ibv_ack_cq_events(ev_cq, 1);