o .Vt pcq_t
c allows multiple writers
q producers , but only a single reader
q consumer . The consumer is expected to be protected by a lock that covers the structure that the .Vt pcq_t is embedded into
o e.g., socket lock, ifnet hwlock
c . These queues operate in a first-in, first-out
q FIFO manner. The act of inserting or removing an item from a .Vt pcq_t does not modify the item in any way. .Nm does not prevent an item from being inserted multiple times into a single .Vt pcq_t . .Sh FUNCTIONS l -tag -width compact t Fn pcq_create "maxlen" "kmflags" Create a queue that can store at most .Fa maxlen items at one time. .Fa kmflags should be either .Dv KM_SLEEP , if .Fn pcq_create is allowed to sleep until resources are available, or .Dv KM_NOSLEEP if it should return .Dv NULL immediately, if resources are unavailable. t Fn pcq_destroy "pcq" Free the resources held by .Fa pcq . t Fn pcq_get "pcq" Remove the next item to be consumed from the queue and return it. If the queue is empty, return .Dv NULL . The caller must prevent concurrent gets from occurring. t Fn pcq_maxitems "pcq" Return the maximum number of items that the queue can store at any one time. t Fn 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, return .Dv NULL . t Fn pcq_put "pcq" "item" Place an item at the end of the queue. If there is no room in the queue for the item, return .Dv false ; otherwise, return .Dv true . The item must not have the value of .Dv NULL . .El .Ss Memory ordering Any memory operations sequenced before .Fn pcq_put of an item in one thread happen before all memory operations with data dependencies on the item returned by .Fn pcq_get or .Fn pcq_peek in another thread. For example: d -literal -offset indent 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 .Ed
p 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 .Fa mumble is independent of the pointer .Fa foo returned by .Fn pcq_get .
p If you must guarantee A happens before F, then on the consumer side, after .Fn pcq_get or .Fn pcq_peek , you can call .Fn membar_acquire to turn it into an acquire operation instead of a consume operation; .Fn pcq_put serves as the matching release operation.
o This is a little dicey. Perhaps there should be separate .Fn pcq_peek_acq and .Fn pcq_get_acq operations if this semantics is necessary.
c .Sh CODE REFERENCES The .Nm interface is implemented within the file
a sys/kern/subr_pcq.c .
.Sh EXAMPLES
.Sh SEE ALSO
.Xr atomic_ops 3 ,
.Xr queue 3
.Sh HISTORY
The
.Nm
interface first appeared in
.Nx 6.0 .
.Sh CAVEATS
.Sh BUGS
.Sh SECURITY CONSIDERATIONS