mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-02 07:30:58 +00:00
libc: cleanup monitor implementation
- Explicit types for function and monitor execution results - Remove pending flag and mutex (pending flag was moved to kernel)
This commit is contained in:
parent
420ed91480
commit
257b3b6775
@ -271,13 +271,16 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
|
|
||||||
Pthread_pool _pthreads { _timer_accessor };
|
Pthread_pool _pthreads { _timer_accessor };
|
||||||
|
|
||||||
Monitor::Pool _monitors { };
|
Monitor::Pool _monitors { *this };
|
||||||
|
|
||||||
Reconstructible<Io_signal_handler<Kernel>> _execute_monitors {
|
Reconstructible<Io_signal_handler<Kernel>> _execute_monitors {
|
||||||
_env.ep(), *this, &Kernel::_monitors_handler };
|
_env.ep(), *this, &Kernel::_monitors_handler };
|
||||||
|
|
||||||
|
bool _execute_monitors_pending { false };
|
||||||
|
|
||||||
void _monitors_handler()
|
void _monitors_handler()
|
||||||
{
|
{
|
||||||
|
_execute_monitors_pending = false;
|
||||||
_monitors.execute_monitors();
|
_monitors.execute_monitors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,26 +535,30 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
|||||||
/**
|
/**
|
||||||
* Monitor interface
|
* Monitor interface
|
||||||
*/
|
*/
|
||||||
bool _monitor(Mutex &mutex, Function &fn, uint64_t timeout_ms) override
|
Monitor::Result _monitor(Mutex &mutex, Function &fn, uint64_t timeout_ms) override
|
||||||
{
|
{
|
||||||
if (_main_context()) {
|
if (_main_context()) {
|
||||||
Main_job job { fn, timeout_ms };
|
Main_job job { fn, timeout_ms };
|
||||||
|
|
||||||
_monitors.monitor(mutex, job);
|
_monitors.monitor(mutex, job);
|
||||||
return job.completed();
|
return job.completed() ? Monitor::Result::COMPLETE
|
||||||
|
: Monitor::Result::TIMEOUT;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Pthread_job job { fn, _timer_accessor, timeout_ms };
|
Pthread_job job { fn, _timer_accessor, timeout_ms };
|
||||||
|
|
||||||
_monitors.monitor(mutex, job);
|
_monitors.monitor(mutex, job);
|
||||||
return job.completed();
|
return job.completed() ? Monitor::Result::COMPLETE
|
||||||
|
: Monitor::Result::TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _charge_monitors() override
|
void _charge_monitors() override
|
||||||
{
|
{
|
||||||
if (_monitors.charge_monitors())
|
if (!_execute_monitors_pending) {
|
||||||
|
_execute_monitors_pending = true;
|
||||||
Signal_transmitter(*_execute_monitors).submit();
|
Signal_transmitter(*_execute_monitors).submit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,20 +48,24 @@ class Libc::Monitor : Interface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
enum class Result { COMPLETE, TIMEOUT };
|
||||||
|
|
||||||
struct Job;
|
struct Job;
|
||||||
struct Pool;
|
struct Pool;
|
||||||
|
|
||||||
struct Function : Interface { virtual bool execute() = 0; };
|
enum class Function_result { COMPLETE, INCOMPLETE };
|
||||||
|
|
||||||
|
struct Function : Interface { virtual Function_result execute() = 0; };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual bool _monitor(Mutex &, Function &, uint64_t) = 0;
|
virtual Result _monitor(Mutex &, Function &, uint64_t) = 0;
|
||||||
virtual void _charge_monitors() = 0;
|
virtual void _charge_monitors() = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block until monitored execution succeeds or timeout expires
|
* Block until monitored execution completed or timeout expires
|
||||||
*
|
*
|
||||||
* The mutex must be locked when calling the monitor. It is released
|
* The mutex must be locked when calling the monitor. It is released
|
||||||
* during wait for completion and re-aquired before the function
|
* during wait for completion and re-aquired before the function
|
||||||
@ -70,15 +74,16 @@ class Libc::Monitor : Interface
|
|||||||
* Returns true if execution completed, false on timeout.
|
* Returns true if execution completed, false on timeout.
|
||||||
*/
|
*/
|
||||||
template <typename FN>
|
template <typename FN>
|
||||||
bool monitor(Mutex &mutex, FN const &fn, uint64_t timeout_ms = 0)
|
Result monitor(Mutex &mutex, FN const &fn, uint64_t timeout_ms = 0)
|
||||||
{
|
{
|
||||||
struct _Function : Function
|
struct _Function : Function
|
||||||
{
|
{
|
||||||
FN const &fn;
|
FN const &fn;
|
||||||
bool execute() override { return fn(); }
|
Function_result execute() override { return fn(); }
|
||||||
_Function(FN const &fn) : fn(fn) { }
|
_Function(FN const &fn) : fn(fn) { }
|
||||||
} function { fn };
|
} function { fn };
|
||||||
|
|
||||||
|
_charge_monitors();
|
||||||
return _monitor(mutex, function, timeout_ms);
|
return _monitor(mutex, function, timeout_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +108,7 @@ struct Libc::Monitor::Job
|
|||||||
|
|
||||||
virtual ~Job() { }
|
virtual ~Job() { }
|
||||||
|
|
||||||
bool execute() { return _fn.execute(); }
|
bool execute() { return _fn.execute() == Function_result::COMPLETE; }
|
||||||
|
|
||||||
bool completed() const { return _blockade.woken_up(); }
|
bool completed() const { return _blockade.woken_up(); }
|
||||||
bool expired() const { return _blockade.expired(); }
|
bool expired() const { return _blockade.expired(); }
|
||||||
@ -117,43 +122,30 @@ struct Libc::Monitor::Pool
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Registry<Job> _jobs;
|
Monitor &_monitor;
|
||||||
Mutex _mutex;
|
Registry<Job> _jobs;
|
||||||
|
|
||||||
bool _execution_pending { false };
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
Pool(Monitor &monitor) : _monitor(monitor) { }
|
||||||
|
|
||||||
|
/* called by monitor-user context */
|
||||||
void monitor(Mutex &mutex, Job &job)
|
void monitor(Mutex &mutex, Job &job)
|
||||||
{
|
{
|
||||||
Registry<Job>::Element element { _jobs, job };
|
Registry<Job>::Element element { _jobs, job };
|
||||||
|
|
||||||
mutex.release();
|
mutex.release();
|
||||||
|
|
||||||
|
_monitor.charge_monitors();
|
||||||
|
|
||||||
job.wait_for_completion();
|
job.wait_for_completion();
|
||||||
|
|
||||||
mutex.acquire();
|
mutex.acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool charge_monitors()
|
/* called by the monitor context itself */
|
||||||
{
|
|
||||||
Mutex::Guard guard { _mutex };
|
|
||||||
|
|
||||||
bool const charged = !_execution_pending;
|
|
||||||
_execution_pending = true;
|
|
||||||
return charged;
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute_monitors()
|
void execute_monitors()
|
||||||
{
|
{
|
||||||
{
|
|
||||||
Mutex::Guard guard { _mutex };
|
|
||||||
|
|
||||||
if (!_execution_pending) return;
|
|
||||||
|
|
||||||
_execution_pending = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_jobs.for_each([&] (Job &job) {
|
_jobs.for_each([&] (Job &job) {
|
||||||
if (!job.completed() && !job.expired() && job.execute()) {
|
if (!job.completed() && !job.expired() && job.execute()) {
|
||||||
job.complete();
|
job.complete();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user