Author: markj
Date: Thu Dec 22 17:51:44 2016
New Revision: 310423
URL: https://svnweb.freebsd.org/changeset/base/310423

Log:
  Revert part of r300109.
  
  The removal of TAILQ_FOREACH_SAFE introduced a small race: when the last
  thread on a sleepqueue is awoken, it reclaims the sleepqueue and may begin
  executing on a different CPU before sleepq_resume_thread() returns. This
  leaves a window during which it may go back to sleep and incorrectly be
  awoken again by the caller of sleepq_broadcast().
  
  Reported and tested by:       pho
  MFC after:    3 days
  Sponsored by: Dell EMC Isilon

Modified:
  head/sys/kern/subr_sleepqueue.c

Modified: head/sys/kern/subr_sleepqueue.c
==============================================================================
--- head/sys/kern/subr_sleepqueue.c     Thu Dec 22 17:44:27 2016        
(r310422)
+++ head/sys/kern/subr_sleepqueue.c     Thu Dec 22 17:51:44 2016        
(r310423)
@@ -880,7 +880,7 @@ int
 sleepq_broadcast(void *wchan, int flags, int pri, int queue)
 {
        struct sleepqueue *sq;
-       struct thread *td;
+       struct thread *td, *tdn;
        int wakeup_swapper;
 
        CTR2(KTR_PROC, "sleepq_broadcast(%p, %d)", wchan, flags);
@@ -894,7 +894,7 @@ sleepq_broadcast(void *wchan, int flags,
 
        /* Resume all blocked threads on the sleep queue. */
        wakeup_swapper = 0;
-       while ((td = TAILQ_FIRST(&sq->sq_blocked[queue])) != NULL) {
+       TAILQ_FOREACH_SAFE(td, &sq->sq_blocked[queue], td_slpq, tdn) {
                thread_lock(td);
                wakeup_swapper |= sleepq_resume_thread(sq, td, pri);
                thread_unlock(td);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to