summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-02-22 11:49:33 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-02-28 10:07:30 +0100
commit5e093a5bcb69ad1fb84c5898dff15e8820487256 (patch)
tree4f084b01112883fba707bc9ddbcfc2505755f397
parentC11/C++11 are the default for the RTEMS 4.12 GCC (diff)
downloadrtems-libbsd-5e093a5bcb69ad1fb84c5898dff15e8820487256.tar.bz2
SLEEPQUEUE(9): Fix absolute timeouts
The FreeBSD kernel timeouts are always based on the uptime. Thus, we have to use the relative watchdog. C_ABSOLUTE just means that the timeout value is already an uptime value. https://lists.freebsd.org/pipermail/freebsd-hackers/2017-February/050572.html
-rw-r--r--freebsd/sys/kern/subr_sleepqueue.c29
1 files changed, 24 insertions, 5 deletions
diff --git a/freebsd/sys/kern/subr_sleepqueue.c b/freebsd/sys/kern/subr_sleepqueue.c
index 971f92dd..90023066 100644
--- a/freebsd/sys/kern/subr_sleepqueue.c
+++ b/freebsd/sys/kern/subr_sleepqueue.c
@@ -448,20 +448,39 @@ sleepq_set_timeout_sbt(void *wchan, sbintime_t sbt, sbintime_t pr,
#else /* __rtems__ */
Per_CPU_Control *cpu_self;
Thread_Control *executing;
+ ISR_lock_Context lock_context;
+ ISR_lock_Context lock_context_2;
+ Watchdog_Header *header;
+ uint64_t expire;
cpu_self = _Thread_Dispatch_disable();
executing = _Per_CPU_Get_executing(cpu_self);
BSD_ASSERT(_Watchdog_Get_state(&executing->Timer.Watchdog) ==
WATCHDOG_INACTIVE);
- if ((flags & C_ABSOLUTE) == 0) {
- _Thread_Timer_insert_relative(executing, cpu_self, sleepq_timeout,
- (Watchdog_Interval)((sbt + tick_sbt - 1) / tick_sbt));
+ _ISR_lock_ISR_disable_and_acquire(&executing->Timer.Lock, &lock_context);
+
+ header = &cpu_self->Watchdog.Header[PER_CPU_WATCHDOG_RELATIVE];
+ executing->Timer.header = header;
+ executing->Timer.Watchdog.routine = sleepq_timeout;
+ _Watchdog_Set_CPU(&executing->Timer.Watchdog, cpu_self);
+
+ _Watchdog_Per_CPU_acquire_critical(cpu_self, &lock_context_2);
+
+ if ((flags & C_ABSOLUTE) != 0) {
+ /*
+ * The FreeBSD uptime starts at one second, however, the
+ * relative watchdog ticks start at zero, see also TIMESEL().
+ */
+ expire = (sbt - SBT_1S + tick_sbt - 1) / tick_sbt;
} else {
- _Thread_Timer_insert_absolute(executing, cpu_self, sleepq_timeout,
- _Watchdog_Ticks_from_sbintime(sbt));
+ expire = (sbt + tick_sbt - 1) / tick_sbt;
+ expire += cpu_self->Watchdog.ticks;
}
+ _Watchdog_Insert(header, &executing->Timer.Watchdog, expire);
+ _Watchdog_Per_CPU_release_critical(cpu_self, &lock_context_2);
+ _ISR_lock_Release_and_ISR_enable(&executing->Timer.Lock, &lock_context);
_Thread_Dispatch_direct(cpu_self);
#endif /* __rtems__ */
}