PCQ(9)
π pcq(9) β producer/consumer queue π
Okay bestie, this is the Kernel Developer's Manual page for pcq(9), with the manual name folded in right here at the top like a little name tag β¨.
πΈ NAME πΈ
pcq β producer/consumer queue π
β¨ SYNOPSIS β¨
#include <sys/pcq.h>
pcq_t *
pcq_create(size_t maxlen, km_flags_t kmflags);
void
pcq_destroy(pcq_t *pcq);
void *
pcq_get(pcq_t *pcq);
size_t
pcq_maxitems(pcq_t *pcq);
void *
pcq_peek(pcq_t *pcq);
bool
pcq_put(pcq_t *pcq, void *item);
π¦ DESCRIPTION π¦
So the machine-independent pcq interface gives you lockless producer/consumer queues. A queue (pcq_t) allows multiple writers β the producers β but only a single reader, aka the 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, no line-cutting allowed π. The act of inserting or removing an item from a pcq_t does not modify the item in any way. And heads up: pcq does not prevent an item from being inserted multiple times into a single pcq_t π.
π FUNCTIONS π
pcq_create(maxlen, kmflags)β Create a queue that can store at most maxlen items at one time.kmflagsshould be eitherKM_SLEEP, ifpcq_create()is allowed to sleep until resources are available, orKM_NOSLEEPif it should returnNULLimmediately, if resources are unavailable.pcq_destroy(pcq)β Free the resources held by pcq.pcq_get(pcq)β Remove the next item to be consumed from the queue and return it. If the queue is empty, returnNULL. The caller must prevent concurrent gets from occurring β one consumer only, no tag-teaming π .pcq_maxitems(pcq)β Return the maximum number of items that the queue can store at any one time.pcq_peek(pcq)β Return the next item to be consumed from the queue but do not remove it from the queue. If the queue is empty, returnNULL.pcq_put(pcq, item)β Place an item at the end of the queue. If there is no room in the queue for the item, returnfalse; otherwise, returntrue. The item must not have the value ofNULL.
π§ Memory ordering π§
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:
int mumble;
/* producer */
mumble = 42; // A
foo->x = 123; // B
refcnt = foo->refcnt; // C
pcq_put(pcq, foo);
KASSERT(refcnt == 0);
/* consumer */
foo = pcq_get(pcq);
if (foo == NULL)
return;
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. However, 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.)
π CODE REFERENCES π
The pcq interface is implemented within the file sys/kern/subr_pcq.c.
π SEE ALSO π
atomic_ops(3)queue(3)
β HISTORY β
The pcq interface first appeared in NetBSD 6.0.
Signed off with π from Debian on January 22, 2012 β PCQ(9), bestie, periodt. π«Ά
π¦ where this page comes from
- nixpkgs unstable: netbsd-source 11.0
- Copyright (c) 2010 The NetBSD Foundation, Inc
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms