mirror of
https://github.com/openbsd/src.git
synced 2026-04-25 06:35:46 +00:00
Move kernel locking inside the sleep machinery. This enables calling
rwsleep(9) with PCATCH and rw_enter(9) with RW_INTR without the kernel lock. In addition, now tsleep(9) with PCATCH should be safe to use without the kernel lock if the sleep is purely time-based. Tested by anton@, cheloha@, chris@ OK anton@, cheloha@
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: drm_linux.c,v 1.50 2019/10/23 10:17:40 jsg Exp $ */
|
||||
/* $OpenBSD: drm_linux.c,v 1.51 2019/11/30 11:19:17 visa Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2013 Jonathan Gray <jsg@openbsd.org>
|
||||
* Copyright (c) 2015, 2016 Mark Kettenis <kettenis@openbsd.org>
|
||||
@@ -91,7 +91,7 @@ schedule_timeout(long timeout)
|
||||
sleep_setup(&sls, sch_ident, sch_priority, "schto");
|
||||
if (timeout != MAX_SCHEDULE_TIMEOUT)
|
||||
sleep_setup_timeout(&sls, timeout);
|
||||
sleep_setup_signal(&sls, sch_priority);
|
||||
sleep_setup_signal(&sls);
|
||||
|
||||
wait = (sch_proc == curproc && timeout > 0);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kern_rwlock.c,v 1.43 2019/11/29 12:41:33 mpi Exp $ */
|
||||
/* $OpenBSD: kern_rwlock.c,v 1.44 2019/11/30 11:19:17 visa Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002, 2003 Artur Grabowski <art@openbsd.org>
|
||||
@@ -231,7 +231,7 @@ rw_enter(struct rwlock *rwl, int flags)
|
||||
*/
|
||||
unsigned int spin = (_kernel_lock_held()) ? 0 : RW_SPINS;
|
||||
#endif
|
||||
int error;
|
||||
int error, prio;
|
||||
#ifdef WITNESS
|
||||
int lop_flags;
|
||||
|
||||
@@ -273,9 +273,12 @@ retry:
|
||||
if (flags & RW_NOSLEEP)
|
||||
return (EBUSY);
|
||||
|
||||
sleep_setup(&sls, rwl, op->wait_prio, rwl->rwl_name);
|
||||
prio = op->wait_prio;
|
||||
if (flags & RW_INTR)
|
||||
sleep_setup_signal(&sls, op->wait_prio | PCATCH);
|
||||
prio |= PCATCH;
|
||||
sleep_setup(&sls, rwl, prio, rwl->rwl_name);
|
||||
if (flags & RW_INTR)
|
||||
sleep_setup_signal(&sls);
|
||||
|
||||
do_sleep = !rw_cas(&rwl->rwl_owner, o, set);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: kern_synch.c,v 1.154 2019/11/12 04:20:21 visa Exp $ */
|
||||
/* $OpenBSD: kern_synch.c,v 1.155 2019/11/30 11:19:17 visa Exp $ */
|
||||
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
|
||||
|
||||
/*
|
||||
@@ -147,7 +147,7 @@ tsleep(const volatile void *ident, int priority, const char *wmesg, int timo)
|
||||
|
||||
sleep_setup(&sls, ident, priority, wmesg);
|
||||
sleep_setup_timeout(&sls, timo);
|
||||
sleep_setup_signal(&sls, priority);
|
||||
sleep_setup_signal(&sls);
|
||||
|
||||
return sleep_finish_all(&sls, 1);
|
||||
}
|
||||
@@ -207,6 +207,9 @@ msleep(const volatile void *ident, struct mutex *mtx, int priority,
|
||||
KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0);
|
||||
KASSERT(mtx != NULL);
|
||||
|
||||
if (priority & PCATCH)
|
||||
KERNEL_ASSERT_LOCKED();
|
||||
|
||||
if (cold || panicstr) {
|
||||
/*
|
||||
* After a panic, or during autoconfiguration,
|
||||
@@ -233,7 +236,7 @@ msleep(const volatile void *ident, struct mutex *mtx, int priority,
|
||||
|
||||
sleep_setup(&sls, ident, priority, wmesg);
|
||||
sleep_setup_timeout(&sls, timo);
|
||||
sleep_setup_signal(&sls, priority);
|
||||
sleep_setup_signal(&sls);
|
||||
|
||||
/* XXX - We need to make sure that the mutex doesn't
|
||||
* unblock splsched. This can be made a bit more
|
||||
@@ -293,7 +296,7 @@ rwsleep(const volatile void *ident, struct rwlock *rwl, int priority,
|
||||
|
||||
sleep_setup(&sls, ident, priority, wmesg);
|
||||
sleep_setup_timeout(&sls, timo);
|
||||
sleep_setup_signal(&sls, priority);
|
||||
sleep_setup_signal(&sls);
|
||||
|
||||
rw_exit(rwl);
|
||||
|
||||
@@ -342,11 +345,22 @@ sleep_setup(struct sleep_state *sls, const volatile void *ident, int prio,
|
||||
panic("tsleep: not SONPROC");
|
||||
#endif
|
||||
|
||||
sls->sls_catch = 0;
|
||||
sls->sls_catch = prio & PCATCH;
|
||||
sls->sls_do_sleep = 1;
|
||||
sls->sls_locked = 0;
|
||||
sls->sls_sig = 1;
|
||||
sls->sls_timeout = 0;
|
||||
|
||||
/*
|
||||
* The kernel has to be locked for signal processing.
|
||||
* This is done here and not in sleep_setup_signal() because
|
||||
* KERNEL_LOCK() has to be taken before SCHED_LOCK().
|
||||
*/
|
||||
if (sls->sls_catch != 0) {
|
||||
KERNEL_LOCK();
|
||||
sls->sls_locked = 1;
|
||||
}
|
||||
|
||||
SCHED_LOCK(sls->sls_s);
|
||||
|
||||
p->p_wchan = ident;
|
||||
@@ -417,13 +431,16 @@ sleep_finish_timeout(struct sleep_state *sls)
|
||||
}
|
||||
|
||||
void
|
||||
sleep_setup_signal(struct sleep_state *sls, int prio)
|
||||
sleep_setup_signal(struct sleep_state *sls)
|
||||
{
|
||||
struct proc *p = curproc;
|
||||
|
||||
if ((sls->sls_catch = (prio & PCATCH)) == 0)
|
||||
if (sls->sls_catch == 0)
|
||||
return;
|
||||
|
||||
/* sleep_setup() has locked the kernel. */
|
||||
KERNEL_ASSERT_LOCKED();
|
||||
|
||||
/*
|
||||
* We put ourselves on the sleep queue and start our timeout
|
||||
* before calling CURSIG, as we could stop there, and a wakeup
|
||||
@@ -449,20 +466,26 @@ int
|
||||
sleep_finish_signal(struct sleep_state *sls)
|
||||
{
|
||||
struct proc *p = curproc;
|
||||
int error;
|
||||
int error = 0;
|
||||
|
||||
if (sls->sls_catch != 0) {
|
||||
if ((error = single_thread_check(p, 1)))
|
||||
return (error);
|
||||
if (sls->sls_sig != 0 || (sls->sls_sig = CURSIG(p)) != 0) {
|
||||
KERNEL_ASSERT_LOCKED();
|
||||
|
||||
error = single_thread_check(p, 1);
|
||||
if (error == 0 &&
|
||||
(sls->sls_sig != 0 || (sls->sls_sig = CURSIG(p)) != 0)) {
|
||||
if (p->p_p->ps_sigacts->ps_sigintr &
|
||||
sigmask(sls->sls_sig))
|
||||
return (EINTR);
|
||||
return (ERESTART);
|
||||
error = EINTR;
|
||||
else
|
||||
error = ERESTART;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
if (sls->sls_locked)
|
||||
KERNEL_UNLOCK();
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: proc.h,v 1.281 2019/11/29 21:32:04 guenther Exp $ */
|
||||
/* $OpenBSD: proc.h,v 1.282 2019/11/30 11:19:17 visa Exp $ */
|
||||
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
|
||||
|
||||
/*-
|
||||
@@ -611,6 +611,7 @@ struct sleep_state {
|
||||
int sls_s;
|
||||
int sls_catch;
|
||||
int sls_do_sleep;
|
||||
int sls_locked;
|
||||
int sls_sig;
|
||||
int sls_timeout;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: systm.h,v 1.143 2019/11/02 16:56:18 cheloha Exp $ */
|
||||
/* $OpenBSD: systm.h,v 1.144 2019/11/30 11:19:17 visa Exp $ */
|
||||
/* $NetBSD: systm.h,v 1.50 1996/06/09 04:55:09 briggs Exp $ */
|
||||
|
||||
/*-
|
||||
@@ -246,7 +246,7 @@ struct sleep_state;
|
||||
void sleep_setup(struct sleep_state *, const volatile void *, int,
|
||||
const char *);
|
||||
void sleep_setup_timeout(struct sleep_state *, int);
|
||||
void sleep_setup_signal(struct sleep_state *, int);
|
||||
void sleep_setup_signal(struct sleep_state *);
|
||||
void sleep_finish(struct sleep_state *, int);
|
||||
int sleep_finish_timeout(struct sleep_state *);
|
||||
int sleep_finish_signal(struct sleep_state *);
|
||||
|
||||
Reference in New Issue
Block a user