From owner-svn-src-all@freebsd.org Sun Dec 15 21:18:08 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 312741CF8D2; Sun, 15 Dec 2019 21:18:08 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 47bch00ZyXz3yNh; Sun, 15 Dec 2019 21:18:08 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 0F4DD1B0B1; Sun, 15 Dec 2019 21:18:08 +0000 (UTC) (envelope-from jeff@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xBFLI7sF031614; Sun, 15 Dec 2019 21:18:07 GMT (envelope-from jeff@FreeBSD.org) Received: (from jeff@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xBFLI72d031613; Sun, 15 Dec 2019 21:18:07 GMT (envelope-from jeff@FreeBSD.org) Message-Id: <201912152118.xBFLI72d031613@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jeff set sender to jeff@FreeBSD.org using -f From: Jeff Roberson Date: Sun, 15 Dec 2019 21:18:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r355781 - in head/sys: kern sys X-SVN-Group: head X-SVN-Commit-Author: jeff X-SVN-Commit-Paths: in head/sys: kern sys X-SVN-Commit-Revision: 355781 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 15 Dec 2019 21:18:08 -0000 Author: jeff Date: Sun Dec 15 21:18:07 2019 New Revision: 355781 URL: https://svnweb.freebsd.org/changeset/base/355781 Log: schedlock 2/4 Do all sleepqueue post-processing in sleepq_remove_thread() so that we do not require the thread lock after a context switch. Reviewed by: jhb, kib Differential Revision: https://reviews.freebsd.org/D22745 Modified: head/sys/kern/subr_sleepqueue.c head/sys/sys/proc.h Modified: head/sys/kern/subr_sleepqueue.c ============================================================================== --- head/sys/kern/subr_sleepqueue.c Sun Dec 15 21:16:35 2019 (r355780) +++ head/sys/kern/subr_sleepqueue.c Sun Dec 15 21:18:07 2019 (r355781) @@ -164,8 +164,8 @@ static uma_zone_t sleepq_zone; * Prototypes for non-exported routines. */ static int sleepq_catch_signals(void *wchan, int pri); -static int sleepq_check_signals(void); -static int sleepq_check_timeout(void); +static inline int sleepq_check_signals(void); +static inline int sleepq_check_timeout(void); #ifdef INVARIANTS static void sleepq_dtor(void *mem, int size, void *arg); #endif @@ -378,9 +378,10 @@ sleepq_add(void *wchan, struct lock_object *lock, cons td->td_wchan = wchan; td->td_wmesg = wmesg; if (flags & SLEEPQ_INTERRUPTIBLE) { + td->td_intrval = 0; td->td_flags |= TDF_SINTR; - td->td_flags &= ~TDF_SLEEPABORT; } + td->td_flags &= ~TDF_TIMEOUT; thread_unlock(td); } @@ -624,63 +625,35 @@ sleepq_switch(void *wchan, int pri) /* * Check to see if we timed out. */ -static int +static inline int sleepq_check_timeout(void) { struct thread *td; int res; - td = curthread; - THREAD_LOCK_ASSERT(td, MA_OWNED); - - /* - * If TDF_TIMEOUT is set, we timed out. But recheck - * td_sleeptimo anyway. - */ res = 0; + td = curthread; if (td->td_sleeptimo != 0) { if (td->td_sleeptimo <= sbinuptime()) res = EWOULDBLOCK; td->td_sleeptimo = 0; } - if (td->td_flags & TDF_TIMEOUT) - td->td_flags &= ~TDF_TIMEOUT; - else - /* - * We ignore the situation where timeout subsystem was - * unable to stop our callout. The struct thread is - * type-stable, the callout will use the correct - * memory when running. The checks of the - * td_sleeptimo value in this function and in - * sleepq_timeout() ensure that the thread does not - * get spurious wakeups, even if the callout was reset - * or thread reused. - */ - callout_stop(&td->td_slpcallout); return (res); } /* * Check to see if we were awoken by a signal. */ -static int +static inline int sleepq_check_signals(void) { struct thread *td; td = curthread; - THREAD_LOCK_ASSERT(td, MA_OWNED); + KASSERT((td->td_flags & TDF_SINTR) == 0, + ("thread %p still in interruptible sleep?", td)); - /* We are no longer in an interruptible sleep. */ - if (td->td_flags & TDF_SINTR) - td->td_flags &= ~TDF_SINTR; - - if (td->td_flags & TDF_SLEEPABORT) { - td->td_flags &= ~TDF_SLEEPABORT; - return (td->td_intrval); - } - - return (0); + return (td->td_intrval); } /* @@ -706,14 +679,12 @@ int sleepq_wait_sig(void *wchan, int pri) { int rcatch; - int rval; rcatch = sleepq_catch_signals(wchan, pri); - rval = sleepq_check_signals(); thread_unlock(curthread); if (rcatch) return (rcatch); - return (rval); + return (sleepq_check_signals()); } /* @@ -724,16 +695,14 @@ int sleepq_timedwait(void *wchan, int pri) { struct thread *td; - int rval; td = curthread; MPASS(!(td->td_flags & TDF_SINTR)); thread_lock(td); sleepq_switch(wchan, pri); - rval = sleepq_check_timeout(); thread_unlock(td); - return (rval); + return (sleepq_check_timeout()); } /* @@ -746,9 +715,11 @@ sleepq_timedwait_sig(void *wchan, int pri) int rcatch, rvalt, rvals; rcatch = sleepq_catch_signals(wchan, pri); + thread_unlock(curthread); + + /* We must always call check_timeout() to clear sleeptimo. */ rvalt = sleepq_check_timeout(); rvals = sleepq_check_signals(); - thread_unlock(curthread); if (rcatch) return (rcatch); if (rvals) @@ -877,9 +848,22 @@ sleepq_remove_thread(struct sleepqueue *sq, struct thr td->td_sleepqueue = LIST_FIRST(&sq->sq_free); LIST_REMOVE(td->td_sleepqueue, sq_hash); + if ((td->td_flags & TDF_TIMEOUT) == 0 && td->td_sleeptimo != 0) + /* + * We ignore the situation where timeout subsystem was + * unable to stop our callout. The struct thread is + * type-stable, the callout will use the correct + * memory when running. The checks of the + * td_sleeptimo value in this function and in + * sleepq_timeout() ensure that the thread does not + * get spurious wakeups, even if the callout was reset + * or thread reused. + */ + callout_stop(&td->td_slpcallout); + td->td_wmesg = NULL; td->td_wchan = NULL; - td->td_flags &= ~TDF_SINTR; + td->td_flags &= ~(TDF_SINTR | TDF_TIMEOUT); CTR3(KTR_PROC, "sleepq_wakeup: thread %p (pid %ld, %s)", (void *)td, (long)td->td_proc->p_pid, td->td_name); @@ -1047,7 +1031,7 @@ sleepq_timeout(void *arg) (void *)td, (long)td->td_proc->p_pid, (void *)td->td_name); thread_lock(td); - if (td->td_sleeptimo > sbinuptime() || td->td_sleeptimo == 0) { + if (td->td_sleeptimo == 0 || td->td_sleeptimo > sbinuptime()) { /* * The thread does not want a timeout (yet). */ @@ -1146,7 +1130,6 @@ sleepq_abort(struct thread *td, int intrval) CTR3(KTR_PROC, "sleepq_abort: thread %p (pid %ld, %s)", (void *)td, (long)td->td_proc->p_pid, (void *)td->td_name); td->td_intrval = intrval; - td->td_flags |= TDF_SLEEPABORT; /* * If the thread has not slept yet it will find the signal in Modified: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Sun Dec 15 21:16:35 2019 (r355780) +++ head/sys/sys/proc.h Sun Dec 15 21:18:07 2019 (r355781) @@ -431,7 +431,7 @@ do { \ #define TDF_TIMEOUT 0x00000010 /* Timing out during sleep. */ #define TDF_IDLETD 0x00000020 /* This is a per-CPU idle thread. */ #define TDF_CANSWAP 0x00000040 /* Thread can be swapped. */ -#define TDF_SLEEPABORT 0x00000080 /* sleepq_abort was called. */ +#define TDF_UNUSED80 0x00000080 /* unused. */ #define TDF_KTH_SUSP 0x00000100 /* kthread is suspended */ #define TDF_ALLPROCSUSP 0x00000200 /* suspended by SINGLE_ALLPROC */ #define TDF_BOUNDARY 0x00000400 /* Thread suspended at user boundary */