Author: vangyzen
Date: Tue Mar 14 22:02:02 2017
New Revision: 315287
URL: https://svnweb.freebsd.org/changeset/base/315287

Log:
  Add missing pieces of r315280
  
  I moved this branch from github to a private server, and pulled from the
  wrong one when committing r315280, so I failed to include two recent commits.
  Thankfully, they were only cosmetic and were included in the review.
  Specifically:
  
  Add documentation, polish comments, and improve style(9).
  
  Tested by:    pho (r315280)
  MFC after:    2 weeks
  Sponsored by: Dell EMC
  Differential Revision:        https://reviews.freebsd.org/D9791

Modified:
  head/share/man/man9/sleep.9
  head/sys/kern/kern_tc.c
  head/sys/kern/subr_sleepqueue.c
  head/sys/sys/proc.h

Modified: head/share/man/man9/sleep.9
==============================================================================
--- head/share/man/man9/sleep.9 Tue Mar 14 20:57:54 2017        (r315286)
+++ head/share/man/man9/sleep.9 Tue Mar 14 22:02:02 2017        (r315287)
@@ -280,6 +280,21 @@ to
 pay particular attention to ensure that no other threads wait on the
 same
 .Fa chan .
+.Pp
+If the timeout given by
+.Fa timo
+or
+.Fa sbt
+is based on an absolute real-time clock value,
+then the thread should copy the global
+.Va rtc_generation
+into its
+.Va td_rtcgen
+member before reading the RTC.
+If the real-time clock is adjusted, these functions will set
+.Va td_rtcgen
+to zero and return zero.
+The caller should reconsider its orientation with the new RTC value.
 .Sh RETURN VALUES
 When awakened by a call to
 .Fn wakeup
@@ -298,6 +313,9 @@ the
 .Fn msleep_spin ,
 .Fn tsleep ,
 and locking primitive sleep functions return 0.
+Zero can also be returned when the real-time clock is adjusted;
+see above regarding
+.Va td_rtcgen .
 Otherwise, a non-zero error code is returned.
 .Sh ERRORS
 .Fn msleep ,

Modified: head/sys/kern/kern_tc.c
==============================================================================
--- head/sys/kern/kern_tc.c     Tue Mar 14 20:57:54 2017        (r315286)
+++ head/sys/kern/kern_tc.c     Tue Mar 14 22:02:02 2017        (r315287)
@@ -1269,6 +1269,15 @@ static bool
 sleeping_on_old_rtc(struct thread *td)
 {
 
+       /*
+        * td_rtcgen is modified by curthread when it is running,
+        * and by other threads in this function.  By finding the thread
+        * on a sleepqueue and holding the lock on the sleepqueue
+        * chain, we guarantee that the thread is not running and that
+        * modifying td_rtcgen is safe.  Setting td_rtcgen to zero informs
+        * the thread that it was woken due to a real-time clock adjustment.
+        * (The declaration of td_rtcgen refers to this comment.)
+        */
        if (td->td_rtcgen != 0 && td->td_rtcgen != rtc_generation) {
                td->td_rtcgen = 0;
                return (true);
@@ -1299,6 +1308,7 @@ tc_setclock(struct timespec *ts)
        /* XXX fiddle all the little crinkly bits around the fiords... */
        tc_windup(&bt);
        mtx_unlock_spin(&tc_setclock_mtx);
+
        /* Avoid rtc_generation == 0, since td_rtcgen == 0 is special. */
        atomic_add_rel_int(&rtc_generation, 2);
        sleepq_chains_remove_matching(sleeping_on_old_rtc);

Modified: head/sys/kern/subr_sleepqueue.c
==============================================================================
--- head/sys/kern/subr_sleepqueue.c     Tue Mar 14 20:57:54 2017        
(r315286)
+++ head/sys/kern/subr_sleepqueue.c     Tue Mar 14 22:02:02 2017        
(r315287)
@@ -561,9 +561,21 @@ sleepq_switch(void *wchan, int pri)
        /*
         * If TDF_TIMEOUT is set, then our sleep has been timed out
         * already but we are still on the sleep queue, so dequeue the
-        * thread and return.  Do the same if the real-time clock has
-        * been adjusted since this thread calculated its timeout
-        * based on that clock.
+        * thread and return.
+        *
+        * Do the same if the real-time clock has been adjusted since this
+        * thread calculated its timeout based on that clock.  This handles
+        * the following race:
+        * - The Ts thread needs to sleep until an absolute real-clock time.
+        *   It copies the global rtc_generation into curthread->td_rtcgen,
+        *   reads the RTC, and calculates a sleep duration based on that time.
+        *   See umtxq_sleep() for an example.
+        * - The Tc thread adjusts the RTC, bumps rtc_generation, and wakes
+        *   threads that are sleeping until an absolute real-clock time.
+        *   See tc_setclock() and the POSIX specification of clock_settime().
+        * - Ts reaches the code below.  It holds the sleepqueue chain lock,
+        *   so Tc has finished waking, so this thread must test td_rtcgen.
+        * (The declaration of td_rtcgen refers to this comment.)
         */
        rtc_changed = td->td_rtcgen != 0 && td->td_rtcgen != rtc_generation;
        if ((td->td_flags & TDF_TIMEOUT) || rtc_changed) {
@@ -899,6 +911,7 @@ sleepq_signal(void *wchan, int flags, in
 static bool
 match_any(struct thread *td __unused)
 {
+
        return (true);
 }
 

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h Tue Mar 14 20:57:54 2017        (r315286)
+++ head/sys/sys/proc.h Tue Mar 14 22:02:02 2017        (r315287)
@@ -148,7 +148,7 @@ struct pargs {
  *      o - ktrace lock
  *      q - td_contested lock
  *      r - p_peers lock
- *      s - by curthread, or by others when curthread is on sleepqueue
+ *      s - see sleepq_switch(), sleeping_on_old_rtc(), and sleep(9)
  *      t - thread lock
  *     u - process stat lock
  *     w - process timer lock
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to