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
This commit is contained in:
Jaakko Heinonen 2010-11-22 16:47:53 +00:00
parent 4ed8ca8f25
commit f7842e00f5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215687
2 changed files with 39 additions and 34 deletions

View File

@ -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)
break;
g_orphan_register(pp);
}
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);
}
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, int flag, ...)
}
void
g_do_wither() {
g_do_wither()
{
mtx_lock(&g_eventlock);
g_wither_work = 1;
mtx_unlock(&g_eventlock);
wakeup(&g_wait_event);
}

View File

@ -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 = {