parent
ffd4e231d7
commit
e889c58bbc
56
repos/ports/src/noux/armed_timeout.h
Normal file
56
repos/ports/src/noux/armed_timeout.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* \brief Timeout mechanism for 'select'
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2011-02-14
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2011-2017 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU Affero General Public License version 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NOUX__ARMED_TIMEOUT_H_
|
||||||
|
#define _NOUX__ARMED_TIMEOUT_H_
|
||||||
|
|
||||||
|
#include <timer_session/connection.h>
|
||||||
|
|
||||||
|
namespace Noux { class Armed_timeout; }
|
||||||
|
|
||||||
|
|
||||||
|
class Noux::Armed_timeout : Noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct State : Noncopyable { bool timed_out; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
State &_state;
|
||||||
|
Lock &_blocker;
|
||||||
|
|
||||||
|
Timer::One_shot_timeout<Armed_timeout> _one_shot_timeout;
|
||||||
|
|
||||||
|
void _handle_one_shot_timeout(Duration)
|
||||||
|
{
|
||||||
|
_state.timed_out = true;
|
||||||
|
_blocker.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Armed_timeout(State &state, Lock &blocker,
|
||||||
|
Timer::Connection &timer, Microseconds microseconds)
|
||||||
|
:
|
||||||
|
_state(state), _blocker(blocker),
|
||||||
|
_one_shot_timeout(timer, *this, &Armed_timeout::_handle_one_shot_timeout)
|
||||||
|
{
|
||||||
|
_state.timed_out = false;
|
||||||
|
_one_shot_timeout.schedule(microseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void discard() { _one_shot_timeout.discard(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _NOUX__ARMED_TIMEOUT_H_ */
|
|
@ -36,7 +36,7 @@
|
||||||
#include <local_rom_service.h>
|
#include <local_rom_service.h>
|
||||||
#include <verbose.h>
|
#include <verbose.h>
|
||||||
#include <user_info.h>
|
#include <user_info.h>
|
||||||
#include <timeout_scheduler.h>
|
#include <armed_timeout.h>
|
||||||
|
|
||||||
namespace Noux {
|
namespace Noux {
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ class Noux::Child : public Rpc_object<Session>,
|
||||||
|
|
||||||
Parent_exit *_parent_exit;
|
Parent_exit *_parent_exit;
|
||||||
Kill_broadcaster &_kill_broadcaster;
|
Kill_broadcaster &_kill_broadcaster;
|
||||||
Timeout_scheduler &_timeout_scheduler;
|
Timer::Connection &_timer_connection;
|
||||||
Parent_execve &_parent_execve;
|
Parent_execve &_parent_execve;
|
||||||
Pid_allocator &_pid_allocator;
|
Pid_allocator &_pid_allocator;
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ class Noux::Child : public Rpc_object<Session>,
|
||||||
User_info const &user_info,
|
User_info const &user_info,
|
||||||
Parent_exit *parent_exit,
|
Parent_exit *parent_exit,
|
||||||
Kill_broadcaster &kill_broadcaster,
|
Kill_broadcaster &kill_broadcaster,
|
||||||
Timeout_scheduler &timeout_scheduler,
|
Timer::Connection &timer_connection,
|
||||||
Parent_execve &parent_execve,
|
Parent_execve &parent_execve,
|
||||||
Pid_allocator &pid_allocator,
|
Pid_allocator &pid_allocator,
|
||||||
int pid,
|
int pid,
|
||||||
|
@ -336,7 +336,7 @@ class Noux::Child : public Rpc_object<Session>,
|
||||||
_user_info(user_info),
|
_user_info(user_info),
|
||||||
_parent_exit(parent_exit),
|
_parent_exit(parent_exit),
|
||||||
_kill_broadcaster(kill_broadcaster),
|
_kill_broadcaster(kill_broadcaster),
|
||||||
_timeout_scheduler(timeout_scheduler),
|
_timer_connection(timer_connection),
|
||||||
_parent_execve(parent_execve),
|
_parent_execve(parent_execve),
|
||||||
_pid_allocator(pid_allocator),
|
_pid_allocator(pid_allocator),
|
||||||
_env(env),
|
_env(env),
|
||||||
|
@ -515,7 +515,7 @@ class Noux::Child : public Rpc_object<Session>,
|
||||||
_user_info,
|
_user_info,
|
||||||
_parent_exit,
|
_parent_exit,
|
||||||
_kill_broadcaster,
|
_kill_broadcaster,
|
||||||
_timeout_scheduler,
|
_timer_connection,
|
||||||
_parent_execve,
|
_parent_execve,
|
||||||
_pid_allocator,
|
_pid_allocator,
|
||||||
pid(),
|
pid(),
|
||||||
|
|
|
@ -264,7 +264,7 @@ struct Noux::Main
|
||||||
|
|
||||||
Pid_allocator _pid_allocator;
|
Pid_allocator _pid_allocator;
|
||||||
|
|
||||||
Timeout_scheduler _timeout_scheduler { _env };
|
Timer::Connection _timer_connection { _env };
|
||||||
|
|
||||||
User_info _user_info { _config.xml() };
|
User_info _user_info { _config.xml() };
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ struct Noux::Main
|
||||||
_user_info,
|
_user_info,
|
||||||
0,
|
0,
|
||||||
_kill_broadcaster,
|
_kill_broadcaster,
|
||||||
_timeout_scheduler,
|
_timer_connection,
|
||||||
_init_child,
|
_init_child,
|
||||||
_pid_allocator,
|
_pid_allocator,
|
||||||
_pid_allocator.alloc(),
|
_pid_allocator.alloc(),
|
||||||
|
|
|
@ -307,8 +307,9 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
int _rd_array[in_fds_total];
|
int _rd_array[in_fds_total];
|
||||||
int _wr_array[in_fds_total];
|
int _wr_array[in_fds_total];
|
||||||
|
|
||||||
long timeout_sec = _sysio.select_in.timeout.sec;
|
unsigned long timeout_sec = _sysio.select_in.timeout.sec;
|
||||||
long timeout_usec = _sysio.select_in.timeout.usec;
|
unsigned long timeout_usec = _sysio.select_in.timeout.usec;
|
||||||
|
|
||||||
bool timeout_reached = false;
|
bool timeout_reached = false;
|
||||||
|
|
||||||
/* reset the blocker lock to the 'locked' state */
|
/* reset the blocker lock to the 'locked' state */
|
||||||
|
@ -440,9 +441,9 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!_sysio.select_in.timeout.infinite()) {
|
if (!_sysio.select_in.timeout.infinite()) {
|
||||||
unsigned long to_msec = (timeout_sec * 1000) + (timeout_usec / 1000);
|
Microseconds const us { timeout_sec*1000U*1000U + timeout_usec };
|
||||||
Timeout_state ts;
|
Armed_timeout::State ts { };
|
||||||
Timeout_alarm ta(ts, _blocker, _timeout_scheduler, to_msec);
|
Armed_timeout timeout(ts, _blocker, _timer_connection, us);
|
||||||
|
|
||||||
/* block until timeout is reached or we were unblocked */
|
/* block until timeout is reached or we were unblocked */
|
||||||
_blocker.lock();
|
_blocker.lock();
|
||||||
|
@ -455,7 +456,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
* We woke up before reaching the timeout,
|
* We woke up before reaching the timeout,
|
||||||
* so we discard the alarm
|
* so we discard the alarm
|
||||||
*/
|
*/
|
||||||
ta.discard();
|
timeout.discard();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -504,7 +505,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
_user_info,
|
_user_info,
|
||||||
this,
|
this,
|
||||||
_kill_broadcaster,
|
_kill_broadcaster,
|
||||||
_timeout_scheduler,
|
_timer_connection,
|
||||||
*this,
|
*this,
|
||||||
_pid_allocator,
|
_pid_allocator,
|
||||||
new_pid,
|
new_pid,
|
||||||
|
@ -834,19 +835,11 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
|
|
||||||
case SYSCALL_GETTIMEOFDAY:
|
case SYSCALL_GETTIMEOFDAY:
|
||||||
{
|
{
|
||||||
/**
|
Milliseconds const ms =
|
||||||
* Since the timeout_scheduler thread is started after noux it
|
_timer_connection.curr_time().trunc_to_plain_ms();
|
||||||
* basicly returns the eleapsed time since noux was started. We
|
|
||||||
* abuse this timer to provide a more useful implemenation of
|
|
||||||
* gettimeofday() to make certain programs (e.g. ping(1)) happy.
|
|
||||||
* Note: this is just a short-term solution because Genode currently
|
|
||||||
* lacks a proper time interface (there is a RTC driver however, but
|
|
||||||
* there is no interface for it).
|
|
||||||
*/
|
|
||||||
unsigned long time = _timeout_scheduler.curr_time();
|
|
||||||
|
|
||||||
_sysio.gettimeofday_out.sec = (time / 1000);
|
_sysio.gettimeofday_out.sec = (ms.value / 1000);
|
||||||
_sysio.gettimeofday_out.usec = (time % 1000) * 1000;
|
_sysio.gettimeofday_out.usec = (ms.value % 1000) * 1000;
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
break;
|
break;
|
||||||
|
@ -857,14 +850,15 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
|
||||||
/**
|
/**
|
||||||
* It's the same procedure as in SYSCALL_GETTIMEOFDAY.
|
* It's the same procedure as in SYSCALL_GETTIMEOFDAY.
|
||||||
*/
|
*/
|
||||||
unsigned long time = _timeout_scheduler.curr_time();
|
Milliseconds const ms =
|
||||||
|
_timer_connection.curr_time().trunc_to_plain_ms();
|
||||||
|
|
||||||
switch (_sysio.clock_gettime_in.clock_id) {
|
switch (_sysio.clock_gettime_in.clock_id) {
|
||||||
|
|
||||||
/* CLOCK_SECOND is used by time(3) in the libc. */
|
/* CLOCK_SECOND is used by time(3) in the libc. */
|
||||||
case Sysio::CLOCK_ID_SECOND:
|
case Sysio::CLOCK_ID_SECOND:
|
||||||
{
|
{
|
||||||
_sysio.clock_gettime_out.sec = (time / 1000);
|
_sysio.clock_gettime_out.sec = (ms.value / 1000);
|
||||||
_sysio.clock_gettime_out.nsec = 0;
|
_sysio.clock_gettime_out.nsec = 0;
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
/*
|
|
||||||
* \brief Timeout mechanism for 'select'
|
|
||||||
* \author Norman Feske
|
|
||||||
* \date 2011-02-14
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2011-2017 Genode Labs GmbH
|
|
||||||
*
|
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
|
||||||
* under the terms of the GNU Affero General Public License version 3.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _NOUX__TIMEOUT_SCHEDULER_H_
|
|
||||||
#define _NOUX__TIMEOUT_SCHEDULER_H_
|
|
||||||
|
|
||||||
#include <timer_session/connection.h>
|
|
||||||
#include <base/alarm.h>
|
|
||||||
|
|
||||||
namespace Noux {
|
|
||||||
class Timeout_scheduler;
|
|
||||||
class Timeout_state;
|
|
||||||
class Timeout_alarm;
|
|
||||||
using namespace Genode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Noux::Timeout_scheduler : public Alarm_scheduler
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Timer::Connection _timer;
|
|
||||||
Alarm::Time _curr_time { 0 };
|
|
||||||
|
|
||||||
enum { TIMER_GRANULARITY_MSEC = 10 };
|
|
||||||
|
|
||||||
Signal_handler<Timeout_scheduler> _timer_handler;
|
|
||||||
|
|
||||||
void _handle_timer()
|
|
||||||
{
|
|
||||||
_curr_time = _timer.elapsed_ms();
|
|
||||||
Alarm_scheduler::handle(_curr_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Timeout_scheduler(Env &env)
|
|
||||||
:
|
|
||||||
_timer(env),
|
|
||||||
_timer_handler(env.ep(), *this, &Timeout_scheduler::_handle_timer)
|
|
||||||
{
|
|
||||||
_timer.sigh(_timer_handler);
|
|
||||||
_timer.trigger_periodic(TIMER_GRANULARITY_MSEC*1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
Alarm::Time curr_time() const { return _curr_time; }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct Noux::Timeout_state
|
|
||||||
{
|
|
||||||
bool timed_out;
|
|
||||||
|
|
||||||
Timeout_state() : timed_out(false) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Noux::Timeout_alarm : public Alarm
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
|
|
||||||
Timeout_state &_state;
|
|
||||||
Lock &_blocker;
|
|
||||||
Timeout_scheduler &_scheduler;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Timeout_alarm(Timeout_state &st, Lock &blocker,
|
|
||||||
Timeout_scheduler &scheduler, Time timeout)
|
|
||||||
:
|
|
||||||
_state(st),
|
|
||||||
_blocker(blocker),
|
|
||||||
_scheduler(scheduler)
|
|
||||||
{
|
|
||||||
_scheduler.schedule_absolute(this, _scheduler.curr_time() + timeout);
|
|
||||||
_state.timed_out = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void discard() { _scheduler.discard(this); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
bool on_alarm(unsigned) override
|
|
||||||
{
|
|
||||||
_state.timed_out = true;
|
|
||||||
_blocker.unlock();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _NOUX__TIMEOUT_SCHEDULER_H_ */
|
|
Loading…
Reference in New Issue
Block a user