Event queue throttling (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 29 Aug 2011 22:06:19 +0000 (15:06 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:36:06 +0000 (17:36 -0700)
If an INDIR alert is pending for an ev_q, we won't send more til the
first one was acknowledged.  Some extras will make it through (due to
the nature of the race, but extras are always okay.

On a simple block test, this reduced the INDIRs by 10% - not a big deal.
If you want to turn it off for debugging reasons, comment out the
check/return block at the top of alert_vcore().  I want to leave it on
all the time, since it might help me catch a bug.

Reinstall your kernel headers / rebuild the parlib stuff.

kern/include/ros/event.h
kern/src/event.c
user/parlib/event.c
user/pthread/pthread.c

index 1eacd68..6ba7a45 100644 (file)
@@ -69,6 +69,7 @@ struct event_mbox {
 struct event_queue {
        struct event_mbox                       *ev_mbox;
        int                                                     ev_flags;
+       bool                                            ev_alert_pending;
        uint32_t                                        ev_vcore;
        void                                            (*ev_handler)(struct event_queue *);
 };
index 148481e..cfb9c24 100644 (file)
@@ -112,6 +112,21 @@ static uint32_t alert_vcore(struct proc *p, struct event_queue *ev_q,
                             uint32_t vcoreid)
 {
        int num_loops = 0;
+       /* If an alert is already pending, just return */
+       if (ev_q->ev_alert_pending)
+               return vcoreid;
+       /* We'll eventually get an INDIR through, so don't send any more til
+        * userspace toggles this.  Regardless of other writers to this flag, we
+        * eventually send an alert that causes userspace to turn throttling off
+        * again (before handling all of the ev_q's events).
+        *
+        * This will also squelch IPIs, since there's no reason to send the IPI if
+        * the INDIR is still un-acknowledged.  The vcore is either in vcore
+        * context, attempting to deal with the INDIR, or offline.  This statement
+        * is probably true. */
+       if (ev_q->ev_flags & EVENT_INDIR) {
+               ev_q->ev_alert_pending = TRUE;
+       }
        /* Don't care about FALLBACK, just send and be done with it */
        if (!ev_q->ev_flags & EVENT_FALLBACK) {
                if (ev_q->ev_flags & EVENT_INDIR)
index dd35b4e..0ec6680 100644 (file)
@@ -217,6 +217,14 @@ void handle_ev_ev(struct event_msg *ev_msg, unsigned int ev_type)
        ev_q = ev_msg->ev_arg3;
        /* Same deal, a null ev_q is probably a bug, or someone being a jackass */
        assert(ev_q);
+       /* Clear pending, so we can start getting INDIRs and IPIs again.  We must
+        * set this before (compared to handle_events, then set it, then handle
+        * again), since there is no guarantee handle_event_q() will return.  If
+        * there is a pending preemption, the vcore quickly yields and will deal
+        * with the remaining events in the future - meaning it won't return to
+        * here. */
+       ev_q->ev_alert_pending = FALSE;
+       wmb();                  /* should be unnecessary, due to the function call */
        handle_event_q(ev_q);
 }
 
index 77d847c..1fad3ad 100644 (file)
@@ -386,7 +386,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                     (uint32_t)(pthread->stacktop));
        pthread->start_routine = start_routine;
        pthread->arg = arg;
-       /* Initializse the uthread */
+       /* Initialize the uthread */
        uthread_init((struct uthread*)pthread);
        uthread_runnable((struct uthread*)pthread);
        *thread = pthread;