[rtems commit] timecounter: Merge FreeBSD change r315280

Sebastian Huber sebh at rtems.org
Thu Oct 12 05:09:49 UTC 2017


Module:    rtems
Branch:    master
Commit:    952b42b643d66fbc88d45d51e4572102c9c00ba9
Changeset: http://git.rtems.org/rtems/commit/?id=952b42b643d66fbc88d45d51e4572102c9c00ba9

Author:    Eric van Gyzen <vangyzen at FreeBSD.org>
Date:      Tue Mar 14 19:06:44 2017 +0000

timecounter: Merge FreeBSD change r315280

When the RTC is adjusted, reevaluate absolute sleep times based on the RTC

POSIX 2008 says this about clock_settime(2):

    If the value of the CLOCK_REALTIME clock is set via clock_settime(),
    the new value of the clock shall be used to determine the time
    of expiration for absolute time services based upon the
    CLOCK_REALTIME clock.  This applies to the time at which armed
    absolute timers expire.  If the absolute time requested at the
    invocation of such a time service is before the new value of
    the clock, the time service shall expire immediately as if the
    clock had reached the requested time normally.

    Setting the value of the CLOCK_REALTIME clock via clock_settime()
    shall have no effect on threads that are blocked waiting for
    a relative time service based upon this clock, including the
    nanosleep() function; nor on the expiration of relative timers
    based upon this clock.  Consequently, these time services shall
    expire when the requested relative interval elapses, independently
    of the new or old value of the clock.

When the real-time clock is adjusted, such as by clock_settime(3),
wake any threads sleeping until an absolute real-clock time.
Such a sleep is indicated by a non-zero td_rtcgen.  The sleep functions
will set that field to zero and return zero to tell the caller
to reevaluate its sleep duration based on the new value of the clock.

At present, this affects the following functions:

    pthread_cond_timedwait(3)
    pthread_mutex_timedlock(3)
    pthread_rwlock_timedrdlock(3)
    pthread_rwlock_timedwrlock(3)
    sem_timedwait(3)
    sem_clockwait_np(3)

I'm working on adding clock_nanosleep(2), which will also be affected.

Reported by:	Sebastian Huber <sebastian.huber at embedded-brains.de>
Reviewed by:	jhb, kib
MFC after:	2 weeks
Relnotes:	yes
Sponsored by:	Dell EMC
Differential Revision:	https://reviews.freebsd.org/D9791

Update #3175.

---

 cpukit/score/src/kern_tc.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index 2810fd8..81c2131 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -56,7 +56,9 @@ __FBSDID("$FreeBSD r284178 2015-06-09T11:49:56Z$");
 #include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
+#include <sys/proc.h>
 #include <sys/sbuf.h>
+#include <sys/sleepqueue.h>
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/systm.h>
@@ -232,6 +234,8 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, alloweddeviation,
     sysctl_kern_timecounter_adjprecision, "I",
     "Allowed time interval deviation in percents");
 
+volatile int rtc_generation = 1;
+
 static int tc_chosen;	/* Non-zero if a specific tc was chosen via sysctl. */
 #endif /* __rtems__ */
 
@@ -1410,6 +1414,17 @@ tc_getfrequency(void)
 	return (timehands->th_counter->tc_frequency);
 }
 
+static bool
+sleeping_on_old_rtc(struct thread *td)
+{
+
+	if (td->td_rtcgen != 0 && td->td_rtcgen != rtc_generation) {
+		td->td_rtcgen = 0;
+		return (true);
+	}
+	return (false);
+}
+
 static struct mtx tc_setclock_mtx;
 MTX_SYSINIT(tc_setclock_init, &tc_setclock_mtx, "tcsetc", MTX_SPIN);
 #endif /* __rtems__ */
@@ -1446,6 +1461,9 @@ _Timecounter_Set_clock(const struct bintime *_bt,
 #ifndef __rtems__
 	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);
 	if (timestepwarnings) {
 		nanotime(&taft);
 		log(LOG_INFO,



More information about the vc mailing list