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:
Poul-Henning Kamp 2003-04-23 21:28:27 +00:00
parent 356e4049da
commit 0a9c130c06
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=113940
6 changed files with 69 additions and 35 deletions

View File

@ -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);

View File

@ -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;

View File

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

View File

@ -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);
}

View File

@ -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;

View File

@ -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);