avoid calling into the pool code while holding sched_lock
since both pool_get() and pool_put() can call wakeup(). instead, allocate the struct sadata_upcall before taking sched_lock in mi_switch() and free it after releasing sched_lock. clean up some modularity warts by adding a callback to struct sadata_upcall for freeing sa_arg.
This commit is contained in:
parent
9c47d944e4
commit
7c02feca68
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_sa.c,v 1.65 2005/09/07 23:31:06 christos Exp $ */
|
||||
/* $NetBSD: kern_sa.c,v 1.66 2005/10/02 17:51:27 chs Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2004, 2005 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.65 2005/09/07 23:31:06 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_sa.c,v 1.66 2005/10/02 17:51:27 chs Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -70,8 +70,8 @@ static struct lwp *sa_vp_repossess(struct lwp *l);
|
|||
|
||||
static __inline int sa_pagefault(struct lwp *, ucontext_t *);
|
||||
|
||||
static int sa_upcall0(struct lwp *, int, struct lwp *, struct lwp *,
|
||||
size_t, void *, struct sadata_upcall *);
|
||||
static void sa_upcall0(struct sadata_upcall *, int, struct lwp *, struct lwp *,
|
||||
size_t, void *, void (*)(void *));
|
||||
static void sa_upcall_getstate(union sau_state *, struct lwp *);
|
||||
|
||||
MALLOC_DEFINE(M_SA, "sa", "Scheduler activations");
|
||||
|
@ -109,39 +109,30 @@ SPLAY_GENERATE(sasttree, sastack, sast_node, sast_compare);
|
|||
struct sadata_upcall *
|
||||
sadata_upcall_alloc(int waitok)
|
||||
{
|
||||
struct sadata_upcall *sau;
|
||||
|
||||
/* XXX zero the memory? */
|
||||
return (pool_get(&saupcall_pool, waitok ? PR_WAITOK : PR_NOWAIT));
|
||||
sau = pool_get(&saupcall_pool, waitok ? PR_WAITOK : PR_NOWAIT);
|
||||
if (sau) {
|
||||
sau->sau_arg = NULL;
|
||||
}
|
||||
return sau;
|
||||
}
|
||||
|
||||
/*
|
||||
* sadata_upcall_free:
|
||||
*
|
||||
* Free an sadata_upcall structure, and any associated
|
||||
* argument data.
|
||||
* Free an sadata_upcall structure and any associated argument data.
|
||||
*/
|
||||
void
|
||||
sadata_upcall_free(struct sadata_upcall *sau)
|
||||
{
|
||||
extern struct pool siginfo_pool; /* XXX Ew. */
|
||||
|
||||
/*
|
||||
* XXX We have to know what the origin of sau_arg is
|
||||
* XXX in order to do the right thing, here. Sucks
|
||||
* XXX to be a non-garbage-collecting kernel.
|
||||
*/
|
||||
if (sau->sau_arg) {
|
||||
switch (sau->sau_type) {
|
||||
case SA_UPCALL_SIGNAL:
|
||||
case SA_UPCALL_SIGEV:
|
||||
pool_put(&siginfo_pool, sau->sau_arg);
|
||||
break;
|
||||
default:
|
||||
panic("sadata_free: unknown type of sau_arg: %d",
|
||||
sau->sau_type);
|
||||
}
|
||||
if (sau == NULL) {
|
||||
return;
|
||||
}
|
||||
if (sau->sau_arg) {
|
||||
(*sau->sau_argfreefunc)(sau->sau_arg);
|
||||
}
|
||||
|
||||
pool_put(&saupcall_pool, sau);
|
||||
}
|
||||
|
||||
|
@ -443,7 +434,7 @@ sys_sa_enable(struct lwp *l, void *v, register_t *retval)
|
|||
if (p->p_flag & P_SA) /* Already running! */
|
||||
return (EBUSY);
|
||||
|
||||
error = sa_upcall(l, SA_UPCALL_NEWPROC, l, NULL, 0, NULL);
|
||||
error = sa_upcall(l, SA_UPCALL_NEWPROC, l, NULL, 0, NULL, NULL);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
|
@ -496,7 +487,7 @@ sa_increaseconcurrency(struct lwp *l, int concurrency)
|
|||
l2->l_savp->savp_lwp = l2;
|
||||
cpu_setfunc(l2, sa_switchcall, NULL);
|
||||
error = sa_upcall(l2, SA_UPCALL_NEWPROC,
|
||||
NULL, NULL, 0, NULL);
|
||||
NULL, NULL, 0, NULL, NULL);
|
||||
if (error) {
|
||||
/* free new savp */
|
||||
SLIST_REMOVE(&sa->sa_vps, l2->l_savp,
|
||||
|
@ -587,11 +578,14 @@ sys_sa_setconcurrency(struct lwp *l, void *v, register_t *retval)
|
|||
vp->savp_lwp->l_flag &=
|
||||
~(L_SA_IDLE|L_SA_YIELD|L_SINTR);
|
||||
SCHED_UNLOCK(s);
|
||||
DPRINTFN(11,("sys_sa_concurrency(%d.%d) NEWPROC vp %d\n",
|
||||
l->l_proc->p_pid, l->l_lid, vp->savp_id));
|
||||
DPRINTFN(11,("sys_sa_concurrency(%d.%d) "
|
||||
"NEWPROC vp %d\n",
|
||||
l->l_proc->p_pid, l->l_lid,
|
||||
vp->savp_id));
|
||||
cpu_setfunc(vp->savp_lwp, sa_switchcall, NULL);
|
||||
/* error = */ sa_upcall(vp->savp_lwp, SA_UPCALL_NEWPROC,
|
||||
NULL, NULL, 0, NULL);
|
||||
/* error = */ sa_upcall(vp->savp_lwp,
|
||||
SA_UPCALL_NEWPROC,
|
||||
NULL, NULL, 0, NULL, NULL);
|
||||
SCHED_LOCK(s);
|
||||
sa->sa_concurrency++;
|
||||
setrunnable(vp->savp_lwp);
|
||||
|
@ -721,7 +715,7 @@ sa_preempt(struct lwp *l)
|
|||
*/
|
||||
if (sa->sa_flag & SA_FLAG_PREEMPT)
|
||||
sa_upcall(l, SA_UPCALL_PREEMPTED | SA_UPCALL_DEFER_EVENT,
|
||||
l, NULL, 0, NULL);
|
||||
l, NULL, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -733,13 +727,13 @@ sa_preempt(struct lwp *l)
|
|||
*/
|
||||
int
|
||||
sa_upcall(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted,
|
||||
size_t argsize, void *arg)
|
||||
size_t argsize, void *arg, void (*func)(void *))
|
||||
{
|
||||
struct sadata_upcall *sau;
|
||||
struct sadata *sa = l->l_proc->p_sa;
|
||||
struct sadata_vp *vp = l->l_savp;
|
||||
struct sastack *sast;
|
||||
int error, f;
|
||||
int f;
|
||||
|
||||
/* XXX prevent recursive upcalls if we sleep for memory */
|
||||
SA_LWP_STATE_LOCK(l, f);
|
||||
|
@ -754,12 +748,7 @@ sa_upcall(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted,
|
|||
SA_LWP_STATE_LOCK(l, f);
|
||||
sau = sadata_upcall_alloc(1);
|
||||
SA_LWP_STATE_UNLOCK(l, f);
|
||||
error = sa_upcall0(l, type, event, interrupted, argsize, arg, sau);
|
||||
if (error) {
|
||||
sadata_upcall_free(sau);
|
||||
sa_setstackfree(sast, sa);
|
||||
return (error);
|
||||
}
|
||||
sa_upcall0(sau, type, event, interrupted, argsize, arg, func);
|
||||
sau->sau_stack = sast->sast_stack;
|
||||
|
||||
SIMPLEQ_INSERT_TAIL(&vp->savp_upcalls, sau, sau_next);
|
||||
|
@ -768,15 +757,14 @@ sa_upcall(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted,
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
sa_upcall0(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted,
|
||||
size_t argsize, void *arg, struct sadata_upcall *sau)
|
||||
static void
|
||||
sa_upcall0(struct sadata_upcall *sau, int type, struct lwp *event,
|
||||
struct lwp *interrupted, size_t argsize, void *arg, void (*func)(void *))
|
||||
{
|
||||
|
||||
KDASSERT((event == NULL) || (event != interrupted));
|
||||
|
||||
sau->sau_flags = 0;
|
||||
sau->sau_arg = 0;
|
||||
|
||||
if (type & SA_UPCALL_DEFER_EVENT) {
|
||||
sau->sau_event.ss_deferred.ss_lwp = event;
|
||||
|
@ -792,8 +780,7 @@ sa_upcall0(struct lwp *l, int type, struct lwp *event, struct lwp *interrupted,
|
|||
sau->sau_type = type & SA_UPCALL_TYPE_MASK;
|
||||
sau->sau_argsize = argsize;
|
||||
sau->sau_arg = arg;
|
||||
|
||||
return (0);
|
||||
sau->sau_argfreefunc = func;
|
||||
}
|
||||
|
||||
|
||||
|
@ -868,14 +855,15 @@ sa_pagefault(struct lwp *l, ucontext_t *l_ctx)
|
|||
* TSLEEP() ITSELF! We are called with sched_lock held, and must
|
||||
* hold it right through the mi_switch() call.
|
||||
*/
|
||||
|
||||
void
|
||||
sa_switch(struct lwp *l, int type)
|
||||
sa_switch(struct lwp *l, struct sadata_upcall *sau, int type)
|
||||
{
|
||||
struct proc *p = l->l_proc;
|
||||
struct sadata_vp *vp = l->l_savp;
|
||||
struct sadata_upcall *sau;
|
||||
struct lwp *l2;
|
||||
int error, s;
|
||||
struct sadata_upcall *freesau = NULL;
|
||||
int s;
|
||||
|
||||
DPRINTFN(4,("sa_switch(%d.%d type %d VP %d)\n", p->p_pid, l->l_lid,
|
||||
type, vp->savp_lwp ? vp->savp_lwp->l_lid : 0));
|
||||
|
@ -884,10 +872,12 @@ sa_switch(struct lwp *l, int type)
|
|||
|
||||
if (p->p_flag & P_WEXIT) {
|
||||
mi_switch(l, NULL);
|
||||
sadata_upcall_free(sau);
|
||||
return;
|
||||
}
|
||||
|
||||
if (l->l_flag & L_SA_YIELD) {
|
||||
|
||||
/*
|
||||
* Case 0: we're blocking in sa_yield
|
||||
*/
|
||||
|
@ -902,6 +892,7 @@ sa_switch(struct lwp *l, int type)
|
|||
s = splsched();
|
||||
SCHED_UNLOCK(s);
|
||||
}
|
||||
sadata_upcall_free(sau);
|
||||
return;
|
||||
} else if (vp->savp_lwp == l) {
|
||||
/*
|
||||
|
@ -910,6 +901,15 @@ sa_switch(struct lwp *l, int type)
|
|||
* UNBLOCKED upcall.
|
||||
*/
|
||||
|
||||
if (sau == NULL) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("sa_switch(%d.%d): no upcall data.\n",
|
||||
p->p_pid, l->l_lid);
|
||||
#endif
|
||||
mi_switch(l, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The process of allocating a new LWP could cause
|
||||
* sleeps. We're called from inside sleep, so that
|
||||
|
@ -931,38 +931,12 @@ sa_switch(struct lwp *l, int type)
|
|||
p->p_pid, l->l_lid);
|
||||
#endif
|
||||
mi_switch(l, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX We need to allocate the sadata_upcall structure here,
|
||||
* XXX since we can't sleep while waiting for memory inside
|
||||
* XXX sa_upcall(). It would be nice if we could safely
|
||||
* XXX allocate the sadata_upcall structure on the stack, here.
|
||||
*/
|
||||
sau = sadata_upcall_alloc(0);
|
||||
if (sau == NULL) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("sa_switch(%d.%d): couldn't allocate upcall data.\n",
|
||||
p->p_pid, l->l_lid);
|
||||
#endif
|
||||
sa_putcachelwp(p, l2); /* PHOLD from sa_getcachelwp */
|
||||
mi_switch(l, NULL);
|
||||
sadata_upcall_free(sau);
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_setfunc(l2, sa_switchcall, sau);
|
||||
error = sa_upcall0(l2, SA_UPCALL_BLOCKED, l, NULL, 0, NULL,
|
||||
sau);
|
||||
if (error) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("sa_switch(%d.%d): Error %d from sa_upcall()\n",
|
||||
p->p_pid, l->l_lid, error);
|
||||
#endif
|
||||
sa_putcachelwp(p, l2); /* PHOLD from sa_getcachelwp */
|
||||
mi_switch(l, NULL);
|
||||
return;
|
||||
}
|
||||
sa_upcall0(sau, SA_UPCALL_BLOCKED, l, NULL, 0, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Perform the double/upcall pagefault check.
|
||||
|
@ -975,9 +949,9 @@ sa_switch(struct lwp *l, int type)
|
|||
*/
|
||||
if ((l->l_flag & L_SA_PAGEFAULT) && sa_pagefault(l,
|
||||
&sau->sau_event.ss_captured.ss_ctx) != 0) {
|
||||
sadata_upcall_free(sau);
|
||||
sa_putcachelwp(p, l2); /* PHOLD from sa_getcachelwp */
|
||||
mi_switch(l, NULL);
|
||||
sadata_upcall_free(sau);
|
||||
DPRINTFN(10,("sa_switch(%d.%d) page fault resolved\n",
|
||||
p->p_pid, l->l_lid));
|
||||
if (vp->savp_faultaddr == vp->savp_ofaultaddr)
|
||||
|
@ -997,6 +971,7 @@ sa_switch(struct lwp *l, int type)
|
|||
|
||||
KDASSERT(l2 != l);
|
||||
} else if (vp->savp_lwp != NULL) {
|
||||
|
||||
/*
|
||||
* Case 2: We've been woken up while another LWP was
|
||||
* on the VP, but we're going back to sleep without
|
||||
|
@ -1007,11 +982,13 @@ sa_switch(struct lwp *l, int type)
|
|||
* go. If the LWP on the VP was idling, don't make it
|
||||
* run again, though.
|
||||
*/
|
||||
freesau = sau;
|
||||
if (vp->savp_lwp->l_flag & L_SA_YIELD)
|
||||
l2 = NULL;
|
||||
else {
|
||||
l2 = vp->savp_lwp; /* XXXUPSXXX Unfair advantage for l2 ? */
|
||||
if((l2->l_stat != LSRUN) || ((l2->l_flag & L_INMEM) == 0))
|
||||
/* XXXUPSXXX Unfair advantage for l2 ? */
|
||||
l2 = vp->savp_lwp;
|
||||
if (l2->l_stat != LSRUN || (l2->l_flag & L_INMEM) == 0)
|
||||
l2 = NULL;
|
||||
}
|
||||
} else {
|
||||
|
@ -1022,7 +999,7 @@ sa_switch(struct lwp *l, int type)
|
|||
DPRINTFN(4,("sa_switch(%d.%d) switching to LWP %d.\n",
|
||||
p->p_pid, l->l_lid, l2 ? l2->l_lid : 0));
|
||||
mi_switch(l, l2);
|
||||
|
||||
sadata_upcall_free(freesau);
|
||||
DPRINTFN(4,("sa_switch(%d.%d flag %x) returned.\n",
|
||||
p->p_pid, l->l_lid, l->l_flag));
|
||||
KDASSERT(l->l_wchan == 0);
|
||||
|
@ -1043,13 +1020,14 @@ sa_switchcall(void *arg)
|
|||
l2 = curlwp;
|
||||
p = l2->l_proc;
|
||||
vp = l2->l_savp;
|
||||
|
||||
if (p->p_flag & P_WEXIT)
|
||||
lwp_exit(l2);
|
||||
|
||||
KDASSERT(vp->savp_lwp == l2);
|
||||
sau = arg;
|
||||
|
||||
if (p->p_flag & P_WEXIT) {
|
||||
sadata_upcall_free(sau);
|
||||
lwp_exit(l2);
|
||||
}
|
||||
|
||||
KDASSERT(vp->savp_lwp == l2);
|
||||
DPRINTFN(6,("sa_switchcall(%d.%d)\n", p->p_pid, l2->l_lid));
|
||||
|
||||
l2->l_flag &= ~L_SA;
|
||||
|
@ -1219,7 +1197,6 @@ sa_unblock_userret(struct lwp *l)
|
|||
lwp_exit(l);
|
||||
|
||||
sau = sadata_upcall_alloc(1);
|
||||
sau->sau_arg = NULL;
|
||||
if (p->p_flag & P_WEXIT) {
|
||||
sadata_upcall_free(sau);
|
||||
lwp_exit(l);
|
||||
|
@ -1235,19 +1212,8 @@ sa_unblock_userret(struct lwp *l)
|
|||
* Defer saving the event lwp's state because a
|
||||
* PREEMPT upcall could be on the queue already.
|
||||
*/
|
||||
if (sa_upcall0(l, SA_UPCALL_UNBLOCKED | SA_UPCALL_DEFER_EVENT,
|
||||
l, l2, 0, NULL, sau) != 0) {
|
||||
/*
|
||||
* We were supposed to deliver an UNBLOCKED
|
||||
* upcall, but don't have resources to do so.
|
||||
*/
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("sa_unblock_userret: out of upcall resources"
|
||||
" for %d.%d\n", p->p_pid, l->l_lid);
|
||||
#endif
|
||||
sigexit(l, SIGABRT);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
sa_upcall0(sau, SA_UPCALL_UNBLOCKED | SA_UPCALL_DEFER_EVENT,
|
||||
l, l2, 0, NULL, NULL);
|
||||
sau->sau_stack = sast->sast_stack;
|
||||
|
||||
SCHED_LOCK(s);
|
||||
|
@ -1309,25 +1275,12 @@ sa_upcall_userret(struct lwp *l)
|
|||
p->p_pid, l->l_lid, l2->l_lid));
|
||||
|
||||
sau = sadata_upcall_alloc(1);
|
||||
sau->sau_arg = NULL;
|
||||
if (p->p_flag & P_WEXIT) {
|
||||
sadata_upcall_free(sau);
|
||||
lwp_exit(l);
|
||||
}
|
||||
|
||||
if (sa_upcall0(l, SA_UPCALL_UNBLOCKED, l2, l, 0, NULL,
|
||||
sau) != 0) {
|
||||
/*
|
||||
* We were supposed to deliver an UNBLOCKED
|
||||
* upcall, but don't have resources to do so.
|
||||
*/
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("sa_upcall_userret: out of upcall resources"
|
||||
" for %d.%d\n", p->p_pid, l->l_lid);
|
||||
#endif
|
||||
sigexit(l, SIGABRT);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
sa_upcall0(sau, SA_UPCALL_UNBLOCKED, l2, l, 0, NULL, NULL);
|
||||
sau->sau_stack = sast->sast_stack;
|
||||
|
||||
SIMPLEQ_INSERT_TAIL(&vp->savp_upcalls, sau, sau_next);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_sig.c,v 1.208 2005/07/23 22:02:13 cube Exp $ */
|
||||
/* $NetBSD: kern_sig.c,v 1.209 2005/10/02 17:51:27 chs Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.208 2005/07/23 22:02:13 cube Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.209 2005/10/02 17:51:27 chs Exp $");
|
||||
|
||||
#include "opt_ktrace.h"
|
||||
#include "opt_compat_sunos.h"
|
||||
|
@ -1388,6 +1388,20 @@ kpsignal2(struct proc *p, const ksiginfo_t *ksi, int dolock)
|
|||
SCHED_UNLOCK(s);
|
||||
}
|
||||
|
||||
siginfo_t *
|
||||
siginfo_alloc(int flags)
|
||||
{
|
||||
|
||||
return pool_get(&siginfo_pool, flags);
|
||||
}
|
||||
|
||||
void
|
||||
siginfo_free(void *arg)
|
||||
{
|
||||
|
||||
pool_put(&siginfo_pool, arg);
|
||||
}
|
||||
|
||||
void
|
||||
kpsendsig(struct lwp *l, const ksiginfo_t *ksi, const sigset_t *mask)
|
||||
{
|
||||
|
@ -1402,7 +1416,7 @@ kpsendsig(struct lwp *l, const ksiginfo_t *ksi, const sigset_t *mask)
|
|||
|
||||
f = l->l_flag & L_SA;
|
||||
l->l_flag &= ~L_SA;
|
||||
si = pool_get(&siginfo_pool, PR_WAITOK);
|
||||
si = siginfo_alloc(PR_WAITOK);
|
||||
si->_info = ksi->ksi_info;
|
||||
le = li = NULL;
|
||||
if (KSI_TRAP_P(ksi))
|
||||
|
@ -1410,8 +1424,8 @@ kpsendsig(struct lwp *l, const ksiginfo_t *ksi, const sigset_t *mask)
|
|||
else
|
||||
li = l;
|
||||
if (sa_upcall(l, SA_UPCALL_SIGNAL | SA_UPCALL_DEFER, le, li,
|
||||
sizeof(*si), si) != 0) {
|
||||
pool_put(&siginfo_pool, si);
|
||||
sizeof(*si), si, siginfo_free) != 0) {
|
||||
siginfo_free(si);
|
||||
if (KSI_TRAP_P(ksi))
|
||||
/* XXX What do we do here?? */;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_synch.c,v 1.149 2005/05/29 22:24:15 christos Exp $ */
|
||||
/* $NetBSD: kern_synch.c,v 1.150 2005/10/02 17:51:27 chs Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000, 2004 The NetBSD Foundation, Inc.
|
||||
|
@ -76,7 +76,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.149 2005/05/29 22:24:15 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.150 2005/10/02 17:51:27 chs Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_ktrace.h"
|
||||
|
@ -384,6 +384,7 @@ ltsleep(__volatile const void *ident, int priority, const char *wmesg, int timo,
|
|||
struct lwp *l = curlwp;
|
||||
struct proc *p = l ? l->l_proc : NULL;
|
||||
struct slpque *qp;
|
||||
struct sadata_upcall *sau;
|
||||
int sig, s;
|
||||
int catch = priority & PCATCH;
|
||||
int relock = (priority & PNORELOCK) == 0;
|
||||
|
@ -420,6 +421,18 @@ ltsleep(__volatile const void *ident, int priority, const char *wmesg, int timo,
|
|||
ktrcsw(p, 1, 0);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX We need to allocate the sadata_upcall structure here,
|
||||
* XXX since we can't sleep while waiting for memory inside
|
||||
* XXX sa_upcall(). It would be nice if we could safely
|
||||
* XXX allocate the sadata_upcall structure on the stack, here.
|
||||
*/
|
||||
if (l->l_flag & L_SA) {
|
||||
sau = sadata_upcall_alloc(0);
|
||||
} else {
|
||||
sau = NULL;
|
||||
}
|
||||
|
||||
SCHED_LOCK(s);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
|
@ -490,7 +503,7 @@ ltsleep(__volatile const void *ident, int priority, const char *wmesg, int timo,
|
|||
p->p_stats->p_ru.ru_nvcsw++;
|
||||
SCHED_ASSERT_LOCKED();
|
||||
if (l->l_flag & L_SA)
|
||||
sa_switch(l, SA_UPCALL_BLOCKED);
|
||||
sa_switch(l, sau, SA_UPCALL_BLOCKED);
|
||||
else
|
||||
mi_switch(l, NULL);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_time.c,v 1.93 2005/09/23 12:10:33 jmmv Exp $ */
|
||||
/* $NetBSD: kern_time.c,v 1.94 2005/10/02 17:51:27 chs Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc.
|
||||
|
@ -68,7 +68,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.93 2005/09/23 12:10:33 jmmv Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.94 2005/10/02 17:51:27 chs Exp $");
|
||||
|
||||
#include "fs_nfs.h"
|
||||
#include "opt_nfs.h"
|
||||
|
@ -102,7 +102,6 @@ __KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.93 2005/09/23 12:10:33 jmmv Exp $");
|
|||
|
||||
static void timerupcall(struct lwp *, void *);
|
||||
|
||||
|
||||
/* Time of day and interval timer support.
|
||||
*
|
||||
* These routines provide the kernel entry points to get and set
|
||||
|
@ -874,7 +873,6 @@ timerupcall(struct lwp *l, void *arg)
|
|||
{
|
||||
struct ptimers *pt = (struct ptimers *)arg;
|
||||
unsigned int i, fired, done;
|
||||
extern struct pool siginfo_pool; /* XXX Ew. */
|
||||
|
||||
KDASSERT(l->l_proc->p_sa);
|
||||
/* Bail out if we do not own the virtual processor */
|
||||
|
@ -892,11 +890,11 @@ timerupcall(struct lwp *l, void *arg)
|
|||
|
||||
f = l->l_flag & L_SA;
|
||||
l->l_flag &= ~L_SA;
|
||||
si = pool_get(&siginfo_pool, PR_WAITOK);
|
||||
si = siginfo_alloc(PR_WAITOK);
|
||||
si->_info = pt->pts_timers[i]->pt_info.ksi_info;
|
||||
if (sa_upcall(l, SA_UPCALL_SIGEV | SA_UPCALL_DEFER, NULL, l,
|
||||
sizeof(*si), si) != 0) {
|
||||
pool_put(&siginfo_pool, si);
|
||||
sizeof(*si), si, siginfo_free) != 0) {
|
||||
siginfo_free(si);
|
||||
/* XXX What do we do here?? */
|
||||
} else
|
||||
done |= mask;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: savar.h,v 1.15 2004/03/14 01:08:47 cl Exp $ */
|
||||
/* $NetBSD: savar.h,v 1.16 2005/10/02 17:51:27 chs Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -63,6 +63,7 @@ struct sadata_upcall {
|
|||
int sau_type;
|
||||
size_t sau_argsize;
|
||||
void *sau_arg;
|
||||
void (*sau_argfreefunc)(void *);
|
||||
stack_t sau_stack;
|
||||
union sau_state sau_event;
|
||||
union sau_state sau_interrupted;
|
||||
|
@ -131,10 +132,11 @@ struct sadata_upcall *sadata_upcall_alloc(int);
|
|||
void sadata_upcall_free(struct sadata_upcall *);
|
||||
|
||||
void sa_release(struct proc *);
|
||||
void sa_switch(struct lwp *, int);
|
||||
void sa_switch(struct lwp *, struct sadata_upcall *, int);
|
||||
void sa_preempt(struct lwp *);
|
||||
void sa_yield(struct lwp *);
|
||||
int sa_upcall(struct lwp *, int, struct lwp *, struct lwp *, size_t, void *);
|
||||
int sa_upcall(struct lwp *, int, struct lwp *, struct lwp *, size_t, void *,
|
||||
void (*)(void *));
|
||||
|
||||
void sa_putcachelwp(struct proc *, struct lwp *);
|
||||
struct lwp *sa_getcachelwp(struct sadata_vp *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: signalvar.h,v 1.58 2005/09/13 01:42:51 christos Exp $ */
|
||||
/* $NetBSD: signalvar.h,v 1.59 2005/10/02 17:51:27 chs Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
|
@ -177,6 +177,8 @@ void sigactsunshare(struct proc *);
|
|||
void sigactsfree(struct sigacts *);
|
||||
|
||||
void kpsendsig(struct lwp *, const struct ksiginfo *, const sigset_t *);
|
||||
siginfo_t *siginfo_alloc(int);
|
||||
void siginfo_free(void *);
|
||||
|
||||
int __sigtimedwait1(struct lwp *, void *, register_t *, copyinout_t,
|
||||
copyinout_t, copyinout_t);
|
||||
|
|
Loading…
Reference in New Issue