Motr  M0
LNet Buffer Event Queue Functional Specification

Data Structures

The circular queue is defined by the nlx_core_bev_cqueue data structure.

Subroutines

Subroutines are provided to:

See also
Detailed Functional Specification

Recipes

The nlx_core_bev_cqueue provides access to the producer and consumer elements in the circular queue.

In addition, semaphores or other synchronization mechanisms can be used to notify the producer or consumer when the queue changes, eg. when it becomes not empty.

Initialization

The circular queue is initialized as follows:

struct nlx_core_bev_cqueue myqueue;
NLX_ALLOC_PTR(e1, ...);
NLX_ALLOC_PTR(e2, ...);
bev_cqueue_init(&myqueue, &e1->cbe_tm_link, &e2->cbe_tm_link);

Allocator

The event queue can be expanded to make room for additional buffer events. This should be performed before buffers are queued. One element should exist on the event queue for each expected buffer operation, plus one additional element for the "current" buffer operation.

size_t needed;
... ; // acquire the lock shared with the consumer
while (needed > bev_cqueue_size(&myqueue)) {
... ; // initialize the new element for both address spaces
bev_cqueue_add(&myqueue, el);
}
... ; // release the lock shared with the consumer

Producer

The (single) producer works in a loop, putting event notifications in the queue:

bool done;
struct nlx_core_bev_link *ql;
while (!done) {
ql = bev_cqueue_pnext(&myqueue);
... ; // initialize the element
bev_cqueue_put(&myqueue, ql);
... ; // notify blocked consumer that data is available
}

Consumer

The (single) consumer works in a loop, consuming data from the queue:

bool done;
struct nlx_core_bev_link *ql;
while (!done) {
... ; // acquire the lock shared with the allocator
ql = bev_cqueue_get(&myqueue);
if (ql == NULL) {
... ; // unlock a lock shared with the allocator
... ; // block until data is available
continue;
}
... ; // operate on the current element
... ; // release the lock shared with the allocator
}
See also
Detailed Functional Specification