mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-08 20:05:54 +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 };
|
||||
|
||||
Monitor::Pool _monitors { };
|
||||
Monitor::Pool _monitors { *this };
|
||||
|
||||
Reconstructible<Io_signal_handler<Kernel>> _execute_monitors {
|
||||
_env.ep(), *this, &Kernel::_monitors_handler };
|
||||
|
||||
bool _execute_monitors_pending { false };
|
||||
|
||||
void _monitors_handler()
|
||||
{
|
||||
_execute_monitors_pending = false;
|
||||
_monitors.execute_monitors();
|
||||
}
|
||||
|
||||
@ -532,26 +535,30 @@ struct Libc::Kernel final : Vfs::Io_response_handler,
|
||||
/**
|
||||
* 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()) {
|
||||
Main_job job { fn, timeout_ms };
|
||||
|
||||
_monitors.monitor(mutex, job);
|
||||
return job.completed();
|
||||
return job.completed() ? Monitor::Result::COMPLETE
|
||||
: Monitor::Result::TIMEOUT;
|
||||
|
||||
} else {
|
||||
Pthread_job job { fn, _timer_accessor, timeout_ms };
|
||||
|
||||
_monitors.monitor(mutex, job);
|
||||
return job.completed();
|
||||
return job.completed() ? Monitor::Result::COMPLETE
|
||||
: Monitor::Result::TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
void _charge_monitors() override
|
||||
{
|
||||
if (_monitors.charge_monitors())
|
||||
if (!_execute_monitors_pending) {
|
||||
_execute_monitors_pending = true;
|
||||
Signal_transmitter(*_execute_monitors).submit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,20 +48,24 @@ class Libc::Monitor : Interface
|
||||
{
|
||||
public:
|
||||
|
||||
enum class Result { COMPLETE, TIMEOUT };
|
||||
|
||||
struct Job;
|
||||
struct Pool;
|
||||
|
||||
struct Function : Interface { virtual bool execute() = 0; };
|
||||
enum class Function_result { COMPLETE, INCOMPLETE };
|
||||
|
||||
struct Function : Interface { virtual Function_result execute() = 0; };
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool _monitor(Mutex &, Function &, uint64_t) = 0;
|
||||
virtual Result _monitor(Mutex &, Function &, uint64_t) = 0;
|
||||
virtual void _charge_monitors() = 0;
|
||||
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
{
|
||||
FN const &fn;
|
||||
bool execute() override { return fn(); }
|
||||
Function_result execute() override { return fn(); }
|
||||
_Function(FN const &fn) : fn(fn) { }
|
||||
} function { fn };
|
||||
|
||||
_charge_monitors();
|
||||
return _monitor(mutex, function, timeout_ms);
|
||||
}
|
||||
|
||||
@ -103,7 +108,7 @@ struct Libc::Monitor::Job
|
||||
|
||||
virtual ~Job() { }
|
||||
|
||||
bool execute() { return _fn.execute(); }
|
||||
bool execute() { return _fn.execute() == Function_result::COMPLETE; }
|
||||
|
||||
bool completed() const { return _blockade.woken_up(); }
|
||||
bool expired() const { return _blockade.expired(); }
|
||||
@ -117,43 +122,30 @@ struct Libc::Monitor::Pool
|
||||
{
|
||||
private:
|
||||
|
||||
Registry<Job> _jobs;
|
||||
Mutex _mutex;
|
||||
|
||||
bool _execution_pending { false };
|
||||
Monitor &_monitor;
|
||||
Registry<Job> _jobs;
|
||||
|
||||
public:
|
||||
|
||||
Pool(Monitor &monitor) : _monitor(monitor) { }
|
||||
|
||||
/* called by monitor-user context */
|
||||
void monitor(Mutex &mutex, Job &job)
|
||||
{
|
||||
Registry<Job>::Element element { _jobs, job };
|
||||
|
||||
mutex.release();
|
||||
|
||||
_monitor.charge_monitors();
|
||||
|
||||
job.wait_for_completion();
|
||||
|
||||
mutex.acquire();
|
||||
}
|
||||
|
||||
bool charge_monitors()
|
||||
{
|
||||
Mutex::Guard guard { _mutex };
|
||||
|
||||
bool const charged = !_execution_pending;
|
||||
_execution_pending = true;
|
||||
return charged;
|
||||
}
|
||||
|
||||
/* called by the monitor context itself */
|
||||
void execute_monitors()
|
||||
{
|
||||
{
|
||||
Mutex::Guard guard { _mutex };
|
||||
|
||||
if (!_execution_pending) return;
|
||||
|
||||
_execution_pending = false;
|
||||
}
|
||||
|
||||
_jobs.for_each([&] (Job &job) {
|
||||
if (!job.completed() && !job.expired() && job.execute()) {
|
||||
job.complete();
|
||||
|
Loading…
x
Reference in New Issue
Block a user