summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/score/src/kern_tc.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index 2810fd88dd..81c2131008 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,