svn commit: r185136 - user/kmacy/HEAD_fast_multi_xmit/sys/sys
Kip Macy
kmacy at FreeBSD.org
Thu Nov 20 16:57:50 PST 2008
Author: kmacy
Date: Fri Nov 21 00:57:50 2008
New Revision: 185136
URL: http://svn.freebsd.org/changeset/base/185136
Log:
- Add single consumer variant of dequeue for cases where
the consumer is already protected by a lock
- move enqueue/dequeue to critical sections to avoid starvation by preemption
Modified:
user/kmacy/HEAD_fast_multi_xmit/sys/sys/buf_ring.h
Modified: user/kmacy/HEAD_fast_multi_xmit/sys/sys/buf_ring.h
==============================================================================
--- user/kmacy/HEAD_fast_multi_xmit/sys/sys/buf_ring.h Fri Nov 21 00:48:57 2008 (r185135)
+++ user/kmacy/HEAD_fast_multi_xmit/sys/sys/buf_ring.h Fri Nov 21 00:57:50 2008 (r185136)
@@ -86,14 +86,17 @@ buf_ring_enqueue(struct buf_ring *br, vo
uint32_t cons_tail;
int success;
+ critical_enter();
do {
prod_head = br->br_prod_head;
cons_tail = br->br_cons_tail;
prod_next = (prod_head + 1) & br->br_prod_mask;
- if (prod_next == cons_tail)
+ if (prod_next == cons_tail) {
+ critical_exit();
return (ENOSPC);
+ }
success = atomic_cmpset_int(&br->br_prod_head, prod_head,
prod_next);
@@ -107,32 +110,38 @@ buf_ring_enqueue(struct buf_ring *br, vo
/*
* If there are other enqueues in progress
* that preceeded us, we need to wait for them
- * to complete - this is only a problem if they
- * have been preempted
+ * to complete
*/
while (br->br_prod_tail != prod_head)
cpu_spinwait();
br->br_prod_tail = prod_next;
-
+ critical_exit();
return (0);
}
+/*
+ * multi-consumer safe dequeue
+ *
+ */
static __inline void *
-buf_ring_dequeue(struct buf_ring *br)
+buf_ring_dequeue_mc(struct buf_ring *br)
{
uint32_t cons_head, cons_next;
uint32_t prod_tail;
void *buf;
int success;
-
+
+ critical_enter();
do {
cons_head = br->br_cons_head;
prod_tail = br->br_prod_tail;
cons_next = (cons_head + 1) & br->br_cons_mask;
- if (cons_head == prod_tail)
+ if (cons_head == prod_tail) {
+ critical_exit();
return (NULL);
+ }
success = atomic_cmpset_int(&br->br_cons_head, cons_head,
cons_next);
@@ -147,14 +156,53 @@ buf_ring_dequeue(struct buf_ring *br)
/*
* If there are other dequeues in progress
* that preceeded us, we need to wait for them
- * to complete - this is only a problem if they
- * have been preempted
+ * to complete
*/
while (br->br_cons_tail != cons_head)
cpu_spinwait();
br->br_cons_tail = cons_next;
+ mb();
+ critical_exit();
+
+ return (buf);
+}
+
+/*
+ * Single-Consumer dequeue for uses where dequeue
+ * is protected by a lock
+ */
+static __inline void *
+buf_ring_dequeue_sc(struct buf_ring *br)
+{
+ uint32_t cons_head, cons_next;
+ uint32_t prod_tail;
+ void *buf;
+
+ critical_enter();
+ cons_head = br->br_cons_head;
+ prod_tail = br->br_prod_tail;
+
+ cons_next = (cons_head + 1) & br->br_cons_mask;
+
+ if (cons_head == prod_tail) {
+ critical_exit();
+ return (NULL);
+ }
+
+ br->br_cons_head = cons_next;
+ buf = br->br_ring[cons_head];
+#ifdef INVARIANTS
+ br->br_ring[cons_head] = NULL;
+#endif
+ mb();
+ KASSERT(br->br_cons_tail == cons_head,
+ ("inconsistent list cons_tail=%d cons_head=%d",
+ br->br_cons_tail, cons_head));
+ br->br_cons_tail = cons_next;
+ mb();
+ critical_exit();
return (buf);
}
More information about the svn-src-user
mailing list