genode/os/include/timer_session/connection.h
Norman Feske 3049c1004c Turn 'Timer::Session' into asynchronous interface
The 'Timer::Session::msleep' function is one of the last occurrences of
long-blocking RPC calls. Synchronous blocking RPC interfaces turned out
to be constant source of trouble and code complexity. I.e., a timer
client that also wants to respond to non-timer events was forced to be a
multi-threaded process. This patch replaces the blocking 'msleep' call
by a mechanism for programming timeouts and receiving wakeup signals in
an asynchronous fashion. Thereby signals originating from the timer can
be handled along with signals from other signal sources by a single
thread.

The changed interface has been tested on Linux, L4/Fiasco, OKL4, NOVA,
L4ka::Pistachio, Codezero, Fiasco.OC, and hw_pbxa9. Furthermore, this
patch adds the timer test to autopilot.

Fixes #1
2013-02-14 10:36:06 +01:00

81 lines
1.9 KiB
C++

/*
* \brief Connection to timer service
* \author Norman Feske
* \date 2008-08-22
*/
/*
* Copyright (C) 2008-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 _INCLUDE__TIMER_SESSION__CONNECTION_H_
#define _INCLUDE__TIMER_SESSION__CONNECTION_H_
#include <timer_session/client.h>
#include <base/connection.h>
namespace Timer {
class Connection : public Genode::Connection<Session>, public Session_client
{
private:
Lock _lock;
Signal_receiver _sig_rec;
Signal_context _default_sigh_ctx;
Signal_context_capability _default_sigh_cap;
Signal_context_capability _custom_sigh_cap;
public:
Connection()
:
Genode::Connection<Session>(session("ram_quota=8K")),
Session_client(cap()),
_default_sigh_cap(_sig_rec.manage(&_default_sigh_ctx))
{
/* register default signal handler */
sigh(_default_sigh_cap);
}
~Connection() { _sig_rec.dissolve(&_default_sigh_ctx); }
/*
* Intercept 'sigh' to keep track of customized signal handlers
*/
void sigh(Signal_context_capability sigh)
{
_custom_sigh_cap = sigh;
Session_client::sigh(_custom_sigh_cap);
}
void usleep(unsigned us)
{
/* serialize sleep calls issued by different threads */
Lock::Guard guard(_lock);
/* temporarily install to the default signal handler */
if (_custom_sigh_cap.valid())
sigh(_default_sigh_cap);
/* trigger timeout at default signal handler */
trigger_once(us);
_sig_rec.wait_for_signal();
/* revert custom signal handler if registered */
if (_custom_sigh_cap.valid())
sigh(_custom_sigh_cap);
}
void msleep(unsigned ms)
{
usleep(1000*ms);
}
};
}
#endif /* _INCLUDE__TIMER_SESSION__CONNECTION_H_ */