mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 06:33:31 +00:00
timer connection: no interpolation on arm w/o hw
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 on ARM. Except we're on the HW kernel. In this case we can read out the kernel time instead. Ref #2435
This commit is contained in:
parent
0d79611c03
commit
685f509a43
@ -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
|
||||
|
@ -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
|
||||
|
@ -1 +1,3 @@
|
||||
LIBS += timeout
|
||||
|
||||
include $(REP_DIR)/lib/mk/base-foc.inc
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -6,4 +6,6 @@
|
||||
|
||||
SRC_CC += cpu/arm/cache.cc
|
||||
|
||||
LIBS += timeout-arm
|
||||
|
||||
include $(REP_DIR)/lib/mk/base.mk
|
||||
|
@ -6,4 +6,6 @@
|
||||
|
||||
SRC_CC += cache.cc
|
||||
|
||||
LIBS += timeout
|
||||
|
||||
include $(REP_DIR)/lib/mk/base-linux.mk
|
||||
|
10
repos/os/lib/mk/timeout-arm.mk
Normal file
10
repos/os/lib/mk/timeout-arm.mk
Normal file
@ -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
|
@ -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
|
||||
|
||||
|
32
repos/os/src/lib/timeout/arm/timer_connection_time.cc
Normal file
32
repos/os/src/lib/timeout/arm/timer_connection_time.cc
Normal file
@ -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 <timer_session/connection.h>
|
||||
#include <base/internal/globals.h>
|
||||
|
||||
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()));
|
||||
}
|
@ -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.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -69,62 +69,6 @@ unsigned long Timer::Connection::_ts_to_us_ratio(Timestamp ts,
|
||||
}
|
||||
|
||||
|
||||
void Timer::Connection::_update_real_time()
|
||||
{
|
||||
Lock_guard<Lock> 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<Lock> > 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) {
|
||||
|
120
repos/os/src/lib/timeout/timer_connection_time.cc
Normal file
120
repos/os/src/lib/timeout/timer_connection_time.cc
Normal file
@ -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 <timer_session/connection.h>
|
||||
#include <base/internal/globals.h>
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Genode::Trace;
|
||||
|
||||
|
||||
void Timer::Connection::_update_real_time()
|
||||
{
|
||||
Lock_guard<Lock> 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<Lock> > 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user