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:
parent
4ed8ca8f25
commit
f7842e00f5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215687
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 = {
|
||||
|
Loading…
Reference in New Issue
Block a user