diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2007-11-28 20:07:37 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2007-11-28 20:07:37 +0000 |
commit | 4e3a26930218d35cf08d85d517f7552adc8cb07d (patch) | |
tree | 72237720995754cbad9146bec88dd420c5cd1819 /sys | |
parent | 7ce0ae885ba1db57d76d6bfa9ed38e8718b9fe99 (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@.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_synch.c | 39 | ||||
-rw-r--r-- | sys/sys/proc.h | 4 |
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) |