diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.cc b/repos/base-hw/src/core/kernel/cpu_scheduler.cc index cdda3a15c2..7991295815 100644 --- a/repos/base-hw/src/core/kernel/cpu_scheduler.cc +++ b/repos/base-hw/src/core/kernel/cpu_scheduler.cc @@ -70,7 +70,7 @@ void Cpu_scheduler::_current_claimed(unsigned const r) * at least ensure that it does not have to wait for all unprioritized * scheduling contexts as well before being scheduled again. */ - if (!_yield) + if (_state != YIELD) _fills.to_head(&_current->_fill_item); } @@ -123,7 +123,7 @@ bool Cpu_scheduler::_schedule_fill() unsigned Cpu_scheduler::_trim_consumption(unsigned &q) { q = Genode::min(Genode::min(q, _current_quantum), _super_period_left); - if (!_yield) + if (_state != YIELD) return _current_quantum - q; return 0; @@ -157,7 +157,6 @@ void Cpu_scheduler::update(time_t time) unsigned duration = (unsigned) (time - _last_time); _last_time = time; - _need_to_schedule = false; unsigned const r = _trim_consumption(duration); /* do not detract the quota if the current share was removed even now */ @@ -166,9 +165,10 @@ void Cpu_scheduler::update(time_t time) else _current_filled(r); } - _yield = false; _consumed(duration); + _state = UP_TO_DATE; + if (_schedule_claim()) return; @@ -184,6 +184,9 @@ void Cpu_scheduler::ready(Share &s) assert(!s._ready && &s != &_idle); s._ready = true; + + bool out_of_date = false; + if (s._quota) { _ucl[s._prio].remove(&s._claim_item); @@ -192,12 +195,9 @@ void Cpu_scheduler::ready(Share &s) _rcl[s._prio].insert_head(&s._claim_item); if (_current && _current->_claim) { - if (s._prio >= _current->_prio) - _need_to_schedule = true; - } else - _need_to_schedule = true; + if (s._prio >= _current->_prio) out_of_date = true; + } else out_of_date = true; } else { - _rcl[s._prio].insert_tail(&s._claim_item);; } } @@ -205,7 +205,9 @@ void Cpu_scheduler::ready(Share &s) s._fill = _fill; _fills.insert_tail(&s._fill_item); - if (!_current || _current == &_idle) _need_to_schedule = true; + if (!_current || _current == &_idle) out_of_date = true; + + if (out_of_date && _state == UP_TO_DATE) _state = OUT_OF_DATE; } @@ -213,8 +215,7 @@ void Cpu_scheduler::unready(Share &s) { assert(s._ready && &s != &_idle); - if (&s == _current) - _need_to_schedule = true; + if (&s == _current && _state == UP_TO_DATE) _state = OUT_OF_DATE; s._ready = false; _fills.remove(&s._fill_item); @@ -229,8 +230,7 @@ void Cpu_scheduler::unready(Share &s) void Cpu_scheduler::yield() { - _yield = true; - _need_to_schedule = true; + _state = YIELD; } diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.h b/repos/base-hw/src/core/kernel/cpu_scheduler.h index fbaf7f1529..63768fc777 100644 --- a/repos/base-hw/src/core/kernel/cpu_scheduler.h +++ b/repos/base-hw/src/core/kernel/cpu_scheduler.h @@ -198,17 +198,18 @@ class Kernel::Cpu_scheduler typedef Cpu_share Share; typedef Cpu_priority Prio; + enum State { UP_TO_DATE, OUT_OF_DATE, YIELD }; + + State _state { UP_TO_DATE }; Share_list _rcl[Prio::max() + 1]; /* ready claims */ Share_list _ucl[Prio::max() + 1]; /* unready claims */ Share_list _fills { }; /* ready fills */ Share &_idle; Share *_current = nullptr; unsigned _current_quantum { 0 }; - bool _yield = false; unsigned const _super_period_length; unsigned _super_period_left { _super_period_length }; unsigned const _fill; - bool _need_to_schedule { true }; time_t _last_time { 0 }; template void _for_each_prio(F f) @@ -260,8 +261,10 @@ class Kernel::Cpu_scheduler */ Cpu_scheduler(Share &i, unsigned const q, unsigned const f); - bool need_to_schedule() { return _need_to_schedule; } - void timeout() { _need_to_schedule = true; } + bool need_to_schedule() const { return _state != UP_TO_DATE; } + + void timeout() { + if (_state == UP_TO_DATE) _state = OUT_OF_DATE; } /** * Update state according to the current (absolute) time diff --git a/repos/base-hw/src/test/cpu_scheduler/main.cc b/repos/base-hw/src/test/cpu_scheduler/main.cc index 2f5c25d6dc..530624d7c1 100644 --- a/repos/base-hw/src/test/cpu_scheduler/main.cc +++ b/repos/base-hw/src/test/cpu_scheduler/main.cc @@ -265,13 +265,13 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const print(output, "(\n"); print(output, " quota: ", _super_period_left, "/", _super_period_length, ", "); print(output, "fill: ", _fill, ", "); - print(output, "need to schedule: ", _need_to_schedule ? "true" : "false", ", "); + print(output, "need to schedule: ", need_to_schedule() ? "true" : "false", ", "); print(output, "last_time: ", _last_time); if (_current != nullptr) { print(output, "\n current: ( "); - if (_need_to_schedule) { + if (need_to_schedule()) { print(output, "\033[31m"); } else { print(output, "\033[32m"); @@ -280,7 +280,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const print(output, "quota: ", _current_quantum, ", "); print(output, "\033[0m"); print(output, "claims: ", (_current && _current->_claim) ? "true" : "false", ", "); - print(output, "yields: ", _yield ? "true" : "false", " "); + print(output, "yields: ", _state == YIELD ? "true" : "false", " "); print(output, ")"); } bool prios_empty { true }; @@ -303,7 +303,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const _rcl[prio].for_each([&] (Kernel::Cpu_share const &share) { if (&share == _current && _current->_claim) { - if (_need_to_schedule) { + if (need_to_schedule()) { print(output, "\033[31m"); } else { print(output, "\033[32m"); @@ -343,7 +343,7 @@ void Cpu_scheduler_test::Cpu_scheduler::print(Output &output) const _fills.for_each([&] (Kernel::Cpu_share const &share) { if (&share == _current && !_current->_claim) { - if (_need_to_schedule) { + if (need_to_schedule()) { print(output, "\033[31m"); } else { print(output, "\033[32m");