Introduce the __ptr_ring_full_next() helper, which lets callers check
if the ptr_ring will become full after the next insertion. This is useful
for proactively managing capacity before the ring is actually full.
Callers must ensure the ring is not already full before using this
helper. This is because __ptr_ring_discard_one() may zero entries in
reverse order, the slot after the current producer position may be
cleared before the current one. This must be considered when using this
check.

Note: This function is especially relevant when paired with the memory
ordering guarantees of __ptr_ring_produce() (smp_wmb()), allowing for
safe producer/consumer coordination.

Co-developed-by: Tim Gebauer <[email protected]>
Signed-off-by: Tim Gebauer <[email protected]>
Co-developed-by: Jon Kohler <[email protected]>
Signed-off-by: Jon Kohler <[email protected]>
Signed-off-by: Simon Schippers <[email protected]>
---
 include/linux/ptr_ring.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h
index 534531807d95..da141cc8b075 100644
--- a/include/linux/ptr_ring.h
+++ b/include/linux/ptr_ring.h
@@ -96,6 +96,31 @@ static inline bool ptr_ring_full_bh(struct ptr_ring *r)
        return ret;
 }
 
+/*
+ * Checks if the ptr_ring will become full after the next insertion.
+ *
+ * Note: Callers must ensure that the ptr_ring is not full before calling
+ * this function, as __ptr_ring_discard_one invalidates entries in
+ * reverse order. Because the next entry (rather than the current one)
+ * may be zeroed after an insertion, failing to account for this can
+ * cause false negatives when checking whether the ring will become full
+ * on the next insertion.
+ */
+static inline bool __ptr_ring_full_next(struct ptr_ring *r)
+{
+       int p;
+
+       if (unlikely(r->size <= 1))
+               return true;
+
+       p = r->producer + 1;
+
+       if (unlikely(p >= r->size))
+               p = 0;
+
+       return r->queue[p];
+}
+
 /* Note: callers invoking this in a loop must use a compiler barrier,
  * for example cpu_relax(). Callers must hold producer_lock.
  * Callers are responsible for making sure pointer that is being queued
-- 
2.43.0


Reply via email to