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
This commit is contained in:
Eric van Gyzen 2017-03-14 22:02:02 +00:00
parent 40769242ed
commit 8addc72b3e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=315287
4 changed files with 45 additions and 4 deletions

View File

@ -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 ,

View File

@ -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);

View File

@ -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, int pri, int queue)
static bool
match_any(struct thread *td __unused)
{
return (true);
}

View File

@ -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