[rtems-libbsd commit] SLEEPQUEUE(9): Fix absolute timeouts

Sebastian Huber sebh at rtems.org
Tue Feb 28 09:55:38 UTC 2017


Module:    rtems-libbsd
Branch:    master
Commit:    5e093a5bcb69ad1fb84c5898dff15e8820487256
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=5e093a5bcb69ad1fb84c5898dff15e8820487256

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Wed Feb 22 11:49:33 2017 +0100

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

---

 freebsd/sys/kern/subr_sleepqueue.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/freebsd/sys/kern/subr_sleepqueue.c b/freebsd/sys/kern/subr_sleepqueue.c
index 971f92d..9002306 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__ */
 }



More information about the vc mailing list