IBV_GET_CQ_EVENT(3)
β¨ ibv_get_cq_event π ibv_ack_cq_events β¨
okay bestie, welcome to the Libibverbs Programmer's Manual page for ibv_get_cq_event(3) β this is the one about grabbing and acknowledging completion queue (CQ) events. it's giving event-loop main character energy and honestly? we're obsessed. π
πΈ NAME πΈ
ibv_get_cq_event, ibv_ack_cq_events β get and acknowledge completion queue (CQ) events
π¦ SYNOPSIS π¦
#include <infiniband/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 π
ibv_get_cq_event() literally just sits there and waits for the next completion event on the completion event channel channel. When it finally gets one, it fills the argument cq with the CQ that got the event, and cq_context with that CQ's context. no cap, that's the whole job. π«Ά
ibv_ack_cq_events() acknowledges nevents events on the CQ cq. you have to do this, okay? we'll get into why in NOTES. π
β RETURN VALUE β
ibv_get_cq_event()returns0on success, and-1on error. that's it, that's the whole range. πibv_ack_cq_events()returns no value. it's a void girlie, it gives nothing back and that's valid. β¨
π₯ NOTES π₯
okay so this part is important, do not skip it, i am begging:
- All completion events that
ibv_get_cq_event()returns must be acknowledged usingibv_ack_cq_events(). every single one. no ghosting your events. - to avoid races, destroying a CQ will wait for all completion events to be acknowledged β which is what guarantees a one-to-one correspondence between acks and successful gets. it's a whole situationship with strict rules. π
- calling
ibv_ack_cq_events()may be relatively expensive in the datapath, since it must take a mutex. π so ngl, it may be better to amortize this cost by keeping a count of the number of events needing acknowledgement, and then acking several completion events in one call toibv_ack_cq_events(). batch it, queen. π
π EXAMPLES π
π§ Example 1: the classic blocking flow
the following code example demonstrates one possible way to work with completion events. it performs the following steps:
Stage I: Preparation β¨
- Creates a CQ
- Requests for notification upon a new (first) completion event
Stage II: Completion Handling Routine π
- Wait for the completion event and ack it
- Request for notification upon the next completion event
- Empty the CQ
heads up bestie: note that an extra event may be triggered without having a corresponding completion entry in the CQ. this occurs if a completion entry is added to the CQ between Step 4 and Step 5, and the CQ is then emptied (polled) in Step 5. it's not a bug, it's just the vibe. π
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, "Couldn't 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(ev_cq, 0)) {
fprintf(stderr, "Couldn't 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;
}
/* there may be an extra event with no completion in the CQ */
if (ne == 0)
continue;
if (wc.status != IBV_WC_SUCCESS) {
fprintf(stderr, "Completion with status 0x%x was found\n", wc.status);
return 1;
}
} while (ne);
π¦ Example 2: non-blocking mode
the following code example demonstrates one possible way to work with completion events in non-blocking mode. it performs the following steps:
- Set the completion event channel to be non-blocked
- Poll the channel until there it has a completion event
- Get the completion event and ack 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_pollfd, 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);
π SEE ALSO π
ibv_create_comp_channel(3), ibv_create_cq(3), ibv_req_notify_cq(3), ibv_poll_cq(3)
π AUTHORS π
Dotan Barak <dotanba@gmail.com>
and that's the whole page, bestie!! π«Ά this was libibverbs, dated 2006-10-31, living in the ibv_get_cq_event(3) slot of the manual β a true classic, a vintage icon, and now you know her. go ack your events. periodt. πβ¨π
π¦ where this page comes from
- alpine 3.24: rdma-core-doc 61.0-r0 Β· GPL-2.0-only OR BSD-2-Clause
- arch rolling: rdma-core 65.0-1 Β· GPL-2.0-or-later OR LicenseRef-OpenIB.org-BSD-MIT AND GPL-2.0-or-later OR LicenseRef-OpenIB.org-BSD-FreeBSD AND GPL-2.0-or-later OR LicenseRef-Intel-BSD-3-Clause AND GPL-2.0-or-later OR LicenseRef-PathScale-BSD-Patent-License AND CC0-1.0 AND MIT AND BSD-2-Clause AND CPL-1.0 OR BSD-2-Clause OR GPL-2.0-or-later
- centos-stream 10: rdma-core-devel 62.0-3.el10 Β· GPLv2 or BSD
- centos-stream 9: rdma-core-devel 61.0-3.el9 Β· GPLv2 or BSD
- centos-stream 9: rdma-core-devel 61.0-3.el9 Β· GPLv2 or BSD
- debian bookworm: libibverbs-dev 44.0-2 Β· BSD-MIT OR GPL-2.0-only
- debian trixie: libibverbs-dev 56.1-1 Β· BSD-MIT OR GPL-2.0-only
- fedora 43: rdma-core-devel 58.0-4.fc43 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- fedora 43: rdma-core-devel 58.0-4.fc43 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- fedora 44: rdma-core-devel 61.0-2.fc44 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- fedora 44: rdma-core-devel 61.0-2.fc44 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- fedora 44: rdma-core-devel 61.1^20260812git975bdaf-1.fc44 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- fedora 44: rdma-core-devel 61.1^20260812git975bdaf-1.fc44 Β· GPL-2.0-only OR BSD-2-Clause AND BSD-3-Clause
- freebsd 14.5: base 14.5
- freebsd 15.1: base 15.1
- nixos 26.05: rdma-core 62.0
- nixpkgs unstable: rdma-core 65.0
- opensuse-leap 16.0: rdma-core-devel 56.1-160000.2.2 Β· BSD-2-Clause OR GPL-2.0-only
- opensuse-leap 16.0: rdma-core-devel 56.1-160000.2.2 Β· BSD-2-Clause OR GPL-2.0-only
- opensuse-leap 16.0: rdma-core-devel 56.1-160000.2.2 Β· BSD-2-Clause OR GPL-2.0-only
- opensuse-leap 16.0: rdma-core-devel 56.1-160000.2.2 Β· BSD-2-Clause OR GPL-2.0-only
- ubuntu jammy: libibverbs-dev 39.0-1 Β· BSD-MIT OR GPL-2.0-only
- ubuntu noble: libibverbs-dev 50.0-2build2 Β· BSD-MIT OR GPL-2.0-only
- ubuntu noble: libibverbs-dev 50.0-2ubuntu0.2 Β· BSD-MIT OR GPL-2.0-only
- ubuntu questing: libibverbs-dev 56.1-1ubuntu1
- ubuntu resolute: libibverbs-dev 61.0-2ubuntu3 Β· BSD-MIT OR GPL-2.0-only
- ubuntu stonking: libibverbs-dev 64.0-1ubuntu1 Β· BSD-MIT OR GPL-2.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms