186 lines
4.7 KiB
Groff
186 lines
4.7 KiB
Groff
.\" -*- nroff -*-
|
|
.\"
|
|
.TH IBV_GET_CQ_EVENT 3 2006-10-31 libibverbs "Libibverbs Programmer's Manual"
|
|
.SH "NAME"
|
|
ibv_get_cq_event, ibv_ack_cq_events \- get and acknowledge completion queue (CQ) events
|
|
|
|
.SH "SYNOPSIS"
|
|
.nf
|
|
.B #include <infiniband/verbs.h>
|
|
.sp
|
|
.BI "int ibv_get_cq_event(struct ibv_comp_channel " "*channel" ,
|
|
.BI " struct ibv_cq " "**cq" ", void " "**cq_context" );
|
|
.sp
|
|
.BI "void ibv_ack_cq_events(struct ibv_cq " "*cq" ", unsigned int " "nevents" );
|
|
.fi
|
|
|
|
.SH "DESCRIPTION"
|
|
.B ibv_get_cq_event()
|
|
waits for the next completion event in the completion event channel
|
|
.I channel\fR.
|
|
Fills the arguments
|
|
.I cq
|
|
with the CQ that got the event and
|
|
.I cq_context
|
|
with the CQ's context\fR.
|
|
.PP
|
|
.B ibv_ack_cq_events()
|
|
acknowledges
|
|
.I nevents
|
|
events on the CQ
|
|
.I cq\fR.
|
|
|
|
.SH "RETURN VALUE"
|
|
.B ibv_get_cq_event()
|
|
returns 0 on success, and \-1 on error.
|
|
.PP
|
|
.B ibv_ack_cq_events()
|
|
returns no value.
|
|
.SH "NOTES"
|
|
All completion events that
|
|
.B ibv_get_cq_event()
|
|
returns must be acknowledged using
|
|
.B ibv_ack_cq_events()\fR.
|
|
To avoid races, destroying a CQ will wait for all completion events to
|
|
be acknowledged; this guarantees a one-to-one correspondence between
|
|
acks and successful gets.
|
|
.PP
|
|
Calling
|
|
.B ibv_ack_cq_events()
|
|
may be relatively expensive in the datapath, since it must take a
|
|
mutex. Therefore it may be better to amortize this cost by
|
|
keeping a count of the number of events needing acknowledgement and
|
|
acking several completion events in one call to
|
|
.B ibv_ack_cq_events()\fR.
|
|
.SH "EXAMPLES"
|
|
The following code example demonstrates one possible way to work with
|
|
completion events. It performs the following steps:
|
|
.PP
|
|
Stage I: Preparation
|
|
.br
|
|
1. Creates a CQ
|
|
.br
|
|
2. Requests for notification upon a new (first) completion event
|
|
.PP
|
|
Stage II: Completion Handling Routine
|
|
.br
|
|
3. Wait for the completion event and ack it
|
|
.br
|
|
4. Request for notification upon the next completion event
|
|
.br
|
|
5. Empty the CQ
|
|
.PP
|
|
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.
|
|
.PP
|
|
.nf
|
|
cq = ibv_create_cq(ctx, 1, ev_ctx, channel, 0);
|
|
if (!cq) {
|
|
fprintf(stderr, "Failed to create CQ\en");
|
|
return 1;
|
|
}
|
|
.PP
|
|
/* Request notification before any completion can be created */
|
|
if (ibv_req_notify_cq(cq, 0)) {
|
|
fprintf(stderr, "Couldn't request CQ notification\en");
|
|
return 1;
|
|
}
|
|
.PP
|
|
\&.
|
|
\&.
|
|
\&.
|
|
.PP
|
|
/* Wait for the completion event */
|
|
if (ibv_get_cq_event(channel, &ev_cq, &ev_ctx)) {
|
|
fprintf(stderr, "Failed to get cq_event\en");
|
|
return 1;
|
|
}
|
|
|
|
/* Ack the event */
|
|
ibv_ack_cq_events(ev_cq, 1);
|
|
.PP
|
|
/* Request notification upon the next completion event */
|
|
if (ibv_req_notify_cq(ev_cq, 0)) {
|
|
fprintf(stderr, "Couldn't request CQ notification\en");
|
|
return 1;
|
|
}
|
|
.PP
|
|
/* 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\en");
|
|
return 1;
|
|
}
|
|
|
|
/* there may be an extra event with no completion in the CQ */
|
|
if (ne == 0)
|
|
continue;
|
|
.PP
|
|
if (wc.status != IBV_WC_SUCCESS) {
|
|
fprintf(stderr, "Completion with status 0x%x was found\en", wc.status);
|
|
return 1;
|
|
}
|
|
} while (ne);
|
|
.fi
|
|
|
|
The following code example demonstrates one possible way to work with
|
|
completion events in non-blocking mode. It performs the following
|
|
steps:
|
|
.PP
|
|
1. Set the completion event channel to be non-blocked
|
|
.br
|
|
2. Poll the channel until there it has a completion event
|
|
.br
|
|
3. Get the completion event and ack it
|
|
.PP
|
|
.nf
|
|
/* 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\en");
|
|
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\en");
|
|
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\en");
|
|
return 1;
|
|
}
|
|
|
|
/* Ack the event */
|
|
ibv_ack_cq_events(ev_cq, 1);
|
|
|
|
.fi
|
|
.SH "SEE ALSO"
|
|
.BR ibv_create_comp_channel (3),
|
|
.BR ibv_create_cq (3),
|
|
.BR ibv_req_notify_cq (3),
|
|
.BR ibv_poll_cq (3)
|
|
|
|
.SH "AUTHORS"
|
|
.TP
|
|
Dotan Barak
|
|
.RI < dotanb@mellanox.co.il >
|