diff --git a/repos/base-foc/lib/mk/base-foc.inc b/repos/base-foc/lib/mk/base-foc.inc index 4f0175471..4b78fbf6b 100644 --- a/repos/base-foc/lib/mk/base-foc.inc +++ b/repos/base-foc/lib/mk/base-foc.inc @@ -1,6 +1,6 @@ include $(BASE_DIR)/lib/mk/base.inc -LIBS += base-foc-common syscall-foc cxx timeout +LIBS += base-foc-common syscall-foc cxx SRC_CC += cap_map_remove.cc cap_alloc.cc SRC_CC += thread_start.cc diff --git a/repos/base-foc/lib/mk/spec/arm/base-foc.mk b/repos/base-foc/lib/mk/spec/arm/base-foc.mk index 77ff4ac86..542fb51b1 100644 --- a/repos/base-foc/lib/mk/spec/arm/base-foc.mk +++ b/repos/base-foc/lib/mk/spec/arm/base-foc.mk @@ -1,4 +1,6 @@ # override default stack-area location INC_DIR += $(REP_DIR)/src/include/spec/arm +LIBS += timeout-arm + include $(REP_DIR)/lib/mk/base-foc.inc diff --git a/repos/base-foc/lib/mk/spec/x86/base-foc.mk b/repos/base-foc/lib/mk/spec/x86/base-foc.mk index ff31b15f8..820c2c270 100644 --- a/repos/base-foc/lib/mk/spec/x86/base-foc.mk +++ b/repos/base-foc/lib/mk/spec/x86/base-foc.mk @@ -1 +1,3 @@ +LIBS += timeout + include $(REP_DIR)/lib/mk/base-foc.inc diff --git a/repos/base-hw/lib/mk/timeout-hw.mk b/repos/base-hw/lib/mk/timeout-hw.mk index 235f50ec7..e8a5a7dc6 100644 --- a/repos/base-hw/lib/mk/timeout-hw.mk +++ b/repos/base-hw/lib/mk/timeout-hw.mk @@ -1,5 +1,6 @@ SRC_CC += timeout.cc SRC_CC += timer_connection.cc +SRC_CC += timer_connection_time.cc SRC_CC += hw/timer_connection_timestamp.cc SRC_CC += duration.cc diff --git a/repos/base-linux/lib/mk/base-linux.mk b/repos/base-linux/lib/mk/base-linux.mk index 1ce498bd1..60e26542e 100644 --- a/repos/base-linux/lib/mk/base-linux.mk +++ b/repos/base-linux/lib/mk/base-linux.mk @@ -6,7 +6,7 @@ include $(REP_DIR)/lib/mk/base-linux.inc -LIBS += startup-linux base-linux-common cxx timeout +LIBS += startup-linux base-linux-common cxx SRC_CC += thread.cc thread_myself.cc thread_linux.cc SRC_CC += capability_space.cc capability_raw.cc SRC_CC += attach_stack_area.cc diff --git a/repos/base-linux/lib/mk/spec/arm/base-linux.mk b/repos/base-linux/lib/mk/spec/arm/base-linux.mk index c8020257b..80643724d 100644 --- a/repos/base-linux/lib/mk/spec/arm/base-linux.mk +++ b/repos/base-linux/lib/mk/spec/arm/base-linux.mk @@ -6,4 +6,6 @@ SRC_CC += cpu/arm/cache.cc +LIBS += timeout-arm + include $(REP_DIR)/lib/mk/base.mk diff --git a/repos/base-linux/lib/mk/spec/x86/base-linux.mk b/repos/base-linux/lib/mk/spec/x86/base-linux.mk index a3ba74e82..1feab5a90 100644 --- a/repos/base-linux/lib/mk/spec/x86/base-linux.mk +++ b/repos/base-linux/lib/mk/spec/x86/base-linux.mk @@ -6,4 +6,6 @@ SRC_CC += cache.cc +LIBS += timeout + include $(REP_DIR)/lib/mk/base-linux.mk diff --git a/repos/os/lib/mk/timeout-arm.mk b/repos/os/lib/mk/timeout-arm.mk new file mode 100644 index 000000000..2ce3b6a28 --- /dev/null +++ b/repos/os/lib/mk/timeout-arm.mk @@ -0,0 +1,10 @@ +SRC_CC += timeout.cc +SRC_CC += timer_connection.cc +SRC_CC += arm/timer_connection_time.cc +SRC_CC += duration.cc + +LIBS += alarm + +INC_DIR += $(BASE_DIR)/src/include + +vpath % $(BASE_DIR)/../os/src/lib/timeout diff --git a/repos/os/lib/mk/timeout.mk b/repos/os/lib/mk/timeout.mk index eaddf2777..d2649af4b 100644 --- a/repos/os/lib/mk/timeout.mk +++ b/repos/os/lib/mk/timeout.mk @@ -1,5 +1,6 @@ SRC_CC += timeout.cc SRC_CC += timer_connection.cc +SRC_CC += timer_connection_time.cc SRC_CC += timer_connection_timestamp.cc SRC_CC += duration.cc diff --git a/repos/os/src/lib/timeout/arm/timer_connection_time.cc b/repos/os/src/lib/timeout/arm/timer_connection_time.cc new file mode 100644 index 000000000..e5c07f0ce --- /dev/null +++ b/repos/os/src/lib/timeout/arm/timer_connection_time.cc @@ -0,0 +1,32 @@ +/* + * \brief Connection to timer service and timeout scheduler + * \author Martin Stein + * \date 2016-11-04 + * + * On ARM, we do not have a component-local hardware time-source. The ARM + * performance counter has no reliable frequency as the ARM idle command + * halts the counter. Thus, we do not do local time interpolation. + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include + +using namespace Genode; +using namespace Genode::Trace; + +Timestamp Timer::Connection::_timestamp() { return 0ULL; } + +void Timer::Connection::_update_real_time() { } + +Duration Timer::Connection::curr_time() +{ + return Duration(Milliseconds(elapsed_ms())); +} diff --git a/repos/os/src/lib/timeout/hw/timer_connection_timestamp.cc b/repos/os/src/lib/timeout/hw/timer_connection_timestamp.cc index dc2f04b04..46bce911f 100644 --- a/repos/os/src/lib/timeout/hw/timer_connection_timestamp.cc +++ b/repos/os/src/lib/timeout/hw/timer_connection_timestamp.cc @@ -2,6 +2,11 @@ * \brief Timestamp implementation for the Genode Timer * \author Martin Stein * \date 2016-11-04 + * + * On ARM, we do not have a component-local hardware time-source. The ARM + * performance counter has no reliable frequency as the ARM idle command + * halts the counter. However, on the HW kernel, we use a syscall that reads + * out the kernel time instead. */ /* diff --git a/repos/os/src/lib/timeout/timer_connection.cc b/repos/os/src/lib/timeout/timer_connection.cc index 3a3f33a96..c16682606 100644 --- a/repos/os/src/lib/timeout/timer_connection.cc +++ b/repos/os/src/lib/timeout/timer_connection.cc @@ -69,62 +69,6 @@ unsigned long Timer::Connection::_ts_to_us_ratio(Timestamp ts, } -void Timer::Connection::_update_real_time() -{ - Lock_guard lock_guard(_real_time_lock); - - Timestamp ts = 0UL; - unsigned long ms = 0UL; - unsigned long us_diff = ~0UL; - - for (unsigned remote_time_trials = 0; - remote_time_trials < MAX_REMOTE_TIME_TRIALS; - remote_time_trials++) - { - /* determine time and timestamp difference since the last call */ - Timestamp volatile new_ts = _timestamp(); - unsigned long volatile new_ms = elapsed_ms(); - - if (_interpolation_quality < MAX_INTERPOLATION_QUALITY) { - ms = new_ms; - ts = new_ts; - break; - } - - Timestamp const ts_diff = _timestamp() - new_ts; - unsigned long const new_us_diff = _ts_to_us_ratio(ts_diff, - _us_to_ts_factor); - - /* remember results only if the latency was better than last time */ - if (new_us_diff < us_diff) { - ms = new_ms; - ts = new_ts; - - if (us_diff < MAX_REMOTE_TIME_LATENCY_US) { - break; - } - } - } - - unsigned long const ms_diff = ms - _ms; - Timestamp const ts_diff = ts - _ts; - - /* update real time and values for next difference calculation */ - _ms = ms; - _ts = ts; - _real_time += Milliseconds(ms_diff); - - unsigned long const new_factor = _ts_to_us_ratio(ts_diff, ms_diff * 1000UL); - unsigned long const old_factor = _us_to_ts_factor; - - /* update interpolation-quality value */ - if (old_factor > new_factor) { _update_interpolation_quality(new_factor, old_factor); } - else { _update_interpolation_quality(old_factor, new_factor); } - - _us_to_ts_factor = new_factor; -} - - Duration Timer::Connection::_update_interpolated_time(Duration &interpolated_time) { /* @@ -167,51 +111,6 @@ void Timer::Connection::schedule_timeout(Microseconds duration, } -Duration Timer::Connection::curr_time() -{ - _enable_modern_mode(); - - Reconstructible > lock_guard(_real_time_lock); - Duration interpolated_time(_real_time); - - /* - * Interpolate with timestamps only if the factor value - * remained stable for some time. If we would interpolate with - * a yet unstable factor, there's an increased risk that the - * interpolated time falsely reaches an enourmous level. Then - * the value would stand still for quite some time because we - * can't let it jump back to a more realistic level. This - * would also eliminate updates of the real time as the - * timeout scheduler that manages our update timeout also - * uses this function. - */ - if (_interpolation_quality == MAX_INTERPOLATION_QUALITY) { - - /* locally buffer real-time related members */ - unsigned long const ts = _ts; - unsigned long const us_to_ts_factor = _us_to_ts_factor; - - lock_guard.destruct(); - - /* get time difference since the last real time update */ - Timestamp const ts_diff = _timestamp() - ts; - unsigned long const us_diff = _ts_to_us_ratio(ts_diff, us_to_ts_factor); - - interpolated_time += Microseconds(us_diff); - - } else { - - /* - * Use remote timer instead of timestamps - */ - interpolated_time += Milliseconds(elapsed_ms() - _ms); - - lock_guard.destruct(); - } - return _update_interpolated_time(interpolated_time); -} - - void Timer::Connection::_enable_modern_mode() { if (_mode == MODERN) { diff --git a/repos/os/src/lib/timeout/timer_connection_time.cc b/repos/os/src/lib/timeout/timer_connection_time.cc new file mode 100644 index 000000000..6aeab59b5 --- /dev/null +++ b/repos/os/src/lib/timeout/timer_connection_time.cc @@ -0,0 +1,120 @@ +/* + * \brief Connection to timer service and timeout scheduler + * \author Martin Stein + * \date 2016-11-04 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include + +using namespace Genode; +using namespace Genode::Trace; + + +void Timer::Connection::_update_real_time() +{ + Lock_guard lock_guard(_real_time_lock); + + Timestamp ts = 0UL; + unsigned long ms = 0UL; + unsigned long us_diff = ~0UL; + + for (unsigned remote_time_trials = 0; + remote_time_trials < MAX_REMOTE_TIME_TRIALS; + remote_time_trials++) + { + /* determine time and timestamp difference since the last call */ + Timestamp volatile new_ts = _timestamp(); + unsigned long volatile new_ms = elapsed_ms(); + + if (_interpolation_quality < MAX_INTERPOLATION_QUALITY) { + ms = new_ms; + ts = new_ts; + break; + } + + Timestamp const ts_diff = _timestamp() - new_ts; + unsigned long const new_us_diff = _ts_to_us_ratio(ts_diff, + _us_to_ts_factor); + + /* remember results only if the latency was better than last time */ + if (new_us_diff < us_diff) { + ms = new_ms; + ts = new_ts; + + if (us_diff < MAX_REMOTE_TIME_LATENCY_US) { + break; + } + } + } + + unsigned long const ms_diff = ms - _ms; + Timestamp const ts_diff = ts - _ts; + + /* update real time and values for next difference calculation */ + _ms = ms; + _ts = ts; + _real_time += Milliseconds(ms_diff); + + unsigned long const new_factor = _ts_to_us_ratio(ts_diff, ms_diff * 1000UL); + unsigned long const old_factor = _us_to_ts_factor; + + /* update interpolation-quality value */ + if (old_factor > new_factor) { _update_interpolation_quality(new_factor, old_factor); } + else { _update_interpolation_quality(old_factor, new_factor); } + + _us_to_ts_factor = new_factor; +} + + +Duration Timer::Connection::curr_time() +{ + _enable_modern_mode(); + + Reconstructible > lock_guard(_real_time_lock); + Duration interpolated_time(_real_time); + + /* + * Interpolate with timestamps only if the factor value + * remained stable for some time. If we would interpolate with + * a yet unstable factor, there's an increased risk that the + * interpolated time falsely reaches an enourmous level. Then + * the value would stand still for quite some time because we + * can't let it jump back to a more realistic level. This + * would also eliminate updates of the real time as the + * timeout scheduler that manages our update timeout also + * uses this function. + */ + if (_interpolation_quality == MAX_INTERPOLATION_QUALITY) + { + /* locally buffer real-time related members */ + unsigned long const ts = _ts; + unsigned long const us_to_ts_factor = _us_to_ts_factor; + + lock_guard.destruct(); + + /* get time difference since the last real time update */ + Timestamp const ts_diff = _timestamp() - ts; + unsigned long const us_diff = _ts_to_us_ratio(ts_diff, us_to_ts_factor); + + interpolated_time += Microseconds(us_diff); + + } else { + + /* + * Use remote timer instead of timestamps + */ + interpolated_time += Milliseconds(elapsed_ms() - _ms); + + lock_guard.destruct(); + } + return _update_interpolated_time(interpolated_time); +}