- NetBSD Manual Pages
PCQ(9) NetBSD Kernel Developer's Manual PCQ(9)
Powered by man-cgi (2021-06-01).
Maintained for NetBSD
by Kimmo Suominen.
Based on man-cgi by Panagiotis Christias.
pcq -- producer/consumer queue
pcq_create(size_t maxlen, km_flags_t kmflags);
pcq_put(pcq_t *pcq, void *item);
The machine-independent pcq interface provides lockless producer/consumer
queues. A queue (pcq_t) allows multiple writers (producers), but only a
single reader (consumer). The consumer is expected to be protected by a
lock that covers the structure that the pcq_t is embedded into (e.g.,
socket lock, ifnet hwlock). These queues operate in a first-in, first-
out (FIFO) manner. The act of inserting or removing an item from a pcq_t
does not modify the item in any way. pcq does not prevent an item from
being inserted multiple times into a single pcq_t.
Create a queue that can store at most maxlen items at one time.
kmflags should be either KM_SLEEP, if pcq_create() is allowed to
sleep until resources are available, or KM_NOSLEEP if it should
return NULL immediately, if resources are unavailable.
Free the resources held by pcq.
Remove the next item to be consumed from the queue and return
it. If the queue is empty, return NULL. The caller must pre-
vent concurrent gets from occurring.
Return the maximum number of items that the queue can store at
any one time.
Return the next item to be consumed from the queue but do not
remove it from the queue. If the queue is empty, return NULL.
Place an item at the end of the queue. If there is no room in
the queue for the item, return false; otherwise, return true.
The item must not have the value of NULL.
Any memory operations sequenced before pcq_put() of an item in one thread
happen before all memory operations with data dependencies on the item
returned by pcq_get() or pcq_peek() in another thread. For example:
/* producer */
mumble = 42; // A
foo->x = 123; // B
refcnt = foo->refcnt; // C
KASSERT(refcnt == 0);
/* consumer */
foo = pcq_get(pcq);
if (foo == NULL)
atomic_inc_uint(&foo->refcnt); // D
x = foo->x; // E
if (x == 123)
KASSERT(mumble == 42); // F
In this example, memory operations B and C happen-before D and E. How-
ever, no ordering is guaranteed for A or F relative to any other memory
operations, because the memory location of mumble is independent of the
pointer foo returned by pcq_get().
If you must guarantee A happens before F, then on the consumer side,
after pcq_get() or pcq_peek(), you can call membar_acquire() to turn it
into an acquire operation instead of a consume operation; pcq_put()
serves as the matching release operation. (This is a little dicey.
Perhaps there should be separate pcq_peek_acq() and pcq_get_acq()
operations if this semantics is necessary.)
The pcq interface is implemented within the file sys/kern/subr_pcq.c.
The pcq interface first appeared in NetBSD 6.0.
NetBSD 10.99 January 22, 2012 NetBSD 10.99