Date: Tue, 14 Mar 2017 22:02:02 +0000 (UTC) From: Eric van Gyzen <vangyzen@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r315287 - in head: share/man/man9 sys/kern sys/sys Message-ID: <201703142202.v2EM22O9072474@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703142202.v2EM22O9072474>