summaryrefslogtreecommitdiff
path: root/sys/kern/kern_synch.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_synch.c')
-rw-r--r--sys/kern/kern_synch.c39
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);
}