| PCQ(9) | Kernel Developer's Manual | PCQ(9) | 
pcq —
#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);
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.
pcq_create(maxlen,
    kmflags)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.pcq_destroy(pcq)pcq_get(pcq)NULL. The caller must
      prevent concurrent gets from occurring.pcq_maxitems(pcq)pcq_peek(pcq)NULL.pcq_put(pcq,
    item)false; otherwise, return
      true. The item must not have the value of
      NULL.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.)
pcq interface is implemented within the file
  sys/kern/subr_pcq.c.
pcq interface first appeared in
  NetBSD 6.0.
| January 22, 2012 | NetBSD 10.0 |