aboutsummaryrefslogtreecommitdiff
path: root/tools/tools/netmap/nm_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/tools/netmap/nm_util.c')
-rw-r--r--tools/tools/netmap/nm_util.c91
1 files changed, 89 insertions, 2 deletions
diff --git a/tools/tools/netmap/nm_util.c b/tools/tools/netmap/nm_util.c
index 195b68776c3b..1268840cd868 100644
--- a/tools/tools/netmap/nm_util.c
+++ b/tools/tools/netmap/nm_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 Luigi Rizzo. All rights reserved.
+ * Copyright (C) 2012-2014 Luigi Rizzo. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -232,7 +232,7 @@ pkt_queued(struct my_ring *me, int tx)
for (i = me->begin; i < me->end; i++) {
struct netmap_ring *ring = tx ?
NETMAP_TXRING(me->nifp, i) : NETMAP_RXRING(me->nifp, i);
- tot += ring->avail;
+ tot += nm_ring_space(ring);
}
if (0 && verbose && tot && !tx)
D("ring %s %s %s has %d avail at %d",
@@ -242,3 +242,90 @@ pkt_queued(struct my_ring *me, int tx)
tot, NETMAP_TXRING(me->nifp, me->begin)->cur);
return tot;
}
+
+#if 0
+
+/*
+ *
+
+Helper routines for multiple readers from the same queue
+
+- all readers open the device in 'passive' mode (NETMAP_PRIV_RING set).
+ In this mode a thread that loses the race on a poll() just continues
+ without calling *xsync()
+
+- all readers share an extra 'ring' which contains the sync information.
+ In particular we have a shared head+tail pointers that work
+ together with cur and available
+ ON RETURN FROM THE SYSCALL:
+ shadow->head = ring->cur
+ shadow->tail = ring->tail
+ shadow->link[i] = i for all slots // mark invalid
+
+ */
+
+struct nm_q_arg {
+ u_int want; /* Input */
+ u_int have; /* Output, 0 on error */
+ u_int head;
+ u_int tail;
+ struct netmap_ring *ring;
+};
+
+/*
+ * grab a number of slots from the queue.
+ */
+struct nm_q_arg
+my_grab(struct nm_q_arg q)
+{
+ const u_int ns = q.ring->num_slots;
+
+ for (;;) {
+
+ q.head = (volatile u_int)q.ring->head;
+ q.have = ns + q.head - (volatile u_int)q.ring->tail;
+ if (q.have >= ns)
+ q.have -= ns;
+ if (q.have == 0) /* no space */
+ break;
+ if (q.want < q.have)
+ q.have = q.want;
+ q.tail = q.head + q.have;
+ if (q.tail >= ns)
+ q.tail -= ns;
+ if (atomic_cmpset_int(&q.ring->head, q.head, q.tail)
+ break; /* success */
+ }
+ D("returns %d out of %d at %d,%d",
+ q.have, q.want, q.head, q.tail);
+ /* the last one can clear avail ? */
+ return q;
+}
+
+
+int
+my_release(struct nm_q_arg q)
+{
+ u_int head = q.head, tail = q.tail, i;
+ struct netmap_ring *r = q.ring;
+
+ /* link the block to the next one.
+ * there is no race here because the location is mine.
+ */
+ r->slot[head].ptr = tail; /* this is mine */
+ // memory barrier
+ if (r->head != head)
+ return; /* not my turn to release */
+ for (;;) {
+ // advance head
+ r->head = head = r->slot[head].ptr;
+ // barrier ?
+ if (head == r->slot[head].ptr)
+ break; // stop here
+ }
+ /* we have advanced from q.head to head (r.head might be
+ * further down.
+ */
+ // do an ioctl/poll to flush.
+}
+#endif /* unused */