diff --git a/repos/ports/src/noux/armed_timeout.h b/repos/ports/src/noux/armed_timeout.h new file mode 100644 index 000000000..9ab5aecb6 --- /dev/null +++ b/repos/ports/src/noux/armed_timeout.h @@ -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 + +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 _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_ */ diff --git a/repos/ports/src/noux/child.h b/repos/ports/src/noux/child.h index e48aa16a9..13977b959 100644 --- a/repos/ports/src/noux/child.h +++ b/repos/ports/src/noux/child.h @@ -36,7 +36,7 @@ #include #include #include -#include +#include namespace Noux { @@ -118,7 +118,7 @@ class Noux::Child : public Rpc_object, Parent_exit *_parent_exit; Kill_broadcaster &_kill_broadcaster; - Timeout_scheduler &_timeout_scheduler; + Timer::Connection &_timer_connection; Parent_execve &_parent_execve; Pid_allocator &_pid_allocator; @@ -313,7 +313,7 @@ class Noux::Child : public Rpc_object, User_info const &user_info, Parent_exit *parent_exit, Kill_broadcaster &kill_broadcaster, - Timeout_scheduler &timeout_scheduler, + Timer::Connection &timer_connection, Parent_execve &parent_execve, Pid_allocator &pid_allocator, int pid, @@ -336,7 +336,7 @@ class Noux::Child : public Rpc_object, _user_info(user_info), _parent_exit(parent_exit), _kill_broadcaster(kill_broadcaster), - _timeout_scheduler(timeout_scheduler), + _timer_connection(timer_connection), _parent_execve(parent_execve), _pid_allocator(pid_allocator), _env(env), @@ -515,7 +515,7 @@ class Noux::Child : public Rpc_object, _user_info, _parent_exit, _kill_broadcaster, - _timeout_scheduler, + _timer_connection, _parent_execve, _pid_allocator, pid(), diff --git a/repos/ports/src/noux/main.cc b/repos/ports/src/noux/main.cc index 414d0372c..b55849132 100644 --- a/repos/ports/src/noux/main.cc +++ b/repos/ports/src/noux/main.cc @@ -264,7 +264,7 @@ struct Noux::Main Pid_allocator _pid_allocator; - Timeout_scheduler _timeout_scheduler { _env }; + Timer::Connection _timer_connection { _env }; User_info _user_info { _config.xml() }; @@ -302,7 +302,7 @@ struct Noux::Main _user_info, 0, _kill_broadcaster, - _timeout_scheduler, + _timer_connection, _init_child, _pid_allocator, _pid_allocator.alloc(), diff --git a/repos/ports/src/noux/syscall.cc b/repos/ports/src/noux/syscall.cc index ed4745a4d..c0a0cda00 100644 --- a/repos/ports/src/noux/syscall.cc +++ b/repos/ports/src/noux/syscall.cc @@ -307,8 +307,9 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) int _rd_array[in_fds_total]; int _wr_array[in_fds_total]; - long timeout_sec = _sysio.select_in.timeout.sec; - long timeout_usec = _sysio.select_in.timeout.usec; + unsigned long timeout_sec = _sysio.select_in.timeout.sec; + unsigned long timeout_usec = _sysio.select_in.timeout.usec; + bool timeout_reached = false; /* 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()) { - unsigned long to_msec = (timeout_sec * 1000) + (timeout_usec / 1000); - Timeout_state ts; - Timeout_alarm ta(ts, _blocker, _timeout_scheduler, to_msec); + Microseconds const us { timeout_sec*1000U*1000U + timeout_usec }; + Armed_timeout::State ts { }; + Armed_timeout timeout(ts, _blocker, _timer_connection, us); /* block until timeout is reached or we were unblocked */ _blocker.lock(); @@ -455,7 +456,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) * We woke up before reaching the timeout, * so we discard the alarm */ - ta.discard(); + timeout.discard(); } } else { @@ -504,7 +505,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) _user_info, this, _kill_broadcaster, - _timeout_scheduler, + _timer_connection, *this, _pid_allocator, new_pid, @@ -834,19 +835,11 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) case SYSCALL_GETTIMEOFDAY: { - /** - * Since the timeout_scheduler thread is started after noux it - * 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(); + Milliseconds const ms = + _timer_connection.curr_time().trunc_to_plain_ms(); - _sysio.gettimeofday_out.sec = (time / 1000); - _sysio.gettimeofday_out.usec = (time % 1000) * 1000; + _sysio.gettimeofday_out.sec = (ms.value / 1000); + _sysio.gettimeofday_out.usec = (ms.value % 1000) * 1000; result = true; break; @@ -857,14 +850,15 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc) /** * 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) { /* CLOCK_SECOND is used by time(3) in the libc. */ 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; result = true; diff --git a/repos/ports/src/noux/timeout_scheduler.h b/repos/ports/src/noux/timeout_scheduler.h deleted file mode 100644 index f70b9408a..000000000 --- a/repos/ports/src/noux/timeout_scheduler.h +++ /dev/null @@ -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 -#include - -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 _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_ */