diff options
Diffstat (limited to 'sys/kern/kern_synch.c')
-rw-r--r-- | sys/kern/kern_synch.c | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 6777e6cb93e..ab0ada25e05 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_synch.c,v 1.36 2001/06/27 04:49:45 art Exp $ */ +/* $OpenBSD: kern_synch.c,v 1.37 2001/08/07 22:57:15 art Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /*- @@ -336,17 +336,24 @@ int safepri; * signal needs to be delivered, ERESTART is returned if the current system * call should be restarted if possible, and EINTR is returned if the system * call should be interrupted by the signal (return EINTR). + * + * The interlock is held until the scheduler_slock (XXX) is held. The + * interlock will be locked before returning back to the caller + * unless the PNORELOCK flag is specified, in which case the + * interlock will always be unlocked upon return. */ int -tsleep(ident, priority, wmesg, timo) +ltsleep(ident, priority, wmesg, timo, interlock) void *ident; int priority, timo; char *wmesg; + volatile struct simplelock *interlock; { - register struct proc *p = curproc; - register struct slpque *qp; - register int s; - int sig, catch = priority & PCATCH; + struct proc *p = curproc; + struct slpque *qp; + int s, sig; + int catch = priority & PCATCH; + int relock = (priority & PNORELOCK) == 0; #ifdef KTRACE if (KTRPOINT(p, KTR_CSW)) @@ -362,6 +369,8 @@ tsleep(ident, priority, wmesg, timo) */ splx(safepri); splx(s); + if (interlock != NULL && relock == 0) + simple_unlock(interlock); return (0); } #ifdef DIAGNOSTIC @@ -381,6 +390,18 @@ tsleep(ident, priority, wmesg, timo) if (timo) timeout_add(&p->p_sleep_to, timo); /* + * We can now release the interlock; the scheduler_slock + * is held, so a thread can't get in to do wakeup() before + * we do the switch. + * + * XXX We leave the code block here, after inserting ourselves + * on the sleep queue, because we might want a more clever + * data structure for the sleep queues at some point. + */ + if (interlock != NULL) + simple_unlock(interlock); + + /* * We put ourselves on the sleep queue and start our timeout * before calling CURSIG, as we could stop there, and a wakeup * or a SIGCONT (or both) could occur while we were stopped. @@ -421,6 +442,8 @@ resume: if (KTRPOINT(p, KTR_CSW)) ktrcsw(p, 0, 0); #endif + if (interlock != NULL && relock) + simple_lock(interlock); return (EWOULDBLOCK); } } else if (timo) @@ -430,6 +453,8 @@ resume: if (KTRPOINT(p, KTR_CSW)) ktrcsw(p, 0, 0); #endif + if (interlock != NULL && relock) + simple_lock(interlock); if (p->p_sigacts->ps_sigintr & sigmask(sig)) return (EINTR); return (ERESTART); @@ -438,6 +463,8 @@ resume: if (KTRPOINT(p, KTR_CSW)) ktrcsw(p, 0, 0); #endif + if (interlock != NULL && relock) + simple_lock(interlock); return (0); } |