diff options
Diffstat (limited to 'tools/tools/netmap/nm_util.c')
-rw-r--r-- | tools/tools/netmap/nm_util.c | 91 |
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 */ |