Author: badger
Date: Mon Aug 15 20:09:09 2016
New Revision: 304184
URL: https://svnweb.freebsd.org/changeset/base/304184

Log:
  sem_post(): wake up the sleeper only after adjusting has_waiters
  
  If the caller of sem_post() wakes up a thread sleeping via sem_wait()
  before it clears the has_waiters flag, the caller of sem_wait() has no way of
  knowing when it is safe to destroy the semaphore and reuse the memory. This is
  because the caller of sem_post() may be interrupted between the wake step and
  the clearing of has_waiters. It will then write into the has_waiters flag in
  userspace after being preempted for some unknown amount of time.
  
  Reviewed by:  jhb, kib, vangyzen
  Approved by:  kib (mentor), vangyzen (mentor)
  MFC after:    2 weeks
  Sponsored by: Dell Inc.
  Differential Revision:        https://reviews.freebsd.org/D7505

Modified:
  head/sys/kern/kern_umtx.c

Modified: head/sys/kern/kern_umtx.c
==============================================================================
--- head/sys/kern/kern_umtx.c   Mon Aug 15 19:47:04 2016        (r304183)
+++ head/sys/kern/kern_umtx.c   Mon Aug 15 20:09:09 2016        (r304184)
@@ -3123,7 +3123,6 @@ do_sem_wake(struct thread *td, struct _u
        umtxq_busy(&key);
        cnt = umtxq_count(&key);
        if (cnt > 0) {
-               umtxq_signal(&key, 1);
                /*
                 * Check if count is greater than 0, this means the memory is
                 * still being referenced by user code, so we can safely
@@ -3136,6 +3135,7 @@ do_sem_wake(struct thread *td, struct _u
                        if (error == -1)
                                error = EFAULT;
                }
+               umtxq_signal(&key, 1);
        }
        umtxq_unbusy(&key);
        umtxq_unlock(&key);
@@ -3235,8 +3235,6 @@ do_sem2_wake(struct thread *td, struct _
        umtxq_busy(&key);
        cnt = umtxq_count(&key);
        if (cnt > 0) {
-               umtxq_signal(&key, 1);
-
                /*
                 * If this was the last sleeping thread, clear the waiters
                 * flag in _count.
@@ -3251,6 +3249,8 @@ do_sem2_wake(struct thread *td, struct _
                                error = EFAULT;
                        umtxq_lock(&key);
                }
+
+               umtxq_signal(&key, 1);
        }
        umtxq_unbusy(&key);
        umtxq_unlock(&key);
_______________________________________________
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