From debd41081ecdd2d858a7a4c0d7ddb89257fdb418 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Wed, 7 Sep 2022 16:45:27 +0200 Subject: [PATCH] base-hw: optimize & cleanup scheduler * Remove useless `ready_check` function * Implement fine-grained checking when schedule updating is necessary Ref genodelabs/genode#4151 --- repos/base-hw/src/core/kernel/cpu.cc | 11 +-- .../base-hw/src/core/kernel/cpu_scheduler.cc | 71 ++++++++----------- repos/base-hw/src/core/kernel/cpu_scheduler.h | 7 +- 3 files changed, 33 insertions(+), 56 deletions(-) diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc index 02e190d63e..cd7e57b5b9 100644 --- a/repos/base-hw/src/core/kernel/cpu.cc +++ b/repos/base-hw/src/core/kernel/cpu.cc @@ -121,14 +121,9 @@ Cpu::Idle_thread::Idle_thread(Board::Address_space_id_allocator &addr_space_id_a void Cpu::schedule(Job * const job) { - if (_id == executing_id()) - _scheduler.ready(job->share()); - else { - _scheduler.ready_check(job->share()); - - if (_scheduler.need_to_schedule()) - trigger_ip_interrupt(); - } + _scheduler.ready(job->share()); + if (_id != executing_id() && _scheduler.need_to_schedule()) + trigger_ip_interrupt(); } diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.cc b/repos/base-hw/src/core/kernel/cpu_scheduler.cc index a9ac614e5d..b56d771656 100644 --- a/repos/base-hw/src/core/kernel/cpu_scheduler.cc +++ b/repos/base-hw/src/core/kernel/cpu_scheduler.cc @@ -191,45 +191,17 @@ void Cpu_scheduler::update(time_t time) } -void Cpu_scheduler::ready_check(Share &s1) -{ - assert(_head); - - ready(s1); - - if (_need_to_schedule) - return; - - Share * s2 = _head; - if (!s1._claim) { - _need_to_schedule = s2 == &_idle; - } else if (!_head_claims) { - _need_to_schedule = true; - } else if (s1._prio != s2->_prio) { - _need_to_schedule = s1._prio > s2->_prio; - } else { - for ( - ; s2 && s2 != &s1; - s2 = - Double_list::next(&s2->_claim_item) != nullptr ? - &Double_list::next(&s2->_claim_item)->payload() : - nullptr) ; - - _need_to_schedule = !s2; - } -} - - void Cpu_scheduler::ready(Share &s) { assert(!s._ready && &s != &_idle); - _need_to_schedule = true; - s._ready = 1; s._fill = _fill; _fills.insert_tail(&s._fill_item); + if (_head == &_idle) + _need_to_schedule = true; + if (!s._quota) return; @@ -239,6 +211,28 @@ void Cpu_scheduler::ready(Share &s) _rcl[s._prio].insert_head(&s._claim_item); else _rcl[s._prio].insert_tail(&s._claim_item); + + /* + * Check whether we need to re-schedule + */ + if (_need_to_schedule) + return; + + /* current head has no quota left */ + if (!_head_claims) { + _need_to_schedule = true; + return; + } + + /* if current head has different priority */ + if (s._prio != _head->_prio) { + _need_to_schedule = s._prio > _head->_prio; + return; + } + + /* if current head has same priority, the ready share gets active */ + if (s._claim) + _need_to_schedule = true; } @@ -246,7 +240,8 @@ void Cpu_scheduler::unready(Share &s) { assert(s._ready && &s != &_idle); - _need_to_schedule = true; + if (&s == _head) + _need_to_schedule = true; s._ready = 0; _fills.remove(&s._fill_item); @@ -270,21 +265,15 @@ void Cpu_scheduler::remove(Share &s) { assert(&s != &_idle); - _need_to_schedule = true; + if (s._ready) unready(s); if (&s == _head) _head = nullptr; - if (s._ready) - _fills.remove(&s._fill_item); - if (!s._quota) return; - if (s._ready) - _rcl[s._prio].remove(&s._claim_item); - else - _ucl[s._prio].remove(&s._claim_item); + _ucl[s._prio].remove(&s._claim_item); } @@ -292,8 +281,6 @@ void Cpu_scheduler::insert(Share &s) { assert(!s._ready); - _need_to_schedule = true; - if (!s._quota) return; diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.h b/repos/base-hw/src/core/kernel/cpu_scheduler.h index ad8624a257..70e921f44c 100644 --- a/repos/base-hw/src/core/kernel/cpu_scheduler.h +++ b/repos/base-hw/src/core/kernel/cpu_scheduler.h @@ -180,15 +180,10 @@ class Kernel::Cpu_scheduler void timeout() { _need_to_schedule = true; } /** - * Update head according to the consumed time + * Update head according to the current (absolute) time */ void update(time_t time); - /** - * Set 's1' ready and return wether this outdates current head - */ - void ready_check(Share &s1); - /** * Set share 's' ready */