ibv_get_cq_event, ibv_ack_cq_events

Gets and acknowledges 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

ibv_get_cq_event() waits for the next completion event in the completion event channel channel. The argument cq is used to return the CQ that caused the event and cq_context is used to return the context of the CQ.

ibv_ack_cq_events() acknowledges nevents events on the CQ cq.

Notes:
  • All completion events that ibv_get_cq_event() returns must be acknowledged using ibv_ack_cq_events().
  • To avoid races, when you destroy a CQ, the CQ waits for the completion of the events. This guarantees a one-to-one correspondence between acknowledgements and successful gets.
  • When you call the ibv_ack_cq_events() function, it might be relatively expensive in the datapath, since it must take a mutex. Therefore it might be better to amortize this cost by keeping a count of the number of events needing acknowledgement and acknowledging several completion events in one call to ibv_ack_cq_events().

Input Parameters

channel struct ibv_comp_channel from ibv_create_comp_channel.

Output Parameters

cq Pointer to the completion queue (CQ) associated with event.
cq_context User supplied context set in ibv_create_cq.

Return Value

The ibv_get_cq_event, and ibv_ack_cq_events functions return 0 on success, and -1 if the request fails.

Examples

  1. The following code example demonstrates one possible way to work with completion events. It performs the following steps:
    1. Preparation
      1. Creates a CQ.
      2. Requests for notification upon a new (first) completion event.
    2. Completion handling routine
      1. Waits for the completion event and ack it.
      2. Requests for notification upon the next completion event.
      3. Empties the CQ.
      Note: An extra event might 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, and 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, "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(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;
    				}
    				if (wc.status != IBV_WC_SUCCESS) {
    						fprintf(stderr, "Completion with status 0x%x was found\n", wc.status);
    						return 1;
    				}
    		} while (ne);
  2. The following code example demonstrates one possible way to work with completion events in nonblocking mode. It performs the following steps:
    1. Sets the completion event channel in the non-blocked mode.
    2. Polls the channel until there it has a completion event.
    3. 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 &lt; 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); 
[ Feedback ]