mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-17 14:48:20 +00:00
committed by
Christian Helmuth
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
|
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
|
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
|
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/hw
|
||||||
|
|
||||||
|
SRC_CC += spec/hw/time_source.cc
|
||||||
|
|
||||||
include $(REP_DIR)/lib/mk/timer.inc
|
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
|
LIBS += syscall
|
||||||
|
|
||||||
SRC_CC += platform_timer.cc
|
include $(REP_DIR)/lib/mk/timer.inc
|
||||||
vpath platform_timer.cc $(REP_DIR)/src/drivers/timer/spec/linux
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
include $(REP_DIR)/lib/mk/timer.inc
|
|
||||||
|
|
||||||
INC_DIR += $(REP_DIR)/src/drivers/timer/spec/nova
|
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
|
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
|
SRC_CC += main.cc
|
||||||
LIBS += base alarm server
|
|
||||||
|
LIBS += base timeout
|
||||||
|
|
||||||
INC_DIR += $(REP_DIR)/src/drivers/timer/include
|
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 Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2006-08-15
|
* \date 2006-08-15
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -12,45 +13,35 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/env.h>
|
|
||||||
#include <base/sleep.h>
|
|
||||||
#include <base/heap.h>
|
#include <base/heap.h>
|
||||||
#include <cap_session/connection.h>
|
#include <base/component.h>
|
||||||
#include <os/server.h>
|
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include "timer_root.h"
|
#include <root_component.h>
|
||||||
|
|
||||||
using namespace Genode;
|
using namespace Genode;
|
||||||
using namespace Timer;
|
|
||||||
|
|
||||||
|
|
||||||
struct Main
|
class Main
|
||||||
{
|
{
|
||||||
Server::Entrypoint &ep;
|
private:
|
||||||
Sliced_heap sliced_heap;
|
|
||||||
Timer::Root_component root;
|
|
||||||
|
|
||||||
Main(Server::Entrypoint &ep)
|
Sliced_heap _sliced_heap;
|
||||||
:
|
Timer::Root_component _root;
|
||||||
ep(ep),
|
|
||||||
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
|
public:
|
||||||
root(ep, &sliced_heap, 0)
|
|
||||||
|
Main(Env &env) : _sliced_heap(env.ram(), env.rm()),
|
||||||
|
_root(env.ep(), _sliced_heap)
|
||||||
{
|
{
|
||||||
/*
|
env.parent().announce(env.ep().manage(_root));
|
||||||
* Announce timer service at our parent.
|
|
||||||
*/
|
|
||||||
env()->parent()->announce(ep.manage(root));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/************
|
/***************
|
||||||
** Server **
|
** Component **
|
||||||
************/
|
***************/
|
||||||
|
|
||||||
namespace Server {
|
size_t Component::stack_size() { return 2 * 1024 * sizeof(addr_t); }
|
||||||
char const *name() { return "timer_drv_ep"; }
|
void Component::construct(Env &env) { static Main main(env); }
|
||||||
size_t stack_size() { return 2048*sizeof(long); }
|
|
||||||
void construct(Entrypoint &ep) { static Main server(ep); }
|
|
||||||
}
|
|
||||||
|
@ -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 Christian Helmuth
|
||||||
* \author Norman Feske
|
* \author Norman Feske
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2006-08-30
|
* \date 2006-08-30
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -14,7 +15,6 @@
|
|||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <util/misc_math.h>
|
#include <util/misc_math.h>
|
||||||
#include <base/printf.h>
|
|
||||||
#include <os/attached_rom_dataspace.h>
|
#include <os/attached_rom_dataspace.h>
|
||||||
|
|
||||||
/* Fiasco includes */
|
/* Fiasco includes */
|
||||||
@ -36,9 +36,10 @@ namespace Fiasco {
|
|||||||
#endif /* L4_SYS_KIP_H__ */
|
#endif /* L4_SYS_KIP_H__ */
|
||||||
|
|
||||||
/* local includes */
|
/* local includes */
|
||||||
#include "timer_session_component.h"
|
#include <time_source.h>
|
||||||
|
|
||||||
using namespace Fiasco;
|
using namespace Fiasco;
|
||||||
|
using Microseconds = Genode::Time_source::Microseconds;
|
||||||
|
|
||||||
|
|
||||||
static l4_timeout_s mus_to_timeout(unsigned long mus)
|
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;
|
long e = Genode::log2(mus) - 7;
|
||||||
unsigned long m;
|
unsigned long m;
|
||||||
|
|
||||||
if (e < 0) e = 0;
|
if (e < 0) e = 0;
|
||||||
m = mus / (1UL << e);
|
m = mus / (1UL << e);
|
||||||
|
|
||||||
/* check corner case */
|
/* check corner case */
|
||||||
if ((e > 31 ) || (m > 1023)) {
|
if ((e > 31 ) || (m > 1023)) {
|
||||||
PWRN("invalid timeout %ld, using max. values\n", mus);
|
Genode::warning("invalid timeout ", mus, ", using max. values");
|
||||||
e = 0;
|
e = 0;
|
||||||
m = 1023;
|
m = 1023;
|
||||||
}
|
}
|
||||||
|
|
||||||
return l4_timeout_rel(m, e);
|
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);
|
Genode::Lock::Guard lock_guard(_lock);
|
||||||
|
return Microseconds(1000 * 1000 * 100);
|
||||||
return 1000*1000*100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned long Platform_timer::curr_time() const
|
Microseconds Timer::Time_source::curr_time() const
|
||||||
{
|
{
|
||||||
Genode::Lock::Guard lock_guard(_lock);
|
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 =
|
static Fiasco::l4_kernel_info_t * const kip =
|
||||||
kip_ds.local_addr<Fiasco::l4_kernel_info_t>();
|
kip_ds.local_addr<Fiasco::l4_kernel_info_t>();
|
||||||
|
|
||||||
return kip->clock;
|
return Microseconds(kip->clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Platform_timer::_usleep(unsigned long usecs)
|
void Timer::Time_source::_usleep(unsigned long usecs) {
|
||||||
{
|
l4_ipc_sleep(l4_timeout(L4_IPC_TIMEOUT_NEVER, mus_to_timeout(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 Julian Stecklina
|
||||||
|
* \author Martin Stein
|
||||||
* \date 2008-03-19
|
* \date 2008-03-19
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -20,34 +21,37 @@ namespace Pistachio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* local includes */
|
/* 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);
|
Lock::Guard lock_guard(_lock);
|
||||||
return 1000*1000;
|
return Microseconds(1000 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned long Platform_timer::curr_time() const
|
Microseconds Timer::Time_source::curr_time() const
|
||||||
{
|
{
|
||||||
Genode::Lock::Guard lock_guard(_lock);
|
Lock::Guard lock_guard(_lock);
|
||||||
return _curr_time_usec;
|
return Microseconds(_curr_time_us);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Platform_timer::_usleep(unsigned long usecs)
|
void Timer::Time_source::_usleep(unsigned long us)
|
||||||
{
|
{
|
||||||
using namespace Pistachio;
|
using namespace Pistachio;
|
||||||
|
|
||||||
enum { MAGIC_USER_DEFINED_HANDLE = 13 };
|
enum { MAGIC_USER_DEFINED_HANDLE = 13 };
|
||||||
L4_Set_UserDefinedHandle(MAGIC_USER_DEFINED_HANDLE);
|
L4_Set_UserDefinedHandle(MAGIC_USER_DEFINED_HANDLE);
|
||||||
|
|
||||||
L4_Sleep(L4_TimePeriod(usecs));
|
L4_Sleep(L4_TimePeriod(us));
|
||||||
_curr_time_usec += usecs;
|
_curr_time_us += us;
|
||||||
|
|
||||||
/* check if sleep was canceled */
|
/* check if sleep was canceled */
|
||||||
if (L4_UserDefinedHandle() != MAGIC_USER_DEFINED_HANDLE)
|
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_ */
|
Reference in New Issue
Block a user