summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwain Ainsworth <oga@cvs.openbsd.org>2007-11-28 20:07:37 +0000
committerOwain Ainsworth <oga@cvs.openbsd.org>2007-11-28 20:07:37 +0000
commit4e3a26930218d35cf08d85d517f7552adc8cb07d (patch)
tree72237720995754cbad9146bec88dd420c5cd1819
parent7ce0ae885ba1db57d76d6bfa9ed38e8718b9fe99 (diff)
Add msleep. This is identical to tsleep but it takes a mutex as a
parameter. The mutex is unlocked just before sleep and relocked after unless P_NORELOCK is in flags, in which case it is left unlocked. ok art@.
-rw-r--r--sys/kern/kern_synch.c39
-rw-r--r--sys/sys/proc.h4
2 files changed, 41 insertions, 2 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 8cd4a4285e1..209883c59b4 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_synch.c,v 1.81 2007/10/10 15:53:53 art Exp $ */
+/* $OpenBSD: kern_synch.c,v 1.82 2007/11/28 20:07:36 oga Exp $ */
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
/*
@@ -136,6 +136,43 @@ tsleep(void *ident, int priority, const char *wmesg, int timo)
return (error);
}
+/*
+ * Same as tsleep, but if we have a mutex provided, then once we've
+ * entered the sleep queue we drop the mutex. After sleeping we re-lock.
+ */
+int
+msleep(void *ident, struct mutex *mtx, int priority, const char *wmesg, int timo)
+{
+ struct sleep_state sls;
+ int error, error1;
+
+ sleep_setup(&sls, ident, priority, wmesg);
+ sleep_setup_timeout(&sls, timo);
+ sleep_setup_signal(&sls, priority);
+
+ if (mtx) {
+ /* XXX - We need to make sure that the mutex doesn't
+ * unblock splsched. This can be made a bit more
+ * correct when the sched_lock is a mutex.
+ */
+ MUTEX_OLDIPL(mtx) = splsched();
+ mtx_leave(mtx);
+ }
+
+ sleep_finish(&sls, 1);
+ error1 = sleep_finish_timeout(&sls);
+ error = sleep_finish_signal(&sls);
+
+ if (mtx && (priority & PNORELOCK) == 0)
+ mtx_enter(mtx);
+
+ /* Signal errors are higher priority than timeouts. */
+ if (error == 0 && error1 != 0)
+ error = error1;
+
+ return (error);
+}
+
void
sleep_setup(struct sleep_state *sls, void *ident, int prio, const char *wmesg)
{
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index a4d4a12fa62..29389bb5e6a 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.101 2007/10/10 15:53:53 art Exp $ */
+/* $OpenBSD: proc.h,v 1.102 2007/11/28 20:07:36 oga Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -45,6 +45,7 @@
#include <sys/queue.h>
#include <sys/timeout.h> /* For struct timeout. */
#include <sys/event.h> /* For struct klist */
+#include <sys/mutex.h> /* For struct mutex */
#include <machine/atomic.h>
#define curproc curcpu()->ci_curproc
@@ -454,6 +455,7 @@ int sleep_finish_signal(struct sleep_state *);
void sleep_queue_init(void);
int tsleep(void *, int, const char *, int);
+int msleep(void *, struct mutex *, int, const char*, int);
#define ltsleep(c, p, w, t, l) tsleep(c, p, w, t)
#if defined(MULTIPROCESSOR)