Introduce a g_waitfor_event() function which posts an event and waits for
it to be run (or cancelled) and use this instead of home-rolled versions.
This commit is contained in:
parent
356e4049da
commit
0a9c130c06
@ -211,6 +211,7 @@ void g_trace(int level, const char *, ...);
|
||||
typedef void g_event_t(void *, int flag);
|
||||
#define EV_CANCEL 1
|
||||
int g_post_event(g_event_t *func, void *arg, int flag, ...);
|
||||
int g_waitfor_event(g_event_t *func, void *arg, int flag, ...);
|
||||
void g_cancel_event(void *ref);
|
||||
void g_orphan_provider(struct g_provider *pp, int error);
|
||||
void g_waitidle(void);
|
||||
|
@ -375,7 +375,6 @@ g_kern_disks(void *p, int flag __unused)
|
||||
sp = " ";
|
||||
}
|
||||
sbuf_finish(sb);
|
||||
wakeup(sb);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -386,10 +385,7 @@ sysctl_disks(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
|
||||
sbuf_clear(sb);
|
||||
g_post_event(g_kern_disks, sb, M_WAITOK, NULL);
|
||||
while (!sbuf_done(sb)) {
|
||||
tsleep(sb, PZERO, "kern.disks", hz);
|
||||
}
|
||||
g_waitfor_event(g_kern_disks, sb, M_WAITOK, NULL);
|
||||
error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
|
||||
sbuf_delete(sb);
|
||||
return error;
|
||||
|
@ -106,7 +106,6 @@ g_confdot(void *p, int flag )
|
||||
g_confdot_class(sb, mp);
|
||||
sbuf_printf(sb, "};\n");
|
||||
sbuf_finish(sb);
|
||||
wakeup(p);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -150,7 +149,6 @@ g_conftxt(void *p, int flag)
|
||||
if (mp != NULL)
|
||||
g_conftxt_class(sb, mp);
|
||||
sbuf_finish(sb);
|
||||
wakeup(p);
|
||||
}
|
||||
|
||||
|
||||
@ -260,7 +258,6 @@ g_confxml(void *p, int flag)
|
||||
KASSERT(flag != EV_CANCEL, ("g_confxml was cancelled"));
|
||||
g_topology_assert();
|
||||
g_conf_specific(p, NULL, NULL, NULL, NULL);
|
||||
wakeup(p);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -64,11 +64,15 @@ static struct sx g_eventstall;
|
||||
|
||||
struct g_event {
|
||||
TAILQ_ENTRY(g_event) events;
|
||||
void *arg;
|
||||
g_event_t *func;
|
||||
void *arg;
|
||||
int flag;
|
||||
void *ref[G_N_EVENTREFS];
|
||||
};
|
||||
|
||||
#define EV_DONE 0x80000
|
||||
#define EV_WAKEUP 0x40000
|
||||
|
||||
void
|
||||
g_waitidle(void)
|
||||
{
|
||||
@ -180,7 +184,12 @@ one_event(void)
|
||||
g_topology_assert();
|
||||
ep->func(ep->arg, 0);
|
||||
g_topology_assert();
|
||||
g_destroy_event(ep);
|
||||
if (ep->flag & EV_WAKEUP) {
|
||||
ep->flag |= EV_DONE;
|
||||
wakeup(ep);
|
||||
} else {
|
||||
g_destroy_event(ep);
|
||||
}
|
||||
g_pending_events--;
|
||||
if (g_pending_events == 0)
|
||||
wakeup(&g_pending_events);
|
||||
@ -212,7 +221,12 @@ g_cancel_event(void *ref)
|
||||
if (ep->ref[n] == ref) {
|
||||
TAILQ_REMOVE(&g_events, ep, events);
|
||||
ep->func(ep->arg, EV_CANCEL);
|
||||
g_free(ep);
|
||||
if (ep->flag & EV_WAKEUP) {
|
||||
ep->flag |= EV_DONE;
|
||||
wakeup(ep);
|
||||
} else {
|
||||
g_destroy_event(ep);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -220,21 +234,18 @@ g_cancel_event(void *ref)
|
||||
mtx_unlock(&g_eventlock);
|
||||
}
|
||||
|
||||
int
|
||||
g_post_event(g_event_t *func, void *arg, int flag, ...)
|
||||
static int
|
||||
g_post_event_x(g_event_t *func, void *arg, int flag, struct g_event **epp, va_list ap)
|
||||
{
|
||||
struct g_event *ep;
|
||||
va_list ap;
|
||||
void *p;
|
||||
u_int n;
|
||||
|
||||
g_trace(G_T_TOPOLOGY, "g_post_event(%p, %p, %d", func, arg, flag);
|
||||
KASSERT(flag == M_NOWAIT || flag == M_WAITOK,
|
||||
("Wrong flag to g_post_event"));
|
||||
g_trace(G_T_TOPOLOGY, "g_post_event_x(%p, %p, %d", func, arg, flag);
|
||||
ep = g_malloc(sizeof *ep, flag | M_ZERO);
|
||||
if (ep == NULL)
|
||||
return (ENOMEM);
|
||||
va_start(ap, flag);
|
||||
ep->flag = flag;
|
||||
for (n = 0; n < G_N_EVENTREFS; n++) {
|
||||
p = va_arg(ap, void *);
|
||||
if (p == NULL)
|
||||
@ -251,6 +262,48 @@ g_post_event(g_event_t *func, void *arg, int flag, ...)
|
||||
TAILQ_INSERT_TAIL(&g_events, ep, events);
|
||||
mtx_unlock(&g_eventlock);
|
||||
wakeup(&g_wait_event);
|
||||
if (epp != NULL)
|
||||
*epp = ep;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
g_post_event(g_event_t *func, void *arg, int flag, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, flag);
|
||||
KASSERT(flag == M_WAITOK || flag == M_NOWAIT,
|
||||
("Wrong flag to g_post_event"));
|
||||
return (g_post_event_x(func, arg, flag, NULL, ap));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XXX: It might actually be useful to call this function with topology held.
|
||||
* XXX: This would ensure that the event gets created before anything else
|
||||
* XXX: changes. At present all users have a handle on things in some other
|
||||
* XXX: way, so this remains an XXX for now.
|
||||
*/
|
||||
|
||||
int
|
||||
g_waitfor_event(g_event_t *func, void *arg, int flag, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct g_event *ep;
|
||||
int error;
|
||||
|
||||
/* g_topology_assert_not(); */
|
||||
va_start(ap, flag);
|
||||
KASSERT(flag == M_WAITOK || flag == M_NOWAIT,
|
||||
("Wrong flag to g_post_event"));
|
||||
error = g_post_event_x(func, arg, flag | EV_WAKEUP, &ep, ap);
|
||||
if (error)
|
||||
return (error);
|
||||
do
|
||||
tsleep(ep, PRIBIO, "g_waitfor_event", hz);
|
||||
while (!(ep->flag & EV_DONE));
|
||||
g_destroy_event(ep);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -172,10 +172,7 @@ sysctl_kern_geom_conftxt(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
|
||||
sbuf_clear(sb);
|
||||
g_post_event(g_conftxt, sb, M_WAITOK, NULL);
|
||||
do {
|
||||
tsleep(sb, PZERO, "g_conftxt", hz);
|
||||
} while(!sbuf_done(sb));
|
||||
g_waitfor_event(g_conftxt, sb, M_WAITOK, NULL);
|
||||
error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
|
||||
sbuf_delete(sb);
|
||||
return error;
|
||||
@ -189,10 +186,7 @@ sysctl_kern_geom_confdot(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
|
||||
sbuf_clear(sb);
|
||||
g_post_event(g_confdot, sb, M_WAITOK, NULL);
|
||||
do {
|
||||
tsleep(sb, PZERO, "g_confdot", hz);
|
||||
} while(!sbuf_done(sb));
|
||||
g_waitfor_event(g_confdot, sb, M_WAITOK, NULL);
|
||||
error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
|
||||
sbuf_delete(sb);
|
||||
return error;
|
||||
@ -206,10 +200,7 @@ sysctl_kern_geom_confxml(SYSCTL_HANDLER_ARGS)
|
||||
|
||||
sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
|
||||
sbuf_clear(sb);
|
||||
g_post_event(g_confxml, sb, M_WAITOK, NULL);
|
||||
do {
|
||||
tsleep(sb, PZERO, "g_confxml", hz);
|
||||
} while(!sbuf_done(sb));
|
||||
g_waitfor_event(g_confxml, sb, M_WAITOK, NULL);
|
||||
error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
|
||||
sbuf_delete(sb);
|
||||
return error;
|
||||
|
@ -164,7 +164,6 @@ g_sunlabel_callconfig(void *arg, int flag)
|
||||
if (!hp->error)
|
||||
hp->error = g_write_data(LIST_FIRST(&hp->gp->consumer),
|
||||
0, hp->label, SUN_SIZE);
|
||||
wakeup(hp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -194,11 +193,8 @@ g_sunlabel_config(struct gctl_req *req, struct g_geom *gp, const char *verb)
|
||||
error = g_access_rel(cp, 1, 1, 1);
|
||||
if (error)
|
||||
return (error);
|
||||
g_post_event(g_sunlabel_callconfig, &h0h0, M_WAITOK, gp, NULL);
|
||||
g_topology_unlock();
|
||||
do
|
||||
tsleep(&h0h0, PRIBIO, "g_sunlabel_config", hz);
|
||||
while (h0h0.error == -1);
|
||||
g_waitfor_event(g_sunlabel_callconfig, &h0h0, M_WAITOK, gp, NULL);
|
||||
g_topology_lock();
|
||||
error = h0h0.error;
|
||||
g_access_rel(cp, -1, -1, -1);
|
||||
|
Loading…
Reference in New Issue
Block a user