nova: avoid Blocking_canceled exception in timer

Issue #3819
This commit is contained in:
Alexander Boettcher 2020-07-20 13:00:56 +02:00 committed by Christian Helmuth
parent de795b1a6e
commit eab09a2f7c
4 changed files with 16 additions and 10 deletions

View File

@ -756,6 +756,7 @@ namespace Nova {
PT_SEL_PARENT = 0x1a, /* convention on Genode */
PT_SEL_MAIN_EC = 0x1c, /* convention on Genode */
PT_SEL_STARTUP = 0x1e,
SM_SEL_SIGNAL = 0x1e, /* alias of PT_SEL_STARTUP */
PT_SEL_RECALL = 0x1f,
SM_SEL_EC = 0x1d, /* convention on Genode */
};

View File

@ -54,9 +54,10 @@ namespace Genode {
{
/* request mapping of semaphore capability selector */
Thread * myself = Thread::myself();
request_signal_sm_cap(myself->native_thread().exc_pt_sel + Nova::PT_SEL_PAGE_FAULT,
myself->native_thread().exc_pt_sel + Nova::PT_SEL_STARTUP);
_sem = Capability_space::import(myself->native_thread().exc_pt_sel + Nova::PT_SEL_STARTUP);
auto const &exc_base = myself->native_thread().exc_pt_sel;
request_signal_sm_cap(exc_base + Nova::PT_SEL_PAGE_FAULT,
exc_base + Nova::SM_SEL_SIGNAL);
_sem = Capability_space::import(exc_base + Nova::SM_SEL_SIGNAL);
call<Rpc_register_semaphore>(_sem);
}

View File

@ -28,7 +28,7 @@ void Timer::Time_source::schedule_timeout(Microseconds duration,
Threaded_time_source::handler(handler);
/* check whether to cancel last timeout */
if (duration.value == 0 && _sem != ~0UL) {
if (duration.value == 0 && _sem) {
uint8_t res = Nova::sm_ctrl(_sem, Nova::SEMAPHORE_UP);
if (res != Nova::NOVA_OK)
nova_die();
@ -40,10 +40,14 @@ void Timer::Time_source::schedule_timeout(Microseconds duration,
void Timer::Time_source::_wait_for_irq()
{
if (_sem == ~0UL) {
_sem = Thread::native_thread().exc_pt_sel + SM_SEL_EC; }
if (!_sem) {
/* initialize first time in context of running thread */
auto const &exc_base = Thread::native_thread().exc_pt_sel;
request_signal_sm_cap(exc_base + Nova::PT_SEL_PAGE_FAULT,
exc_base + Nova::SM_SEL_SIGNAL);
addr_t sem = _sem;
_sem = Thread::native_thread().exc_pt_sel + SM_SEL_SIGNAL;
}
/* calculate absolute timeout */
Trace::Timestamp now = Trace::timestamp();
@ -52,7 +56,7 @@ void Timer::Time_source::_wait_for_irq()
if (_timeout_us == max_timeout().value) {
/* tsc_absolute == 0 means blocking without timeout */
uint8_t res = sm_ctrl(sem, SEMAPHORE_DOWN, 0);
uint8_t res = sm_ctrl(_sem, SEMAPHORE_DOWN, 0);
if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT) {
nova_die(); }
@ -60,7 +64,7 @@ void Timer::Time_source::_wait_for_irq()
/* block until timeout fires or it gets canceled */
unsigned long long tsc_absolute = now + us_64 * (_tsc_khz / TSC_FACTOR);
uint8_t res = sm_ctrl(sem, SEMAPHORE_DOWN, tsc_absolute);
uint8_t res = sm_ctrl(_sem, SEMAPHORE_DOWN, tsc_absolute);
if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT) {
nova_die(); }
}

View File

@ -57,7 +57,7 @@ class Timer::Time_source : public Threaded_time_source
return 1000*1000;
}
Genode::addr_t _sem { ~0UL };
Genode::addr_t _sem { 0 };
uint64_t _timeout_us { 0 };
unsigned long const _tsc_khz;
Duration _curr_time { Microseconds(0) };