Author: jh
Date: Mon Nov 22 16:47:53 2010
New Revision: 215687
URL: http://svn.freebsd.org/changeset/base/215687

Log:
  Use g_eventlock to protect against losing wakeups in the g_event process
  and replace tsleep(9) with msleep(9) which doesn't use a timeout. The
  previously used timeout caused the event process to wake up ten times
  per second on an idle system.
  
  one_event() is now called with the topology lock held and it returns
  with both the topology and event locks held when there are no more
  events in the queue.
  
  Reported by:  mav, Marius NĂ¼nnerich
  Reviewed by:  freebsd-geom

Modified:
  head/sys/geom/geom_event.c
  head/sys/geom/geom_kern.c

Modified: head/sys/geom/geom_event.c
==============================================================================
--- head/sys/geom/geom_event.c  Mon Nov 22 16:43:05 2010        (r215686)
+++ head/sys/geom/geom_event.c  Mon Nov 22 16:47:53 2010        (r215687)
@@ -183,33 +183,27 @@ one_event(void)
        struct g_event *ep;
        struct g_provider *pp;
 
-       g_topology_lock();
-       for (;;) {
-               mtx_lock(&g_eventlock);
-               TAILQ_FOREACH(pp, &g_doorstep, orphan) {
-                       if (pp->nstart == pp->nend)
-                               break;
-               }
-               if (pp != NULL) {
-                       G_VALID_PROVIDER(pp);
-                       TAILQ_REMOVE(&g_doorstep, pp, orphan);
-               }
-               mtx_unlock(&g_eventlock);
-               if (pp == NULL)
+       g_topology_assert();
+       mtx_lock(&g_eventlock);
+       TAILQ_FOREACH(pp, &g_doorstep, orphan) {
+               if (pp->nstart == pp->nend)
                        break;
+       }
+       if (pp != NULL) {
+               G_VALID_PROVIDER(pp);
+               TAILQ_REMOVE(&g_doorstep, pp, orphan);
+               mtx_unlock(&g_eventlock);
                g_orphan_register(pp);
+               return (1);
        }
-       mtx_lock(&g_eventlock);
+
        ep = TAILQ_FIRST(&g_events);
        if (ep == NULL) {
                wakeup(&g_pending_events);
-               mtx_unlock(&g_eventlock);
-               g_topology_unlock();
                return (0);
        }
        if (ep->flag & EV_INPROGRESS) {
                mtx_unlock(&g_eventlock);
-               g_topology_unlock();
                return (1);
        }
        ep->flag |= EV_INPROGRESS;
@@ -228,7 +222,6 @@ one_event(void)
                mtx_unlock(&g_eventlock);
                g_free(ep);
        }
-       g_topology_unlock();
        return (1);
 }
 
@@ -237,16 +230,27 @@ g_run_events()
 {
        int i;
 
-       while (one_event())
-               ;
-       g_topology_lock();
-       i = g_wither_work;
-       while (i) {
-               i = g_wither_washer();
-               g_wither_work = i & 1;
-               i &= 2;
+       for (;;) {
+               g_topology_lock();
+               while (one_event())
+                       ;
+               mtx_assert(&g_eventlock, MA_OWNED);
+               i = g_wither_work;
+               if (i) {
+                       mtx_unlock(&g_eventlock);
+                       while (i) {
+                               i = g_wither_washer();
+                               g_wither_work = i & 1;
+                               i &= 2;
+                       }
+                       g_topology_unlock();
+               } else {
+                       g_topology_unlock();
+                       msleep(&g_wait_event, &g_eventlock, PRIBIO | PDROP,
+                           "-", 0);
+               }
        }
-       g_topology_unlock();
+       /* NOTREACHED */
 }
 
 void
@@ -338,9 +342,12 @@ g_post_event(g_event_t *func, void *arg,
 }
 
 void
-g_do_wither() {
+g_do_wither()
+{
 
+       mtx_lock(&g_eventlock);
        g_wither_work = 1;
+       mtx_unlock(&g_eventlock);
        wakeup(&g_wait_event);
 }
 

Modified: head/sys/geom/geom_kern.c
==============================================================================
--- head/sys/geom/geom_kern.c   Mon Nov 22 16:43:05 2010        (r215686)
+++ head/sys/geom/geom_kern.c   Mon Nov 22 16:47:53 2010        (r215687)
@@ -137,10 +137,8 @@ g_event_procbody(void)
        thread_lock(tp);
        sched_prio(tp, PRIBIO);
        thread_unlock(tp);
-       for(;;) {
-               g_run_events();
-               tsleep(&g_wait_event, PRIBIO, "-", hz/10);
-       }
+       g_run_events();
+       /* NOTREACHED */
 }
 
 static struct kproc_desc g_event_kp = {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to