From 46a9878a41aaad00dfd01a8fe77c3ee86d73b7be Mon Sep 17 00:00:00 2001 From: ad Date: Sun, 19 Apr 2020 20:35:29 +0000 Subject: [PATCH] Set LW_SINTR earlier so it doesn't pose a problem for doing interruptable waits with turnstiles (not currently done). --- sys/kern/kern_condvar.c | 16 ++++++++-------- sys/kern/kern_sleepq.c | 23 +++++++++++++++-------- sys/kern/kern_synch.c | 18 +++++++++++------- sys/kern/kern_timeout.c | 6 +++--- sys/kern/kern_turnstile.c | 6 +++--- sys/kern/sys_lwp.c | 6 +++--- sys/kern/sys_select.c | 6 +++--- sys/sys/sleepq.h | 5 +++-- 8 files changed, 49 insertions(+), 37 deletions(-) diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index 2d26fbd51c2c..1dbeef94e3f4 100644 --- a/sys/kern/kern_condvar.c +++ b/sys/kern/kern_condvar.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_condvar.c,v 1.46 2020/04/13 15:54:45 maxv Exp $ */ +/* $NetBSD: kern_condvar.c,v 1.47 2020/04/19 20:35:29 ad Exp $ */ /*- * Copyright (c) 2006, 2007, 2008, 2019, 2020 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_condvar.c,v 1.46 2020/04/13 15:54:45 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_condvar.c,v 1.47 2020/04/19 20:35:29 ad Exp $"); #include #include @@ -116,7 +116,7 @@ cv_destroy(kcondvar_t *cv) * condition variable, and increment the number of waiters. */ static inline void -cv_enter(kcondvar_t *cv, kmutex_t *mtx, lwp_t *l) +cv_enter(kcondvar_t *cv, kmutex_t *mtx, lwp_t *l, bool catch_p) { sleepq_t *sq; kmutex_t *mp; @@ -129,7 +129,7 @@ cv_enter(kcondvar_t *cv, kmutex_t *mtx, lwp_t *l) mp = sleepq_hashlock(cv); sq = CV_SLEEPQ(cv); sleepq_enter(sq, l, mp); - sleepq_enqueue(sq, cv, CV_WMESG(cv), &cv_syncobj); + sleepq_enqueue(sq, cv, CV_WMESG(cv), &cv_syncobj, catch_p); mutex_exit(mtx); KASSERT(cv_has_waiters(cv)); } @@ -169,7 +169,7 @@ cv_wait(kcondvar_t *cv, kmutex_t *mtx) KASSERT(mutex_owned(mtx)); - cv_enter(cv, mtx, l); + cv_enter(cv, mtx, l, false); (void)sleepq_block(0, false); mutex_enter(mtx); } @@ -190,7 +190,7 @@ cv_wait_sig(kcondvar_t *cv, kmutex_t *mtx) KASSERT(mutex_owned(mtx)); - cv_enter(cv, mtx, l); + cv_enter(cv, mtx, l, true); error = sleepq_block(0, true); mutex_enter(mtx); return error; @@ -213,7 +213,7 @@ cv_timedwait(kcondvar_t *cv, kmutex_t *mtx, int timo) KASSERT(mutex_owned(mtx)); - cv_enter(cv, mtx, l); + cv_enter(cv, mtx, l, false); error = sleepq_block(timo, false); mutex_enter(mtx); return error; @@ -238,7 +238,7 @@ cv_timedwait_sig(kcondvar_t *cv, kmutex_t *mtx, int timo) KASSERT(mutex_owned(mtx)); - cv_enter(cv, mtx, l); + cv_enter(cv, mtx, l, true); error = sleepq_block(timo, true); mutex_enter(mtx); return error; diff --git a/sys/kern/kern_sleepq.c b/sys/kern/kern_sleepq.c index c8b14c895864..1e611bdc96ee 100644 --- a/sys/kern/kern_sleepq.c +++ b/sys/kern/kern_sleepq.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_sleepq.c,v 1.65 2020/04/13 15:54:45 maxv Exp $ */ +/* $NetBSD: kern_sleepq.c,v 1.66 2020/04/19 20:35:29 ad Exp $ */ /*- * Copyright (c) 2006, 2007, 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_sleepq.c,v 1.65 2020/04/13 15:54:45 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sleepq.c,v 1.66 2020/04/19 20:35:29 ad Exp $"); #include #include @@ -210,13 +210,15 @@ sleepq_insert(sleepq_t *sq, lwp_t *l, syncobj_t *sobj) * lock) must have be released (see sleeptab_lookup(), sleepq_enter()). */ void -sleepq_enqueue(sleepq_t *sq, wchan_t wchan, const char *wmesg, syncobj_t *sobj) +sleepq_enqueue(sleepq_t *sq, wchan_t wchan, const char *wmesg, syncobj_t *sobj, + bool catch_p) { lwp_t *l = curlwp; KASSERT(lwp_locked(l, NULL)); KASSERT(l->l_stat == LSONPROC); KASSERT(l->l_wchan == NULL && l->l_sleepq == NULL); + KASSERT((l->l_flag & LW_SINTR) == 0); l->l_syncobj = sobj; l->l_wchan = wchan; @@ -224,6 +226,8 @@ sleepq_enqueue(sleepq_t *sq, wchan_t wchan, const char *wmesg, syncobj_t *sobj) l->l_wmesg = wmesg; l->l_slptime = 0; l->l_stat = LSSLEEP; + if (catch_p) + l->l_flag |= LW_SINTR; sleepq_insert(sq, l, sobj); @@ -254,13 +258,9 @@ sleepq_block(int timo, bool catch_p) /* * If sleeping interruptably, check for pending signals, exits or - * core dump events. XXX The set of LW_SINTR here assumes no unlock - * between sleepq_enqueue() and sleepq_block(). Unlock between - * those only happens with turnstiles, which never set catch_p. - * Ugly but safe. + * core dump events. */ if (catch_p) { - l->l_flag |= LW_SINTR; if ((l->l_flag & (LW_CANCELLED|LW_WEXIT|LW_WCORE)) != 0) { l->l_flag &= ~LW_CANCELLED; error = EINTR; @@ -273,6 +273,13 @@ sleepq_block(int timo, bool catch_p) /* lwp_unsleep() will release the lock */ lwp_unsleep(l, true); } else { + /* + * The LWP may have already been awoken if the caller + * dropped the sleep queue lock between sleepq_enqueue() and + * sleepq_block(). If that happends l_stat will be LSONPROC + * and mi_switch() will treat this as a preemption. No need + * to do anything special here. + */ if (timo) { l->l_flag &= ~LW_STIMO; callout_schedule(&l->l_timeout_ch, timo); diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 2b51fc55af59..cc3ed62b0047 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_synch.c,v 1.346 2020/04/04 20:21:53 ad Exp $ */ +/* $NetBSD: kern_synch.c,v 1.347 2020/04/19 20:35:29 ad Exp $ */ /*- * Copyright (c) 1999, 2000, 2004, 2006, 2007, 2008, 2009, 2019, 2020 @@ -69,7 +69,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.346 2020/04/04 20:21:53 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_synch.c,v 1.347 2020/04/19 20:35:29 ad Exp $"); #include "opt_kstack.h" #include "opt_dtrace.h" @@ -173,6 +173,7 @@ tsleep(wchan_t ident, pri_t priority, const char *wmesg, int timo) struct lwp *l = curlwp; sleepq_t *sq; kmutex_t *mp; + bool catch_p; KASSERT((l->l_pflag & LP_INTR) == 0); KASSERT(ident != &lbolt); @@ -183,10 +184,11 @@ tsleep(wchan_t ident, pri_t priority, const char *wmesg, int timo) } l->l_kpriority = true; + catch_p = priority & PCATCH; sq = sleeptab_lookup(&sleeptab, ident, &mp); sleepq_enter(sq, l, mp); - sleepq_enqueue(sq, ident, wmesg, &sleep_syncobj); - return sleepq_block(timo, priority & PCATCH); + sleepq_enqueue(sq, ident, wmesg, &sleep_syncobj, catch_p); + return sleepq_block(timo, catch_p); } int @@ -196,6 +198,7 @@ mtsleep(wchan_t ident, pri_t priority, const char *wmesg, int timo, struct lwp *l = curlwp; sleepq_t *sq; kmutex_t *mp; + bool catch_p; int error; KASSERT((l->l_pflag & LP_INTR) == 0); @@ -207,11 +210,12 @@ mtsleep(wchan_t ident, pri_t priority, const char *wmesg, int timo, } l->l_kpriority = true; + catch_p = priority & PCATCH; sq = sleeptab_lookup(&sleeptab, ident, &mp); sleepq_enter(sq, l, mp); - sleepq_enqueue(sq, ident, wmesg, &sleep_syncobj); + sleepq_enqueue(sq, ident, wmesg, &sleep_syncobj, catch_p); mutex_exit(mtx); - error = sleepq_block(timo, priority & PCATCH); + error = sleepq_block(timo, catch_p); if ((priority & PNORELOCK) == 0) mutex_enter(mtx); @@ -238,7 +242,7 @@ kpause(const char *wmesg, bool intr, int timo, kmutex_t *mtx) l->l_kpriority = true; lwp_lock(l); KERNEL_UNLOCK_ALL(NULL, &l->l_biglocks); - sleepq_enqueue(NULL, l, wmesg, &kpause_syncobj); + sleepq_enqueue(NULL, l, wmesg, &kpause_syncobj, intr); error = sleepq_block(timo, intr); if (mtx != NULL) mutex_enter(mtx); diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index c9d25a66edd6..52474e61ced5 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_timeout.c,v 1.60 2020/04/13 15:54:45 maxv Exp $ */ +/* $NetBSD: kern_timeout.c,v 1.61 2020/04/19 20:35:29 ad Exp $ */ /*- * Copyright (c) 2003, 2006, 2007, 2008, 2009, 2019 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_timeout.c,v 1.60 2020/04/13 15:54:45 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_timeout.c,v 1.61 2020/04/19 20:35:29 ad Exp $"); /* * Timeouts are kept in a hierarchical timing wheel. The c_time is the @@ -539,7 +539,7 @@ callout_wait(callout_impl_t *c, void *interlock, kmutex_t *lock) l->l_kpriority = true; sleepq_enter(&cc->cc_sleepq, l, cc->cc_lock); sleepq_enqueue(&cc->cc_sleepq, cc, "callout", - &sleep_syncobj); + &sleep_syncobj, false); sleepq_block(0, false); } diff --git a/sys/kern/kern_turnstile.c b/sys/kern/kern_turnstile.c index d05372d50739..aa7c941c1576 100644 --- a/sys/kern/kern_turnstile.c +++ b/sys/kern/kern_turnstile.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_turnstile.c,v 1.38 2020/03/26 22:43:19 ad Exp $ */ +/* $NetBSD: kern_turnstile.c,v 1.39 2020/04/19 20:35:29 ad Exp $ */ /*- * Copyright (c) 2002, 2006, 2007, 2009, 2019, 2020 @@ -61,7 +61,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.38 2020/03/26 22:43:19 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_turnstile.c,v 1.39 2020/04/19 20:35:29 ad Exp $"); #include #include @@ -429,7 +429,7 @@ turnstile_block(turnstile_t *ts, int q, wchan_t obj, syncobj_t *sobj) obase = l->l_kpribase; if (obase < PRI_KTHREAD) l->l_kpribase = PRI_KTHREAD; - sleepq_enqueue(sq, obj, "tstile", sobj); + sleepq_enqueue(sq, obj, "tstile", sobj, false); /* * Disable preemption across this entire block, as we may drop diff --git a/sys/kern/sys_lwp.c b/sys/kern/sys_lwp.c index 63debd03280c..91ac25f7b1d5 100644 --- a/sys/kern/sys_lwp.c +++ b/sys/kern/sys_lwp.c @@ -1,4 +1,4 @@ -/* $NetBSD: sys_lwp.c,v 1.76 2020/04/04 20:20:12 thorpej Exp $ */ +/* $NetBSD: sys_lwp.c,v 1.77 2020/04/19 20:35:29 ad Exp $ */ /*- * Copyright (c) 2001, 2006, 2007, 2008, 2019, 2020 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.76 2020/04/04 20:20:12 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.77 2020/04/19 20:35:29 ad Exp $"); #include #include @@ -542,7 +542,7 @@ lwp_park(clockid_t clock_id, int flags, struct timespec *ts) return EALREADY; } l->l_biglocks = 0; - sleepq_enqueue(NULL, l, "parked", &lwp_park_syncobj); + sleepq_enqueue(NULL, l, "parked", &lwp_park_syncobj, true); error = sleepq_block(timo, true); switch (error) { case EWOULDBLOCK: diff --git a/sys/kern/sys_select.c b/sys/kern/sys_select.c index fcacd6253a52..b6bf5934761f 100644 --- a/sys/kern/sys_select.c +++ b/sys/kern/sys_select.c @@ -1,4 +1,4 @@ -/* $NetBSD: sys_select.c,v 1.53 2020/03/26 19:46:42 ad Exp $ */ +/* $NetBSD: sys_select.c,v 1.54 2020/04/19 20:35:29 ad Exp $ */ /*- * Copyright (c) 2007, 2008, 2009, 2010, 2019, 2020 The NetBSD Foundation, Inc. @@ -84,7 +84,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.53 2020/03/26 19:46:42 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_select.c,v 1.54 2020/04/19 20:35:29 ad Exp $"); #include #include @@ -321,7 +321,7 @@ state_check: l->l_selflag = SEL_BLOCKING; l->l_kpriority = true; sleepq_enter(&sc->sc_sleepq, l, lock); - sleepq_enqueue(&sc->sc_sleepq, sc, opname, &select_sobj); + sleepq_enqueue(&sc->sc_sleepq, sc, opname, &select_sobj, true); error = sleepq_block(timo, true); if (error != 0) { break; diff --git a/sys/sys/sleepq.h b/sys/sys/sleepq.h index bf310164a1a7..1fcbe68905ea 100644 --- a/sys/sys/sleepq.h +++ b/sys/sys/sleepq.h @@ -1,4 +1,4 @@ -/* $NetBSD: sleepq.h,v 1.28 2020/03/26 19:46:42 ad Exp $ */ +/* $NetBSD: sleepq.h,v 1.29 2020/04/19 20:35:29 ad Exp $ */ /*- * Copyright (c) 2002, 2006, 2007, 2008, 2009, 2019, 2020 @@ -60,7 +60,8 @@ typedef struct sleeptab { void sleepq_init(sleepq_t *); void sleepq_remove(sleepq_t *, lwp_t *); -void sleepq_enqueue(sleepq_t *, wchan_t, const char *, struct syncobj *); +void sleepq_enqueue(sleepq_t *, wchan_t, const char *, struct syncobj *, + bool); void sleepq_unsleep(lwp_t *, bool); void sleepq_timeout(void *); void sleepq_wake(sleepq_t *, wchan_t, u_int, kmutex_t *);