genode/repos/base-nova/src/timer/nova/time_source.cc
Martin Stein 7feea78991 timeout: rework timeout framework
* get rid of alarm abstraction
* get rid of Timeout::Time type
* get rid of pointer arguments
* get rid of _discard_timeout indirection
* get rid of 65th bit in stored time values
* get rid of Timeout_scheduler interface
* get rid of uninitialized deadlines
* get rid of default arguments
* get rid of Timeout::_periodic
* get rid of Timeout::Raw
* use list abstraction
* only one interface for timeout handlers
* rework locking scheme to be smp safe
* move all method definitions to CC file
* name mutexes more accurate
* fix when & how to set time-source timeout
* fix deadlocks

Fixes #3884
2020-10-09 13:35:56 +02:00

69 lines
1.6 KiB
C++

/*
* \brief Time source using Nova timed semaphore down
* \author Alexander Boettcher
* \author Martin Stein
* \date 2014-06-24
*/
/*
* Copyright (C) 2014-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.
*/
/* NOVA includes */
#include <nova/native_thread.h>
/* local includes */
#include <time_source.h>
using namespace Genode;
using namespace Nova;
void Timer::Time_source::set_timeout(Microseconds duration,
Timeout_handler &handler)
{
/* set new timeout parameters and wake up the blocking thread */
Threaded_time_source::handler(handler);
_timeout_us = duration.value;
if (_sem) {
if (Nova::sm_ctrl(_sem, Nova::SEMAPHORE_UP) != Nova::NOVA_OK) {
nova_die();
}
}
}
Timer::Time_source::Result_of_wait_for_irq
Timer::Time_source::_wait_for_irq()
{
/* initialize semaphore if not done yet */
if (!_sem) {
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);
_sem = Thread::native_thread().exc_pt_sel + SM_SEL_SIGNAL;
}
/* calculate absolute timeout */
unsigned long long const deadline_timestamp {
_timeout_us <= max_timeout().value ?
Trace::timestamp() + _timeout_us * (_tsc_khz / TSC_FACTOR) : 0 };
/* block until timeout fires or it gets canceled */
switch (sm_ctrl(_sem, SEMAPHORE_DOWN, deadline_timestamp)) {
case Nova::NOVA_TIMEOUT:
return IRQ_TRIGGERED;
case Nova::NOVA_OK:
return CANCELLED;
default:
nova_die();
return CANCELLED;
}
}