diff --git a/sys/dev/pci/drm/drm_linux.c b/sys/dev/pci/drm/drm_linux.c index a53230091f0..ffd8ded926d 100644 --- a/sys/dev/pci/drm/drm_linux.c +++ b/sys/dev/pci/drm/drm_linux.c @@ -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 * Copyright (c) 2015, 2016 Mark Kettenis @@ -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); diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index a78cba7b6d6..686803f3317 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -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 @@ -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); diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 6b858a8c727..ae6ca786eb7 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -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); } /* diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 60aec692f8b..5476e9bc739 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -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; }; diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 4263bc19ed9..9fb40dcb26e 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -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 *);