svn commit: r355781 - in head/sys: kern sys

Jeff Roberson jeff at FreeBSD.org
Sun Dec 15 21:18:08 UTC 2019


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 */


More information about the svn-src-all mailing list