qio: Only fire writable taps on edge transitions
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 6 Oct 2016 15:56:58 +0000 (11:56 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 6 Oct 2016 19:41:48 +0000 (15:41 -0400)
commitf202fd6937cf71d396b1388d9cd280a758fabb05
tree74360c9d3b332562a0246b8ac6bfb07ec881fac2
parent27c7c0faf2ab08ff42e42ea641e254cb5d96ae6b
qio: Only fire writable taps on edge transitions

We were firing writable taps (via the qwake_cb()) any time someone read
from a queue.  The effect of this was that applications that tapped their
Qdata FD would see a lot of writable taps firing, even though there wasn't
an edge transition.

For instance, say a conversation's write queue (outbound, TX) is no where
near full.  The app puts a packet in the queue.  When the network stack
drains the block from the queue with __qbread(), that will trigger a
writable tap.  So the app gets an FD tap / epoll every time it writes a
packet.  Incidentally, that behavior helped me track down a bug, but it
isn't what we're looking for.

Like the read side, we only fire on edge transitions, as done in commit
dbaaf4a3029e ("qio: Fire read taps on actual edges").  Back then, I had us
firing writable taps all the time, which was a bit much.

Note that we still fire the readable/writable taps regardless of
Qstarve/Qflow.  Those queue state flags only get set when someone tries to
read/write a queue and fails.  The taps we fire occur independently, which
is why their logic (e.g. was_empty / was_unwritable) are separate from the
rendez control variables (e.g. dowakeup).  This is probably right, since
it's possible for an application to know a queue would block without trying
(perhaps through stat()).

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/src/ns/qio.c