mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
parent
791138ee63
commit
b85fa1d069
@ -1,6 +1,5 @@
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/periodic
|
||||
|
||||
SRC_CC += spec/periodic/time_source.cc spec/fiasco/time_source.cc
|
||||
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/include_periodic
|
||||
|
||||
SRC_CC += platform_timer.cc
|
||||
vpath platform_timer.cc $(REP_DIR)/src/drivers/timer/spec/fiasco
|
||||
|
@ -1,6 +1,5 @@
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/periodic
|
||||
|
||||
SRC_CC += spec/periodic/time_source.cc spec/fiasco/time_source.cc
|
||||
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/include_periodic
|
||||
|
||||
SRC_CC += platform_timer.cc
|
||||
vpath platform_timer.cc $(REP_DIR)/src/drivers/timer/spec/fiasco
|
||||
|
@ -1,3 +1,5 @@
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/hw
|
||||
|
||||
SRC_CC += spec/hw/time_source.cc
|
||||
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
@ -1,8 +1,7 @@
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/periodic
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/include_periodic
|
||||
SRC_CC += spec/periodic/time_source.cc spec/linux/time_source.cc
|
||||
|
||||
LIBS += syscall
|
||||
|
||||
SRC_CC += platform_timer.cc
|
||||
vpath platform_timer.cc $(REP_DIR)/src/drivers/timer/spec/linux
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
@ -1,3 +1,5 @@
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/nova
|
||||
|
||||
SRC_CC += spec/nova/time_source.cc
|
||||
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
@ -1,3 +1,5 @@
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/pit
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/include_pit
|
||||
SRC_CC += spec/pit/time_source.cc
|
||||
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
@ -1,6 +1,5 @@
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/periodic
|
||||
|
||||
SRC_CC += spec/periodic/time_source.cc spec/pistachio/time_source.cc
|
||||
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/include_periodic
|
||||
|
||||
SRC_CC += platform_timer.cc
|
||||
vpath platform_timer.cc $(REP_DIR)/src/drivers/timer/spec/pistachio
|
||||
|
@ -1,3 +1,5 @@
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/pit
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/include_pit
|
||||
SRC_CC += spec/pit/time_source.cc
|
||||
|
||||
include $(REP_DIR)/lib/mk/timer.inc
|
||||
|
@ -1,5 +1,7 @@
|
||||
SRC_CC += main.cc
|
||||
LIBS += base alarm server
|
||||
SRC_CC += main.cc
|
||||
|
||||
LIBS += base timeout
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/timer/include
|
||||
|
||||
vpath main.cc $(REP_DIR)/src/drivers/timer
|
||||
vpath %.cc $(REP_DIR)/src/drivers/timer
|
||||
|
62
repos/os/src/drivers/timer/include/root_component.h
Normal file
62
repos/os/src/drivers/timer/include/root_component.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* \brief Root interface to timer service
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2006-08-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _ROOT_COMPONENT_H_
|
||||
#define _ROOT_COMPONENT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <root/component.h>
|
||||
|
||||
/* local includes */
|
||||
#include <time_source.h>
|
||||
#include <session_component.h>
|
||||
|
||||
namespace Timer { class Root_component; }
|
||||
|
||||
|
||||
class Timer::Root_component : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Time_source _time_source;
|
||||
Genode::Alarm_timeout_scheduler _timeout_scheduler;
|
||||
|
||||
|
||||
/********************
|
||||
** Root_component **
|
||||
********************/
|
||||
|
||||
Session_component *_create_session(const char *args)
|
||||
{
|
||||
using namespace Genode;
|
||||
size_t const ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota").ulong_value(0);
|
||||
|
||||
if (ram_quota < sizeof(Session_component)) {
|
||||
throw Root::Quota_exceeded(); }
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_timeout_scheduler);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root_component(Genode::Entrypoint &ep, Genode::Allocator &md_alloc)
|
||||
:
|
||||
Genode::Root_component<Session_component>(&ep.rpc_ep(), &md_alloc),
|
||||
_time_source(ep), _timeout_scheduler(_time_source)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* _ROOT_COMPONENT_H_ */
|
69
repos/os/src/drivers/timer/include/session_component.h
Normal file
69
repos/os/src/drivers/timer/include/session_component.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* \brief Instance of the timer session interface
|
||||
* \author Norman Feske
|
||||
* \author Markus Partheymueller
|
||||
* \author Martin Stein
|
||||
* \date 2006-08-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SESSION_COMPONENT_
|
||||
#define _SESSION_COMPONENT_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
#include <timer_session/timer_session.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <os/timeout.h>
|
||||
|
||||
namespace Timer { class Session_component; }
|
||||
|
||||
|
||||
class Timer::Session_component : public Genode::Rpc_object<Session>,
|
||||
public Genode::List<Session_component>::Element,
|
||||
private Genode::Timeout::Handler
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Timeout _timeout;
|
||||
Genode::Timeout_scheduler &_timeout_scheduler;
|
||||
Genode::Signal_context_capability _sigh;
|
||||
|
||||
unsigned long const _init_time_us = _timeout_scheduler.curr_time().value;
|
||||
|
||||
void handle_timeout(Microseconds) {
|
||||
Genode::Signal_transmitter(_sigh).submit(); }
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Genode::Timeout_scheduler &timeout_scheduler)
|
||||
: _timeout(timeout_scheduler), _timeout_scheduler(timeout_scheduler) { }
|
||||
|
||||
|
||||
/********************
|
||||
** Timer::Session **
|
||||
********************/
|
||||
|
||||
void trigger_once(unsigned us) override {
|
||||
_timeout.schedule_one_shot(Microseconds(us), *this); }
|
||||
|
||||
void trigger_periodic(unsigned us) override {
|
||||
_timeout.schedule_periodic(Microseconds(us), *this); }
|
||||
|
||||
void sigh(Signal_context_capability sigh) override { _sigh = sigh; }
|
||||
|
||||
unsigned long elapsed_ms() const override {
|
||||
return (_timeout_scheduler.curr_time().value - _init_time_us) / 1000; }
|
||||
|
||||
void msleep(unsigned) override { /* never called at the server side */ }
|
||||
void usleep(unsigned) override { /* never called at the server side */ }
|
||||
};
|
||||
|
||||
#endif /* _SESSION_COMPONENT_ */
|
49
repos/os/src/drivers/timer/include/signalled_time_source.h
Normal file
49
repos/os/src/drivers/timer/include/signalled_time_source.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* \brief Time source that handles timeouts via a signal handler
|
||||
* \author Martin Stein
|
||||
* \date 2016-11-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SIGNALLED_TIME_SOURCE_H_
|
||||
#define _SIGNALLED_TIME_SOURCE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/time_source.h>
|
||||
#include <base/rpc_client.h>
|
||||
#include <base/entrypoint.h>
|
||||
|
||||
namespace Genode { class Signalled_time_source; }
|
||||
|
||||
|
||||
class Genode::Signalled_time_source : public Time_source
|
||||
{
|
||||
protected:
|
||||
|
||||
using Signal_handler = Genode::Signal_handler<Signalled_time_source>;
|
||||
|
||||
Signal_handler _signal_handler;
|
||||
Timeout_handler *_handler = nullptr;
|
||||
|
||||
void _handle_timeout()
|
||||
{
|
||||
if (_handler) {
|
||||
_handler->handle_timeout(curr_time()); }
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Signalled_time_source(Entrypoint &ep)
|
||||
:
|
||||
_signal_handler(ep, *this,
|
||||
&Signalled_time_source::_handle_timeout)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif /* _SIGNALLED_TIME_SOURCE_H_ */
|
89
repos/os/src/drivers/timer/include/threaded_time_source.h
Normal file
89
repos/os/src/drivers/timer/include/threaded_time_source.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* \brief Time source that uses an extra thread for timeout handling
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2009-06-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _THREADED_TIME_SOURCE_H_
|
||||
#define _THREADED_TIME_SOURCE_H_
|
||||
|
||||
/* Genode inludes */
|
||||
#include <base/entrypoint.h>
|
||||
#include <base/rpc_client.h>
|
||||
#include <os/time_source.h>
|
||||
|
||||
namespace Timer {
|
||||
|
||||
enum { STACK_SIZE = 8 * 1024 * sizeof(Genode::addr_t) };
|
||||
|
||||
class Threaded_time_source;
|
||||
}
|
||||
|
||||
|
||||
class Timer::Threaded_time_source : public Genode::Time_source,
|
||||
protected Genode::Thread_deprecated<STACK_SIZE>
|
||||
{
|
||||
private:
|
||||
|
||||
struct Irq_dispatcher
|
||||
{
|
||||
GENODE_RPC(Rpc_do_dispatch, void, do_dispatch, Microseconds);
|
||||
GENODE_RPC_INTERFACE(Rpc_do_dispatch);
|
||||
};
|
||||
|
||||
struct Irq_dispatcher_component : Genode::Rpc_object<Irq_dispatcher,
|
||||
Irq_dispatcher_component>
|
||||
{
|
||||
Timeout_handler *handler = nullptr;
|
||||
|
||||
|
||||
/********************
|
||||
** Irq_dispatcher **
|
||||
********************/
|
||||
|
||||
void do_dispatch(Microseconds duration)
|
||||
{
|
||||
if (handler) {
|
||||
handler->handle_timeout(Microseconds(duration)); }
|
||||
}
|
||||
|
||||
} _irq_dispatcher_component;
|
||||
|
||||
Genode::Capability<Irq_dispatcher> _irq_dispatcher_cap;
|
||||
|
||||
virtual void _wait_for_irq() = 0;
|
||||
|
||||
|
||||
/***********************
|
||||
** Thread_deprecated **
|
||||
***********************/
|
||||
|
||||
void entry()
|
||||
{
|
||||
while (true) {
|
||||
_wait_for_irq();
|
||||
_irq_dispatcher_cap.call<Irq_dispatcher::Rpc_do_dispatch>(curr_time());
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Threaded_time_source(Genode::Entrypoint &ep)
|
||||
:
|
||||
Thread_deprecated<STACK_SIZE>("threaded_time_source"),
|
||||
_irq_dispatcher_cap(ep.rpc_ep().manage(&_irq_dispatcher_component))
|
||||
{ }
|
||||
|
||||
void handler(Timeout_handler &handler) {
|
||||
_irq_dispatcher_component.handler = &handler; }
|
||||
};
|
||||
|
||||
#endif /* _THREADED_TIME_SOURCE_H_ */
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* \brief Root interface to timer service
|
||||
* \author Norman Feske
|
||||
* \date 2006-08-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_ROOT_H_
|
||||
#define _TIMER_ROOT_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/arg_string.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/heap.h>
|
||||
#include <root/component.h>
|
||||
#include <cap_session/cap_session.h>
|
||||
#include <os/server.h>
|
||||
|
||||
/* local includes */
|
||||
#include "timer_session_component.h"
|
||||
|
||||
|
||||
namespace Timer { class Root_component; }
|
||||
|
||||
|
||||
class Timer::Root_component : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Platform_timer _platform_timer;
|
||||
Timeout_scheduler _timeout_scheduler;
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args)
|
||||
{
|
||||
Genode::size_t ram_quota = Genode::Arg_string::find_arg(args, "ram_quota").ulong_value(0);
|
||||
|
||||
if (ram_quota < sizeof(Session_component)) {
|
||||
PWRN("Insufficient donated ram_quota (%ld bytes), require %zd bytes",
|
||||
ram_quota, sizeof(Session_component));
|
||||
}
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_timeout_scheduler);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* The 'cap' argument is not used by the single-threaded server
|
||||
* variant.
|
||||
*/
|
||||
Root_component(Server::Entrypoint &ep,
|
||||
Genode::Allocator *md_alloc,
|
||||
Genode::Cap_session *cap)
|
||||
:
|
||||
Genode::Root_component<Session_component>(&ep.rpc_ep(), md_alloc),
|
||||
_timeout_scheduler(&_platform_timer, &ep.rpc_ep())
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif
|
@ -1,282 +0,0 @@
|
||||
/*
|
||||
* \brief Instance of the timer session interface
|
||||
* \author Norman Feske
|
||||
* \author Markus Partheymueller
|
||||
* \date 2006-08-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2012 Intel Corporation
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TIMER_SESSION_COMPONENT_
|
||||
#define _TIMER_SESSION_COMPONENT_
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/list.h>
|
||||
#include <os/alarm.h>
|
||||
#include <base/rpc_server.h>
|
||||
#include <timer_session/timer_session.h>
|
||||
|
||||
/* local includes */
|
||||
#include "platform_timer.h"
|
||||
|
||||
|
||||
namespace Timer {
|
||||
|
||||
enum { STACK_SIZE = 32*1024 };
|
||||
|
||||
struct Irq_dispatcher;
|
||||
class Irq_dispatcher_component;
|
||||
class Wake_up_alarm;
|
||||
class Timeout_scheduler;
|
||||
class Session_component;
|
||||
}
|
||||
|
||||
|
||||
struct Timer::Irq_dispatcher
|
||||
{
|
||||
GENODE_RPC(Rpc_do_dispatch, void, do_dispatch);
|
||||
GENODE_RPC_INTERFACE(Rpc_do_dispatch);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Timer interrupt handler
|
||||
*
|
||||
* This class represents a RPC object that gets locally called for each
|
||||
* timer interrupt. It is managed by the same entrypoint as all timer
|
||||
* client components. Because the 'do_dispatch' function is executed in
|
||||
* the same thread context as the dispatch functions of client requests,
|
||||
* we are able to answer those requests from here (by calling the
|
||||
* 'handle()' function of the alarm scheduler).
|
||||
*/
|
||||
class Timer::Irq_dispatcher_component : public Genode::Rpc_object<Irq_dispatcher,
|
||||
Irq_dispatcher_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Alarm_scheduler *_alarm_scheduler;
|
||||
Platform_timer *_platform_timer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Irq_dispatcher_component(Genode::Alarm_scheduler *as,
|
||||
Platform_timer *pt)
|
||||
: _alarm_scheduler(as), _platform_timer(pt) { }
|
||||
|
||||
|
||||
/******************************
|
||||
** Irq_dispatcher interface **
|
||||
******************************/
|
||||
|
||||
void do_dispatch()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Alarm::Time now = _platform_timer->curr_time();
|
||||
Alarm::Time sleep_time;
|
||||
|
||||
/* trigger timeout alarms */
|
||||
_alarm_scheduler->handle(now);
|
||||
|
||||
/* determine duration for next one-shot timer event */
|
||||
Alarm::Time deadline;
|
||||
if (_alarm_scheduler->next_deadline(&deadline))
|
||||
sleep_time = deadline - now;
|
||||
else
|
||||
sleep_time = _platform_timer->max_timeout();
|
||||
|
||||
if (sleep_time == 0)
|
||||
sleep_time = 1;
|
||||
|
||||
_platform_timer->schedule_timeout(sleep_time);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Alarm for answering an oneshot timeout request
|
||||
*/
|
||||
class Timer::Wake_up_alarm : public Genode::Alarm
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Signal_context_capability _sigh;
|
||||
bool _periodic;
|
||||
|
||||
public:
|
||||
|
||||
Wake_up_alarm() : _periodic(false) { }
|
||||
|
||||
void sigh(Genode::Signal_context_capability sigh) { _sigh = sigh; }
|
||||
void periodic(bool periodic) { _periodic = periodic; }
|
||||
bool periodic() { return _periodic; }
|
||||
|
||||
|
||||
/*********************
|
||||
** Alarm interface **
|
||||
*********************/
|
||||
|
||||
/**
|
||||
* Dispatch a wakeup alarm
|
||||
*
|
||||
* This function gets called by the 'Alarm_scheduler' thread.
|
||||
*/
|
||||
bool on_alarm (unsigned cnt) override
|
||||
{
|
||||
Genode::Signal_transmitter(_sigh).submit(cnt);
|
||||
|
||||
return _periodic;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Timer::Timeout_scheduler : public Genode::Alarm_scheduler,
|
||||
Genode::Thread_deprecated<STACK_SIZE>
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Genode::Capability<Irq_dispatcher>
|
||||
Irq_dispatcher_capability;
|
||||
|
||||
Platform_timer *_platform_timer;
|
||||
Irq_dispatcher_component _irq_dispatcher_component;
|
||||
Irq_dispatcher_capability _irq_dispatcher_cap;
|
||||
|
||||
/**
|
||||
* Timer-interrupt thread
|
||||
*
|
||||
* This thread blocks for the timer interrupt. For each occuring
|
||||
* interrupt, it performs an local RPC call to the server
|
||||
* activation, which, in turn, processes the scheduled timeouts and
|
||||
* reprograms the platform timer.
|
||||
*/
|
||||
void entry()
|
||||
{
|
||||
while (true) {
|
||||
|
||||
_platform_timer->wait_for_timeout(this);
|
||||
|
||||
/*
|
||||
* Call timer irq handler to trigger timeout alarms and
|
||||
* reprogram the platform timer.
|
||||
*/
|
||||
_irq_dispatcher_cap.call<Irq_dispatcher::Rpc_do_dispatch>();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Timeout_scheduler(Platform_timer *pt, Genode::Rpc_entrypoint *ep)
|
||||
:
|
||||
Thread_deprecated("timeout_scheduler"),
|
||||
_platform_timer(pt),
|
||||
_irq_dispatcher_component(this, pt),
|
||||
_irq_dispatcher_cap(ep->manage(&_irq_dispatcher_component))
|
||||
{
|
||||
_platform_timer->schedule_timeout(0);
|
||||
start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the '_trigger' function executed by the server activation
|
||||
*/
|
||||
void schedule_timeout(Wake_up_alarm *alarm, Genode::Alarm::Time timeout)
|
||||
{
|
||||
Genode::Alarm::Time now = _platform_timer->curr_time();
|
||||
if (alarm->periodic()) {
|
||||
handle(now); /* update '_now' in 'Alarm_scheduler' */
|
||||
schedule(alarm, timeout);
|
||||
} else schedule_absolute(alarm, now + timeout);
|
||||
|
||||
/* interrupt current 'wait_for_timeout' */
|
||||
if (head_timeout(alarm))
|
||||
_platform_timer->schedule_timeout(0);
|
||||
}
|
||||
|
||||
unsigned long curr_time() const
|
||||
{
|
||||
return _platform_timer->curr_time();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Timer session
|
||||
*/
|
||||
class Timer::Session_component : public Genode::Rpc_object<Session>,
|
||||
public Genode::List<Session_component>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
Timeout_scheduler &_timeout_scheduler;
|
||||
Wake_up_alarm _wake_up_alarm;
|
||||
unsigned long const _initial_time;
|
||||
|
||||
void _trigger(unsigned us, bool periodic)
|
||||
{
|
||||
_wake_up_alarm.periodic(periodic);
|
||||
_timeout_scheduler.schedule_timeout(&_wake_up_alarm, us);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Timeout_scheduler &ts)
|
||||
:
|
||||
_timeout_scheduler(ts),
|
||||
_initial_time(_timeout_scheduler.curr_time())
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~Session_component()
|
||||
{
|
||||
_timeout_scheduler.discard(&_wake_up_alarm);
|
||||
}
|
||||
|
||||
|
||||
/*****************************
|
||||
** Timer session interface **
|
||||
*****************************/
|
||||
|
||||
void trigger_once(unsigned us)
|
||||
{
|
||||
_trigger(us, false);
|
||||
}
|
||||
|
||||
void trigger_periodic(unsigned us)
|
||||
{
|
||||
_trigger(us, true);
|
||||
}
|
||||
|
||||
void sigh(Signal_context_capability sigh)
|
||||
{
|
||||
_wake_up_alarm.sigh(sigh);
|
||||
}
|
||||
|
||||
unsigned long elapsed_ms() const
|
||||
{
|
||||
unsigned long const now = _timeout_scheduler.curr_time();
|
||||
return (now - _initial_time) / 1000;
|
||||
}
|
||||
|
||||
void msleep(unsigned) { /* never called at the server side */ }
|
||||
void usleep(unsigned) { /* never called at the server side */ }
|
||||
};
|
||||
|
||||
#endif
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* \brief Platform timer based on spinning usleep
|
||||
* \author Norman Feske
|
||||
* \date 2009-06-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PLATFORM_TIMER_H_
|
||||
#define _PLATFORM_TIMER_H_
|
||||
|
||||
/* Genode inludes */
|
||||
#include <base/thread.h>
|
||||
#include <os/server.h>
|
||||
|
||||
|
||||
class Platform_timer
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Lock mutable _lock; /* for protecting '_next_timeout_usec' */
|
||||
unsigned long _next_timeout_usec; /* timeout of current sleep */
|
||||
unsigned long _curr_time_usec; /* accumulated sleep time */
|
||||
|
||||
/**
|
||||
* Platform-specific sleep implementation
|
||||
*/
|
||||
void _usleep(unsigned long usecs);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform_timer() : _next_timeout_usec(max_timeout()), _curr_time_usec(0) { }
|
||||
|
||||
/**
|
||||
* Set next relative timeout
|
||||
*/
|
||||
void schedule_timeout(unsigned long timeout_usec)
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_lock);
|
||||
_next_timeout_usec = timeout_usec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return maximum supported timeout in microseconds
|
||||
*/
|
||||
unsigned long max_timeout();
|
||||
|
||||
/**
|
||||
* Get current time in microseconds
|
||||
*/
|
||||
unsigned long curr_time() const;
|
||||
|
||||
/**
|
||||
* Block until the scheduled timeout triggers
|
||||
*/
|
||||
void wait_for_timeout(Genode::Thread *blocking_thread)
|
||||
{
|
||||
enum { SLEEP_GRANULARITY_USEC = 1000UL };
|
||||
|
||||
unsigned long last_time = curr_time();
|
||||
_lock.lock();
|
||||
while (_next_timeout_usec) {
|
||||
_lock.unlock();
|
||||
|
||||
try { _usleep(SLEEP_GRANULARITY_USEC); }
|
||||
catch (Genode::Blocking_canceled) { }
|
||||
|
||||
unsigned long now_time = curr_time();
|
||||
unsigned long sleep_duration = now_time - last_time;
|
||||
last_time = now_time;
|
||||
|
||||
_lock.lock();
|
||||
|
||||
if (_next_timeout_usec >= sleep_duration)
|
||||
_next_timeout_usec -= sleep_duration;
|
||||
else
|
||||
break;
|
||||
}
|
||||
_lock.unlock();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _PLATFORM_TIMER_H_ */
|
@ -1,205 +0,0 @@
|
||||
/*
|
||||
* \brief Platform timer based on the Programmable Interval Timer (PIT)
|
||||
* \author Norman Feske
|
||||
* \date 2009-06-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PLATFORM_TIMER_H_
|
||||
#define _PLATFORM_TIMER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <io_port_session/connection.h>
|
||||
#include <irq_session/connection.h>
|
||||
#include <os/server.h>
|
||||
|
||||
class Platform_timer
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
PIT_TICKS_PER_SECOND = 1193182,
|
||||
PIT_TICKS_PER_MSEC = PIT_TICKS_PER_SECOND/1000,
|
||||
PIT_MAX_COUNT = 65535,
|
||||
PIT_DATA_PORT_0 = 0x40, /* data port for PIT channel 0,
|
||||
connected to the PIC */
|
||||
PIT_CMD_PORT = 0x43, /* PIT command port */
|
||||
|
||||
PIT_MAX_USEC = (PIT_MAX_COUNT*1000)/(PIT_TICKS_PER_MSEC)
|
||||
};
|
||||
|
||||
enum {
|
||||
IRQ_PIT = 0, /* timer interrupt at the PIC */
|
||||
};
|
||||
|
||||
/**
|
||||
* Bit definitions for accessing the PIT command port
|
||||
*/
|
||||
enum {
|
||||
PIT_CMD_SELECT_CHANNEL_0 = 0 << 6,
|
||||
PIT_CMD_ACCESS_LO = 1 << 4,
|
||||
PIT_CMD_ACCESS_LO_HI = 3 << 4,
|
||||
PIT_CMD_MODE_IRQ = 0 << 1,
|
||||
PIT_CMD_MODE_RATE = 2 << 1,
|
||||
|
||||
PIT_CMD_READ_BACK = 3 << 6,
|
||||
PIT_CMD_RB_COUNT = 0 << 5,
|
||||
PIT_CMD_RB_STATUS = 0 << 4,
|
||||
PIT_CMD_RB_CHANNEL_0 = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Bit definitions of the PIT status byte
|
||||
*/
|
||||
enum {
|
||||
PIT_STAT_INT_LINE = 1 << 7,
|
||||
};
|
||||
|
||||
Genode::Io_port_connection _io_port;
|
||||
Genode::Irq_connection _timer_irq;
|
||||
unsigned long mutable _curr_time_usec;
|
||||
Genode::uint16_t mutable _counter_init_value;
|
||||
bool mutable _handled_wrap;
|
||||
Genode::Signal_receiver _irq_rec;
|
||||
Genode::Signal_context _irq_ctx;
|
||||
|
||||
/**
|
||||
* Set PIT counter value
|
||||
*/
|
||||
void _set_counter(Genode::uint16_t value)
|
||||
{
|
||||
_handled_wrap = false;
|
||||
_io_port.outb(PIT_DATA_PORT_0, value & 0xff);
|
||||
_io_port.outb(PIT_DATA_PORT_0, (value >> 8) & 0xff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read current PIT counter value
|
||||
*/
|
||||
Genode::uint16_t _read_counter(bool *wrapped)
|
||||
{
|
||||
/* read-back count and status of counter 0 */
|
||||
_io_port.outb(PIT_CMD_PORT, PIT_CMD_READ_BACK |
|
||||
PIT_CMD_RB_COUNT | PIT_CMD_RB_STATUS | PIT_CMD_RB_CHANNEL_0);
|
||||
|
||||
/* read status byte from latch register */
|
||||
Genode::uint8_t status = _io_port.inb(PIT_DATA_PORT_0);
|
||||
|
||||
/* read low and high bytes from latch register */
|
||||
Genode::uint16_t lo = _io_port.inb(PIT_DATA_PORT_0);
|
||||
Genode::uint16_t hi = _io_port.inb(PIT_DATA_PORT_0);
|
||||
|
||||
*wrapped = status & PIT_STAT_INT_LINE ? true : false;
|
||||
return (hi << 8) | lo;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform_timer()
|
||||
:
|
||||
_io_port(PIT_DATA_PORT_0, PIT_CMD_PORT - PIT_DATA_PORT_0 + 1),
|
||||
_timer_irq(IRQ_PIT),
|
||||
_curr_time_usec(0),
|
||||
_counter_init_value(0),
|
||||
_handled_wrap(false)
|
||||
{
|
||||
/* operate PIT in one-shot mode */
|
||||
_io_port.outb(PIT_CMD_PORT, PIT_CMD_SELECT_CHANNEL_0 |
|
||||
PIT_CMD_ACCESS_LO_HI | PIT_CMD_MODE_IRQ);
|
||||
|
||||
_timer_irq.sigh(_irq_rec.manage(&_irq_ctx));
|
||||
_timer_irq.ack_irq();
|
||||
}
|
||||
|
||||
~Platform_timer() { _irq_rec.dissolve(&_irq_ctx); }
|
||||
|
||||
/**
|
||||
* Return current time-counter value in microseconds
|
||||
*
|
||||
* This function has to be executed regularly,
|
||||
* at least all max_timeout() usecs.
|
||||
*/
|
||||
unsigned long curr_time() const
|
||||
{
|
||||
Genode::uint32_t passed_ticks;
|
||||
|
||||
/*
|
||||
* Read PIT count and status
|
||||
*
|
||||
* Reading the PIT registers via port I/O is a non-const operation.
|
||||
* Since 'curr_time' is declared as const, however, we need to
|
||||
* explicitly override the const-ness of the 'this' pointer.
|
||||
*/
|
||||
bool wrapped;
|
||||
Genode::uint16_t const curr_counter = const_cast<Platform_timer *>(this)->_read_counter(&wrapped);
|
||||
|
||||
/* determine the time since we looked at the counter */
|
||||
if (wrapped && !_handled_wrap) {
|
||||
passed_ticks = _counter_init_value;
|
||||
/* the counter really wrapped around */
|
||||
if (curr_counter)
|
||||
passed_ticks += PIT_MAX_COUNT + 1 - curr_counter;
|
||||
|
||||
_handled_wrap = true;
|
||||
} else {
|
||||
if (_counter_init_value)
|
||||
passed_ticks = _counter_init_value - curr_counter;
|
||||
else
|
||||
passed_ticks = PIT_MAX_COUNT + 1 - curr_counter;
|
||||
}
|
||||
|
||||
_curr_time_usec += (passed_ticks*1000)/PIT_TICKS_PER_MSEC;
|
||||
|
||||
/* use current counter as the reference for the next update */
|
||||
_counter_init_value = curr_counter;
|
||||
|
||||
return _curr_time_usec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return maximum timeout as supported by the platform
|
||||
*/
|
||||
unsigned long max_timeout() { return PIT_MAX_USEC; }
|
||||
|
||||
/**
|
||||
* Schedule next timeout
|
||||
*
|
||||
* \param timeout_usec timeout in microseconds
|
||||
*
|
||||
* The maximum value for 'timeout_ms' is 54924 microseconds. If
|
||||
* specifying a higher timeout, this maximum value will be scheduled.
|
||||
*/
|
||||
void schedule_timeout(unsigned long timeout_usec)
|
||||
{
|
||||
/* limit timer-interrupt rate */
|
||||
enum { MAX_TIMER_IRQS_PER_SECOND = 4*1000 };
|
||||
if (timeout_usec < 1000*1000/MAX_TIMER_IRQS_PER_SECOND)
|
||||
timeout_usec = 1000*1000/MAX_TIMER_IRQS_PER_SECOND;
|
||||
|
||||
if (timeout_usec > max_timeout())
|
||||
timeout_usec = max_timeout();
|
||||
|
||||
_counter_init_value = (PIT_TICKS_PER_MSEC * timeout_usec)/1000;
|
||||
_set_counter(_counter_init_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Block for the next scheduled timeout
|
||||
*/
|
||||
void wait_for_timeout(Genode::Thread *blocking_thread)
|
||||
{
|
||||
_irq_rec.wait_for_signal();
|
||||
_timer_irq.ack_irq();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _PLATFORM_TIMER_H_ */
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Timer service
|
||||
* \brief Provides the Timer service to multiple clients
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2006-08-15
|
||||
*/
|
||||
|
||||
@ -12,45 +13,35 @@
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/heap.h>
|
||||
#include <cap_session/connection.h>
|
||||
#include <os/server.h>
|
||||
#include <base/component.h>
|
||||
|
||||
/* local includes */
|
||||
#include "timer_root.h"
|
||||
#include <root_component.h>
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Timer;
|
||||
|
||||
|
||||
struct Main
|
||||
class Main
|
||||
{
|
||||
Server::Entrypoint &ep;
|
||||
Sliced_heap sliced_heap;
|
||||
Timer::Root_component root;
|
||||
private:
|
||||
|
||||
Main(Server::Entrypoint &ep)
|
||||
:
|
||||
ep(ep),
|
||||
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
|
||||
root(ep, &sliced_heap, 0)
|
||||
{
|
||||
/*
|
||||
* Announce timer service at our parent.
|
||||
*/
|
||||
env()->parent()->announce(ep.manage(root));
|
||||
}
|
||||
Sliced_heap _sliced_heap;
|
||||
Timer::Root_component _root;
|
||||
|
||||
public:
|
||||
|
||||
Main(Env &env) : _sliced_heap(env.ram(), env.rm()),
|
||||
_root(env.ep(), _sliced_heap)
|
||||
{
|
||||
env.parent().announce(env.ep().manage(_root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/************
|
||||
** Server **
|
||||
************/
|
||||
/***************
|
||||
** Component **
|
||||
***************/
|
||||
|
||||
namespace Server {
|
||||
char const *name() { return "timer_drv_ep"; }
|
||||
size_t stack_size() { return 2048*sizeof(long); }
|
||||
void construct(Entrypoint &ep) { static Main server(ep); }
|
||||
}
|
||||
size_t Component::stack_size() { return 2 * 1024 * sizeof(addr_t); }
|
||||
void Component::construct(Env &env) { static Main main(env); }
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
* \brief Fiasco-specific sleep implementation
|
||||
* \brief Time source that uses sleeping by the means of the kernel
|
||||
* \author Christian Helmuth
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2006-08-30
|
||||
*/
|
||||
|
||||
@ -14,7 +15,6 @@
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/misc_math.h>
|
||||
#include <base/printf.h>
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
|
||||
/* Fiasco includes */
|
||||
@ -36,9 +36,10 @@ namespace Fiasco {
|
||||
#endif /* L4_SYS_KIP_H__ */
|
||||
|
||||
/* local includes */
|
||||
#include "timer_session_component.h"
|
||||
#include <time_source.h>
|
||||
|
||||
using namespace Fiasco;
|
||||
using Microseconds = Genode::Time_source::Microseconds;
|
||||
|
||||
|
||||
static l4_timeout_s mus_to_timeout(unsigned long mus)
|
||||
@ -50,42 +51,36 @@ static l4_timeout_s mus_to_timeout(unsigned long mus)
|
||||
|
||||
long e = Genode::log2(mus) - 7;
|
||||
unsigned long m;
|
||||
|
||||
if (e < 0) e = 0;
|
||||
m = mus / (1UL << e);
|
||||
|
||||
/* check corner case */
|
||||
if ((e > 31 ) || (m > 1023)) {
|
||||
PWRN("invalid timeout %ld, using max. values\n", mus);
|
||||
Genode::warning("invalid timeout ", mus, ", using max. values");
|
||||
e = 0;
|
||||
m = 1023;
|
||||
}
|
||||
|
||||
return l4_timeout_rel(m, e);
|
||||
}
|
||||
|
||||
|
||||
unsigned long Platform_timer::max_timeout()
|
||||
Microseconds Timer::Time_source::max_timeout() const
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_lock);
|
||||
|
||||
return 1000*1000*100;
|
||||
return Microseconds(1000 * 1000 * 100);
|
||||
}
|
||||
|
||||
|
||||
unsigned long Platform_timer::curr_time() const
|
||||
Microseconds Timer::Time_source::curr_time() const
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_lock);
|
||||
|
||||
static Genode::Attached_rom_dataspace kip_ds("l4v2_kip");
|
||||
static Genode::Attached_rom_dataspace kip_ds("l4v2_kip");
|
||||
static Fiasco::l4_kernel_info_t * const kip =
|
||||
kip_ds.local_addr<Fiasco::l4_kernel_info_t>();
|
||||
|
||||
return kip->clock;
|
||||
return Microseconds(kip->clock);
|
||||
}
|
||||
|
||||
|
||||
void Platform_timer::_usleep(unsigned long usecs)
|
||||
{
|
||||
l4_ipc_sleep(l4_timeout(L4_IPC_TIMEOUT_NEVER, mus_to_timeout(usecs)));
|
||||
}
|
||||
void Timer::Time_source::_usleep(unsigned long usecs) {
|
||||
l4_ipc_sleep(l4_timeout(L4_IPC_TIMEOUT_NEVER, mus_to_timeout(usecs))); }
|
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* \brief Platform timer specific for base-hw
|
||||
* \author Martin Stein
|
||||
* \date 2012-05-03
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _OS__SRC__DRIVERS__TIMER__HW__PLATFORM_TIMER_H_
|
||||
#define _OS__SRC__DRIVERS__TIMER__HW__PLATFORM_TIMER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/signal.h>
|
||||
#include <os/server.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/interface.h>
|
||||
|
||||
/**
|
||||
* Platform timer specific for base-hw
|
||||
*/
|
||||
class Platform_timer
|
||||
{
|
||||
private:
|
||||
|
||||
using time_t = Kernel::time_t;
|
||||
|
||||
Genode::Signal_receiver _sigrec;
|
||||
Genode::Signal_context _sigctx;
|
||||
Kernel::capid_t const _sigid;
|
||||
unsigned long mutable _curr_time_us;
|
||||
Genode::Lock mutable _curr_time_us_lock;
|
||||
unsigned long mutable _last_timeout_age_us;
|
||||
time_t const _max_timeout_us;
|
||||
|
||||
/**
|
||||
* Return kernel capability selector of Genode capability
|
||||
*
|
||||
* This function is normally framework-internal and defined in
|
||||
* 'base/internal/capability_space.h'.
|
||||
*/
|
||||
static inline Kernel::capid_t _capid(Genode::Native_capability const &cap)
|
||||
{
|
||||
Genode::addr_t const index = (Genode::addr_t)cap.data();
|
||||
return index;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Platform_timer()
|
||||
:
|
||||
_sigid(_capid(_sigrec.manage(&_sigctx))),
|
||||
_curr_time_us(0), _last_timeout_age_us(0),
|
||||
_max_timeout_us(Kernel::timeout_max_us())
|
||||
{
|
||||
Genode::log("maximum timeout ", _max_timeout_us, " us");
|
||||
if (max_timeout() < min_timeout()) {
|
||||
Genode::error("minimum timeout greater then maximum timeout");
|
||||
throw Genode::Exception();
|
||||
}
|
||||
}
|
||||
|
||||
~Platform_timer() { _sigrec.dissolve(&_sigctx); }
|
||||
|
||||
/**
|
||||
* Refresh and return time in microseconds
|
||||
*
|
||||
* This function has to be executed regulary, at least all
|
||||
* max_timeout() us.
|
||||
*/
|
||||
unsigned long curr_time() const
|
||||
{
|
||||
Genode::Lock::Guard lock(_curr_time_us_lock);
|
||||
time_t const timeout_age_us = Kernel::timeout_age_us();
|
||||
if (timeout_age_us > _last_timeout_age_us) {
|
||||
|
||||
/* increment time by the difference since the last update */
|
||||
_curr_time_us += timeout_age_us - _last_timeout_age_us;
|
||||
_last_timeout_age_us = timeout_age_us;
|
||||
}
|
||||
return _curr_time_us;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return maximum timeout in microseconds
|
||||
*/
|
||||
time_t max_timeout() const { return _max_timeout_us; }
|
||||
|
||||
/**
|
||||
* Return minimum timeout in microseconds
|
||||
*/
|
||||
static time_t min_timeout() { return 1000; }
|
||||
|
||||
/**
|
||||
* Schedule next timeout, bad timeouts are adapted
|
||||
*
|
||||
* \param timeout_us Timeout in microseconds
|
||||
*/
|
||||
void schedule_timeout(time_t timeout_us)
|
||||
{
|
||||
Genode::Lock::Guard lock(_curr_time_us_lock);
|
||||
if (timeout_us < min_timeout()) { timeout_us = min_timeout(); }
|
||||
if (timeout_us > max_timeout()) { timeout_us = max_timeout(); }
|
||||
|
||||
/*
|
||||
* Once the timer runs, one can wait for its signal and update our
|
||||
* timeout counter through 'curr_time()' (We rely on the fact that
|
||||
* this is done at least one time in every max-timeout period)
|
||||
*/
|
||||
_last_timeout_age_us = 0;
|
||||
Kernel::timeout(timeout_us, _sigid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Await the lastly scheduled timeout
|
||||
*/
|
||||
void wait_for_timeout(Genode::Thread *) { _sigrec.wait_for_signal(); }
|
||||
};
|
||||
|
||||
#endif /* _OS__SRC__DRIVERS__TIMER__HW__PLATFORM_TIMER_H_ */
|
69
repos/os/src/drivers/timer/spec/hw/time_source.cc
Normal file
69
repos/os/src/drivers/timer/spec/hw/time_source.cc
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* \brief Time source that uses the timeout syscalls of the HW kernel
|
||||
* \author Martin Stein
|
||||
* \date 2012-05-03
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/log.h>
|
||||
#include <base/signal.h>
|
||||
#include <base/entrypoint.h>
|
||||
|
||||
/* local includes */
|
||||
#include <time_source.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/interface.h>
|
||||
|
||||
using namespace Genode;
|
||||
using Microseconds = Genode::Time_source::Microseconds;
|
||||
|
||||
enum { MIN_TIMEOUT_US = 1000 };
|
||||
|
||||
|
||||
Timer::Time_source::Time_source(Entrypoint &ep)
|
||||
:
|
||||
Signalled_time_source(ep),
|
||||
_max_timeout_us(Kernel::timeout_max_us())
|
||||
{
|
||||
if (_max_timeout_us < MIN_TIMEOUT_US) {
|
||||
error("minimum timeout greater then maximum timeout");
|
||||
throw Genode::Exception();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Timer::Time_source::schedule_timeout(Microseconds duration,
|
||||
Timeout_handler &handler)
|
||||
{
|
||||
unsigned long duration_us = duration.value;
|
||||
if (duration_us < MIN_TIMEOUT_US) {
|
||||
duration_us = MIN_TIMEOUT_US; }
|
||||
|
||||
if (duration_us > max_timeout().value) {
|
||||
duration_us = max_timeout().value; }
|
||||
|
||||
_handler = &handler;
|
||||
_last_timeout_age_us = 0;
|
||||
Kernel::timeout(duration_us, (addr_t)_signal_handler.data());
|
||||
}
|
||||
|
||||
|
||||
Microseconds Timer::Time_source::curr_time() const
|
||||
{
|
||||
unsigned long const timeout_age_us = Kernel::timeout_age_us();
|
||||
if (timeout_age_us > _last_timeout_age_us) {
|
||||
|
||||
/* increment time by the difference since the last update */
|
||||
_curr_time_us += timeout_age_us - _last_timeout_age_us;
|
||||
_last_timeout_age_us = timeout_age_us;
|
||||
}
|
||||
return Microseconds(_curr_time_us);
|
||||
}
|
46
repos/os/src/drivers/timer/spec/hw/time_source.h
Normal file
46
repos/os/src/drivers/timer/spec/hw/time_source.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* \brief Time source that uses the timeout syscalls of the HW kernel
|
||||
* \author Martin Stein
|
||||
* \date 2012-05-03
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TIME_SOURCE_H_
|
||||
#define _TIME_SOURCE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <signalled_time_source.h>
|
||||
|
||||
namespace Timer { class Time_source; }
|
||||
|
||||
|
||||
class Timer::Time_source : public Genode::Signalled_time_source
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned long mutable _curr_time_us = 0;
|
||||
unsigned long mutable _last_timeout_age_us = 0;
|
||||
unsigned long const _max_timeout_us;
|
||||
|
||||
public:
|
||||
|
||||
Time_source(Genode::Entrypoint &ep);
|
||||
|
||||
|
||||
/*************************
|
||||
** Genode::Time_source **
|
||||
*************************/
|
||||
|
||||
Microseconds curr_time() const override;
|
||||
void schedule_timeout(Microseconds duration, Timeout_handler &handler) override;
|
||||
Microseconds max_timeout() const override {
|
||||
return Microseconds(_max_timeout_us); };
|
||||
};
|
||||
|
||||
#endif /* _TIME_SOURCE_H_ */
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* \brief Linux-specific sleep implementation
|
||||
* \author Norman Feske
|
||||
* \date 2006-08-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Linux syscall bindings */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
/* local includes */
|
||||
#include "timer_session_component.h"
|
||||
|
||||
/* Linux includes */
|
||||
#include <linux_syscalls.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
inline int lx_gettimeofday(struct timeval *tv, struct timeval *tz)
|
||||
{
|
||||
return lx_syscall(SYS_gettimeofday, tv, tz);
|
||||
}
|
||||
|
||||
|
||||
unsigned long Platform_timer::max_timeout()
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_lock);
|
||||
return 1000*1000;
|
||||
}
|
||||
|
||||
|
||||
unsigned long Platform_timer::curr_time() const
|
||||
{
|
||||
struct timeval tv;
|
||||
lx_gettimeofday(&tv, 0);
|
||||
return tv.tv_sec*1000*1000 + tv.tv_usec;
|
||||
}
|
||||
|
||||
|
||||
void Platform_timer::_usleep(unsigned long usecs)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = usecs / (1000*1000);
|
||||
ts.tv_nsec = (usecs % (1000*1000)) * 1000;
|
||||
|
||||
if (lx_nanosleep(&ts, &ts) != 0)
|
||||
throw Genode::Blocking_canceled();
|
||||
}
|
53
repos/os/src/drivers/timer/spec/linux/time_source.cc
Normal file
53
repos/os/src/drivers/timer/spec/linux/time_source.cc
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* \brief Time source that uses sleeping by the means of the kernel
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2006-08-15
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Linux includes */
|
||||
#include <linux_syscalls.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
/* local includes */
|
||||
#include <time_source.h>
|
||||
|
||||
using namespace Genode;
|
||||
using Microseconds = Genode::Time_source::Microseconds;
|
||||
|
||||
|
||||
inline int lx_gettimeofday(struct timeval *tv, struct timeval *tz) {
|
||||
return lx_syscall(SYS_gettimeofday, tv, tz); }
|
||||
|
||||
|
||||
Microseconds Timer::Time_source::max_timeout() const
|
||||
{
|
||||
Lock::Guard lock_guard(_lock);
|
||||
return Microseconds(1000 * 1000);
|
||||
}
|
||||
|
||||
|
||||
Microseconds Timer::Time_source::curr_time() const
|
||||
{
|
||||
struct timeval tv;
|
||||
lx_gettimeofday(&tv, 0);
|
||||
return Microseconds(tv.tv_sec * 1000 * 1000 + tv.tv_usec);
|
||||
}
|
||||
|
||||
|
||||
void Timer::Time_source::_usleep(unsigned long us)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = us / (1000 * 1000);
|
||||
ts.tv_nsec = (us % (1000 * 1000)) * 1000;
|
||||
|
||||
if (lx_nanosleep(&ts, &ts) != 0)
|
||||
throw Blocking_canceled();
|
||||
}
|
@ -1,132 +0,0 @@
|
||||
/*
|
||||
* \brief Platform timer using Nova timed semaphore down
|
||||
* \author Alexander Boettcher
|
||||
* \date 2014-06-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PLATFORM_TIMER_H_
|
||||
#define _PLATFORM_TIMER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
#include <os/server.h>
|
||||
#include <trace/timestamp.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/native_thread.h>
|
||||
|
||||
class Platform_timer
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::addr_t _sem;
|
||||
unsigned long _timeout;
|
||||
Genode::Trace::Timestamp _tsc_start;
|
||||
unsigned long _tsc_khz;
|
||||
|
||||
/* 1 / ((us / (1000 * 1000)) * (tsc_khz * 1000)) */
|
||||
enum { TSC_FACTOR = 1000ULL };
|
||||
|
||||
/**
|
||||
* Convenience function to calculate time in us value out of tsc
|
||||
*/
|
||||
inline unsigned long _time_in_us(unsigned long long tsc,
|
||||
bool sub_tsc_start = true) const
|
||||
{
|
||||
if (sub_tsc_start)
|
||||
return (tsc - _tsc_start) / (_tsc_khz / TSC_FACTOR);
|
||||
|
||||
return (tsc) / (_tsc_khz / TSC_FACTOR);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Platform_timer()
|
||||
:
|
||||
_sem(~0UL), _timeout(0),
|
||||
_tsc_start(Genode::Trace::timestamp())
|
||||
{
|
||||
/* read out the tsc frequenzy once */
|
||||
Genode::Attached_rom_dataspace _ds("hypervisor_info_page");
|
||||
Nova::Hip * const hip = _ds.local_addr<Nova::Hip>();
|
||||
_tsc_khz = hip->tsc_freq;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return current time-counter value in microseconds
|
||||
*/
|
||||
unsigned long curr_time() const
|
||||
{
|
||||
return _time_in_us(Genode::Trace::timestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return maximum timeout as supported by the platform
|
||||
*/
|
||||
unsigned long max_timeout() { return _time_in_us(~0UL); }
|
||||
|
||||
/**
|
||||
* Schedule next timeout
|
||||
*
|
||||
* \param timeout_usec timeout in microseconds
|
||||
*/
|
||||
void schedule_timeout(unsigned long timeout_usec)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* check whether to cancel last timeout */
|
||||
if (timeout_usec == 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 = timeout_usec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Block for the next scheduled timeout
|
||||
*/
|
||||
void wait_for_timeout(Genode::Thread *blocking_thread)
|
||||
{
|
||||
using namespace Genode;
|
||||
using namespace Nova;
|
||||
|
||||
if (_sem == ~0UL)
|
||||
_sem = blocking_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;
|
||||
|
||||
if (_timeout == max_timeout()) {
|
||||
/* tsc_absolute == 0 means blocking without timeout */
|
||||
Genode::uint8_t res = sm_ctrl(sem, SEMAPHORE_DOWN, 0);
|
||||
if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT)
|
||||
nova_die();
|
||||
return;
|
||||
}
|
||||
|
||||
/* block until timeout fires or it gets canceled */
|
||||
unsigned long long tsc_absolute = now + us_64 * (_tsc_khz / TSC_FACTOR);
|
||||
Genode::uint8_t res = sm_ctrl(sem, SEMAPHORE_DOWN, tsc_absolute);
|
||||
if (res != Nova::NOVA_OK && res != Nova::NOVA_TIMEOUT)
|
||||
nova_die();
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _PLATFORM_TIMER_H_ */
|
81
repos/os/src/drivers/timer/spec/nova/time_source.cc
Normal file
81
repos/os/src/drivers/timer/spec/nova/time_source.cc
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* \brief Time source using Nova timed semaphore down
|
||||
* \author Alexander Boettcher
|
||||
* \author Martin Stein
|
||||
* \date 2014-06-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/native_thread.h>
|
||||
|
||||
/* local includes */
|
||||
#include <time_source.h>
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Nova;
|
||||
using Microseconds = Genode::Time_source::Microseconds;
|
||||
|
||||
|
||||
Timer::Time_source::Time_source(Entrypoint &ep) : Threaded_time_source(ep)
|
||||
{
|
||||
/* read out the tsc frequenzy once */
|
||||
Attached_rom_dataspace _ds("hypervisor_info_page");
|
||||
Nova::Hip * const hip = _ds.local_addr<Nova::Hip>();
|
||||
_tsc_khz = hip->tsc_freq;
|
||||
start();
|
||||
}
|
||||
|
||||
|
||||
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(); }
|
||||
}
|
||||
}
|
71
repos/os/src/drivers/timer/spec/nova/time_source.h
Normal file
71
repos/os/src/drivers/timer/spec/nova/time_source.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* \brief Time source using Nova timed semaphore down
|
||||
* \author Alexander Boettcher
|
||||
* \author Martin Stein
|
||||
* \date 2014-06-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TIME_SOURCE_H_
|
||||
#define _TIME_SOURCE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <trace/timestamp.h>
|
||||
|
||||
/* local includes */
|
||||
#include <threaded_time_source.h>
|
||||
|
||||
namespace Timer { class Time_source; }
|
||||
|
||||
|
||||
class Timer::Time_source : public Threaded_time_source
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::addr_t _sem = ~0UL;
|
||||
unsigned long _timeout_us = 0;
|
||||
Genode::Trace::Timestamp _tsc_start = Genode::Trace::timestamp();
|
||||
unsigned long _tsc_khz;
|
||||
|
||||
/* 1 / ((us / (1000 * 1000)) * (tsc_khz * 1000)) */
|
||||
enum { TSC_FACTOR = 1000ULL };
|
||||
|
||||
inline Microseconds _tsc_to_us(unsigned long long tsc,
|
||||
bool sub_tsc_start = true) const
|
||||
{
|
||||
if (sub_tsc_start) {
|
||||
return Microseconds((tsc - _tsc_start) /
|
||||
(_tsc_khz / TSC_FACTOR));
|
||||
}
|
||||
return Microseconds((tsc) / (_tsc_khz / TSC_FACTOR));
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
** Threaded_time_source **
|
||||
**************************/
|
||||
|
||||
void _wait_for_irq();
|
||||
|
||||
public:
|
||||
|
||||
Time_source(Genode::Entrypoint &ep);
|
||||
|
||||
|
||||
/*************************
|
||||
** Genode::Time_source **
|
||||
*************************/
|
||||
|
||||
Microseconds max_timeout() const override { return _tsc_to_us(~0UL); }
|
||||
void schedule_timeout(Microseconds duration, Timeout_handler &handler) override;
|
||||
Microseconds curr_time() const override {
|
||||
return _tsc_to_us(Genode::Trace::timestamp()); }
|
||||
};
|
||||
|
||||
#endif /* _TIME_SOURCE_H_ */
|
52
repos/os/src/drivers/timer/spec/periodic/time_source.cc
Normal file
52
repos/os/src/drivers/timer/spec/periodic/time_source.cc
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* \brief Time source that uses sleeping by the means of the kernel
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2009-06-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <time_source.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
void Timer::Time_source::schedule_timeout(Microseconds duration,
|
||||
Timeout_handler &handler)
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_lock);
|
||||
Threaded_time_source::handler(handler);
|
||||
_next_timeout_us = duration.value;
|
||||
}
|
||||
|
||||
|
||||
void Timer::Time_source::_wait_for_irq()
|
||||
{
|
||||
enum { SLEEP_GRANULARITY_US = 1000UL };
|
||||
unsigned long last_time_us = curr_time().value;
|
||||
_lock.lock();
|
||||
while (_next_timeout_us > 0) {
|
||||
_lock.unlock();
|
||||
|
||||
try { _usleep(SLEEP_GRANULARITY_US); }
|
||||
catch (Blocking_canceled) { }
|
||||
|
||||
unsigned long curr_time_us = curr_time().value;
|
||||
unsigned long sleep_duration_us = curr_time_us - last_time_us;
|
||||
last_time_us = curr_time_us;
|
||||
|
||||
_lock.lock();
|
||||
if (_next_timeout_us >= sleep_duration_us)
|
||||
_next_timeout_us -= sleep_duration_us;
|
||||
else
|
||||
break;
|
||||
}
|
||||
_lock.unlock();
|
||||
}
|
56
repos/os/src/drivers/timer/spec/periodic/time_source.h
Normal file
56
repos/os/src/drivers/timer/spec/periodic/time_source.h
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* \brief Time source that uses sleeping by the means of the kernel
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2009-06-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TIME_SOURCE_H_
|
||||
#define _TIME_SOURCE_H_
|
||||
|
||||
/* local includes */
|
||||
#include <threaded_time_source.h>
|
||||
|
||||
namespace Timer { class Time_source; }
|
||||
|
||||
|
||||
class Timer::Time_source : public Threaded_time_source
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Lock mutable _lock;
|
||||
unsigned long _curr_time_us = 0;
|
||||
unsigned long _next_timeout_us = max_timeout().value;
|
||||
|
||||
void _usleep(unsigned long us);
|
||||
|
||||
|
||||
/**************************
|
||||
** Threaded_time_source **
|
||||
**************************/
|
||||
|
||||
void _wait_for_irq();
|
||||
|
||||
public:
|
||||
|
||||
Time_source(Genode::Entrypoint &ep) : Threaded_time_source(ep) {
|
||||
start(); }
|
||||
|
||||
|
||||
/*************************
|
||||
** Genode::Time_source **
|
||||
*************************/
|
||||
|
||||
Microseconds curr_time() const override;
|
||||
Microseconds max_timeout() const override;
|
||||
void schedule_timeout(Microseconds duration, Timeout_handler &handler) override;
|
||||
};
|
||||
|
||||
#endif /* _TIME_SOURCE_H_ */
|
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* \brief Pistachio-specific sleep implementation
|
||||
* \brief Time source that uses sleeping by the means of the kernel
|
||||
* \author Julian Stecklina
|
||||
* \author Martin Stein
|
||||
* \date 2008-03-19
|
||||
*/
|
||||
|
||||
@ -20,34 +21,37 @@ namespace Pistachio {
|
||||
}
|
||||
|
||||
/* local includes */
|
||||
#include "timer_session_component.h"
|
||||
#include <time_source.h>
|
||||
|
||||
using namespace Genode;
|
||||
using Microseconds = Genode::Time_source::Microseconds;
|
||||
|
||||
|
||||
unsigned long Platform_timer::max_timeout()
|
||||
Microseconds Timer::Time_source::max_timeout() const
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_lock);
|
||||
return 1000*1000;
|
||||
Lock::Guard lock_guard(_lock);
|
||||
return Microseconds(1000 * 1000);
|
||||
}
|
||||
|
||||
|
||||
unsigned long Platform_timer::curr_time() const
|
||||
Microseconds Timer::Time_source::curr_time() const
|
||||
{
|
||||
Genode::Lock::Guard lock_guard(_lock);
|
||||
return _curr_time_usec;
|
||||
Lock::Guard lock_guard(_lock);
|
||||
return Microseconds(_curr_time_us);
|
||||
}
|
||||
|
||||
|
||||
void Platform_timer::_usleep(unsigned long usecs)
|
||||
void Timer::Time_source::_usleep(unsigned long us)
|
||||
{
|
||||
using namespace Pistachio;
|
||||
|
||||
enum { MAGIC_USER_DEFINED_HANDLE = 13 };
|
||||
L4_Set_UserDefinedHandle(MAGIC_USER_DEFINED_HANDLE);
|
||||
|
||||
L4_Sleep(L4_TimePeriod(usecs));
|
||||
_curr_time_usec += usecs;
|
||||
L4_Sleep(L4_TimePeriod(us));
|
||||
_curr_time_us += us;
|
||||
|
||||
/* check if sleep was canceled */
|
||||
if (L4_UserDefinedHandle() != MAGIC_USER_DEFINED_HANDLE)
|
||||
throw Genode::Blocking_canceled();
|
||||
throw Blocking_canceled();
|
||||
}
|
118
repos/os/src/drivers/timer/spec/pit/time_source.cc
Normal file
118
repos/os/src/drivers/timer/spec/pit/time_source.cc
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* \brief Time source that uses the Programmable Interval Timer (PIT)
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2009-06-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* local includes */
|
||||
#include <time_source.h>
|
||||
|
||||
using namespace Genode;
|
||||
using Microseconds = Genode::Time_source::Microseconds;
|
||||
|
||||
|
||||
void Timer::Time_source::_set_counter(uint16_t value)
|
||||
{
|
||||
_handled_wrap = false;
|
||||
_io_port.outb(PIT_DATA_PORT_0, value & 0xff);
|
||||
_io_port.outb(PIT_DATA_PORT_0, (value >> 8) & 0xff);
|
||||
}
|
||||
|
||||
|
||||
uint16_t Timer::Time_source::_read_counter(bool *wrapped)
|
||||
{
|
||||
/* read-back count and status of counter 0 */
|
||||
_io_port.outb(PIT_CMD_PORT, PIT_CMD_READ_BACK |
|
||||
PIT_CMD_RB_COUNT |
|
||||
PIT_CMD_RB_STATUS |
|
||||
PIT_CMD_RB_CHANNEL_0);
|
||||
|
||||
/* read status byte from latch register */
|
||||
uint8_t status = _io_port.inb(PIT_DATA_PORT_0);
|
||||
|
||||
/* read low and high bytes from latch register */
|
||||
uint16_t lo = _io_port.inb(PIT_DATA_PORT_0);
|
||||
uint16_t hi = _io_port.inb(PIT_DATA_PORT_0);
|
||||
|
||||
*wrapped = status & PIT_STAT_INT_LINE ? true : false;
|
||||
return (hi << 8) | lo;
|
||||
}
|
||||
|
||||
|
||||
void Timer::Time_source::schedule_timeout(Microseconds duration,
|
||||
Timeout_handler &handler)
|
||||
{
|
||||
_handler = &handler;
|
||||
_timer_irq.ack_irq();
|
||||
unsigned long duration_us = duration.value;
|
||||
|
||||
/* limit timer-interrupt rate */
|
||||
enum { MAX_TIMER_IRQS_PER_SECOND = 4*1000 };
|
||||
if (duration_us < 1000 * 1000 / MAX_TIMER_IRQS_PER_SECOND)
|
||||
duration_us = 1000 * 1000 / MAX_TIMER_IRQS_PER_SECOND;
|
||||
|
||||
if (duration_us > max_timeout().value)
|
||||
duration_us = max_timeout().value;
|
||||
|
||||
_counter_init_value = (PIT_TICKS_PER_MSEC * duration_us) / 1000;
|
||||
_set_counter(_counter_init_value);
|
||||
}
|
||||
|
||||
|
||||
Microseconds Timer::Time_source::curr_time() const
|
||||
{
|
||||
uint32_t passed_ticks;
|
||||
|
||||
/*
|
||||
* Read PIT count and status
|
||||
*
|
||||
* Reading the PIT registers via port I/O is a non-const operation.
|
||||
* Since 'curr_time' is declared as const, however, we need to
|
||||
* explicitly override the const-ness of the 'this' pointer.
|
||||
*/
|
||||
bool wrapped;
|
||||
uint16_t const curr_counter =
|
||||
const_cast<Time_source *>(this)->_read_counter(&wrapped);
|
||||
|
||||
/* determine the time since we looked at the counter */
|
||||
if (wrapped && !_handled_wrap) {
|
||||
passed_ticks = _counter_init_value;
|
||||
/* the counter really wrapped around */
|
||||
if (curr_counter)
|
||||
passed_ticks += PIT_MAX_COUNT + 1 - curr_counter;
|
||||
|
||||
_handled_wrap = true;
|
||||
} else {
|
||||
if (_counter_init_value)
|
||||
passed_ticks = _counter_init_value - curr_counter;
|
||||
else
|
||||
passed_ticks = PIT_MAX_COUNT + 1 - curr_counter;
|
||||
}
|
||||
_curr_time_us += (passed_ticks*1000)/PIT_TICKS_PER_MSEC;
|
||||
|
||||
/* use current counter as the reference for the next update */
|
||||
_counter_init_value = curr_counter;
|
||||
return Microseconds(_curr_time_us);
|
||||
}
|
||||
|
||||
|
||||
Timer::Time_source::Time_source(Entrypoint &ep)
|
||||
:
|
||||
Signalled_time_source(ep),
|
||||
_io_port(PIT_DATA_PORT_0, PIT_CMD_PORT - PIT_DATA_PORT_0 + 1),
|
||||
_timer_irq(IRQ_PIT)
|
||||
{
|
||||
/* operate PIT in one-shot mode */
|
||||
_io_port.outb(PIT_CMD_PORT, PIT_CMD_SELECT_CHANNEL_0 |
|
||||
PIT_CMD_ACCESS_LO_HI | PIT_CMD_MODE_IRQ);
|
||||
|
||||
_timer_irq.sigh(_signal_handler);
|
||||
}
|
90
repos/os/src/drivers/timer/spec/pit/time_source.h
Normal file
90
repos/os/src/drivers/timer/spec/pit/time_source.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* \brief Time source that uses the Programmable Interval Timer (PIT)
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2009-06-16
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2009-2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _TIME_SOURCE_H_
|
||||
#define _TIME_SOURCE_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <io_port_session/connection.h>
|
||||
#include <irq_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <signalled_time_source.h>
|
||||
|
||||
namespace Timer { class Time_source; }
|
||||
|
||||
|
||||
class Timer::Time_source : public Genode::Signalled_time_source
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
enum {
|
||||
PIT_TICKS_PER_SECOND = 1193182,
|
||||
PIT_TICKS_PER_MSEC = PIT_TICKS_PER_SECOND/1000,
|
||||
PIT_MAX_COUNT = 65535,
|
||||
PIT_DATA_PORT_0 = 0x40, /* data port for PIT channel 0,
|
||||
connected to the PIC */
|
||||
PIT_CMD_PORT = 0x43, /* PIT command port */
|
||||
|
||||
PIT_MAX_USEC = (PIT_MAX_COUNT*1000)/(PIT_TICKS_PER_MSEC),
|
||||
|
||||
IRQ_PIT = 0, /* timer interrupt at the PIC */
|
||||
|
||||
/*
|
||||
* Bit definitions for accessing the PIT command port
|
||||
*/
|
||||
PIT_CMD_SELECT_CHANNEL_0 = 0 << 6,
|
||||
PIT_CMD_ACCESS_LO = 1 << 4,
|
||||
PIT_CMD_ACCESS_LO_HI = 3 << 4,
|
||||
PIT_CMD_MODE_IRQ = 0 << 1,
|
||||
PIT_CMD_MODE_RATE = 2 << 1,
|
||||
|
||||
PIT_CMD_READ_BACK = 3 << 6,
|
||||
PIT_CMD_RB_COUNT = 0 << 5,
|
||||
PIT_CMD_RB_STATUS = 0 << 4,
|
||||
PIT_CMD_RB_CHANNEL_0 = 1 << 1,
|
||||
|
||||
/*
|
||||
* Bit definitions of the PIT status byte
|
||||
*/
|
||||
PIT_STAT_INT_LINE = 1 << 7,
|
||||
};
|
||||
|
||||
Genode::Io_port_connection _io_port;
|
||||
Genode::Irq_connection _timer_irq;
|
||||
unsigned long mutable _curr_time_us = 0;
|
||||
Genode::uint16_t mutable _counter_init_value = 0;
|
||||
bool mutable _handled_wrap = false;
|
||||
|
||||
void _set_counter(Genode::uint16_t value);
|
||||
|
||||
Genode::uint16_t _read_counter(bool *wrapped);
|
||||
|
||||
public:
|
||||
|
||||
Time_source(Genode::Entrypoint &ep);
|
||||
|
||||
|
||||
/*************************
|
||||
** Genode::Time_source **
|
||||
*************************/
|
||||
|
||||
Microseconds curr_time() const override;
|
||||
void schedule_timeout(Microseconds duration, Timeout_handler &handler) override;
|
||||
Microseconds max_timeout() const override {
|
||||
return Microseconds(PIT_MAX_USEC); }
|
||||
};
|
||||
|
||||
#endif /* _TIME_SOURCE_H_ */
|
Loading…
x
Reference in New Issue
Block a user