/* * \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 /* local includes */ #include "time_source.h" using namespace Genode; using namespace Nova; void Timer::Time_source::schedule_timeout(Microseconds duration, Timeout_handler &handler) { Threaded_time_source::handler(handler); /* check whether to cancel last timeout */ if (duration.value == 0 && _sem != ~0UL) { uint8_t res = Nova::sm_ctrl(_sem, Nova::SEMAPHORE_UP); if (res != Nova::NOVA_OK) nova_die(); } /* remember timeout to be set during wait_for_timeout call */ _timeout_us = duration.value; } void Timer::Time_source::_wait_for_irq() { if (_sem == ~0UL) { _sem = Thread::native_thread().exc_pt_sel + SM_SEL_EC; } addr_t sem = _sem; /* calculate absolute timeout */ Trace::Timestamp now = Trace::timestamp(); Trace::Timestamp us_64 = _timeout_us; if (_timeout_us == max_timeout().value) { /* tsc_absolute == 0 means blocking without timeout */ uint8_t res = sm_ctrl(sem, SEMAPHORE_DOWN, 0); if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT) { nova_die(); } } else { /* 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); if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT) { nova_die(); } } }