diff --git a/repos/libports/src/lib/libc/internal/kernel.h b/repos/libports/src/lib/libc/internal/kernel.h index fb1ca36f1b..30b428523e 100644 --- a/repos/libports/src/lib/libc/internal/kernel.h +++ b/repos/libports/src/lib/libc/internal/kernel.h @@ -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> _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(); + } } /** diff --git a/repos/libports/src/lib/libc/internal/monitor.h b/repos/libports/src/lib/libc/internal/monitor.h index cecbae6e0e..108387430b 100644 --- a/repos/libports/src/lib/libc/internal/monitor.h +++ b/repos/libports/src/lib/libc/internal/monitor.h @@ -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 - 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 _jobs; - Mutex _mutex; - - bool _execution_pending { false }; + Monitor &_monitor; + Registry _jobs; public: + Pool(Monitor &monitor) : _monitor(monitor) { } + + /* called by monitor-user context */ void monitor(Mutex &mutex, Job &job) { Registry::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();