noux: remove dependency from alarm library

Fixes #3123
This commit is contained in:
Norman Feske 2019-01-18 15:18:03 +01:00
parent ffd4e231d7
commit e889c58bbc
5 changed files with 78 additions and 130 deletions

View 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_ */

View File

@ -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(),

View File

@ -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(),

View File

@ -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;

View File

@ -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_ */