qio: Ensure qwait() sets Qstarve
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 31 Aug 2015 20:51:46 +0000 (16:51 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 28 Sep 2015 19:14:00 +0000 (15:14 -0400)
Qstarve tracks the status of the queue.  When the flag is set, the queue
was checked and was found empty.  All of the wakeup code (grep dowakeup)
will check Qstarve.

A couple things to note:
- Qstarve is an optimization.  You should be able to just call
  rendez_wakeup and whatever else.  However, those can be expensive.
- This is false: "The queue is empty only if Qstarve is set".  It is
  possible for the queue to have been drained to 0, but not all the way,
and Qstarve is not set.  It will be set when some thread attempts to
extract data.

Ideally, this would be merged with the (already pushed)
3e0ae7c72ced ("qio: Add non-blocking queues")

kern/src/ns/qio.c

index 14a7f5e..8e469ee 100644 (file)
@@ -1234,12 +1234,14 @@ static bool qwait(struct queue *q)
                        }
                        return FALSE;
                }
+               /* We set Qstarve regardless of whether we are non-blocking or not.
+                * Qstarve tracks the edge detection of the queue being empty. */
+               q->state |= Qstarve;
                if (q->state & Qnonblock) {
                        spin_unlock_irqsave(&q->lock);
                        set_errno(EAGAIN);
                        error("queue empty");
                }
-               q->state |= Qstarve;    /* flag requesting producer to wake me */
                spin_unlock_irqsave(&q->lock);
                /* may throw an error() */
                rendez_sleep(&q->rr, notempty, q);