From aefbc47c56424c5aad4d982aba2c0b09e134ad18 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Tue, 16 Apr 2024 11:40:54 +0200 Subject: [PATCH] hw: preserve slack time, favor activated jobs In the scheduler's implementation preserve the consumed slack-time over periods of activation/deactivation, but instead of appending activated jobs to the end of the slack queue, insert it as new head. Thereby, the extreme discrimination of threads with short execution times and frequent blocking behaviour against long running computations gets avoided. Fix genodelabs/genode#4796 --- repos/base-hw/src/core/kernel/scheduler.cc | 45 +++---- repos/base-hw/src/core/kernel/scheduler.h | 4 - repos/base-hw/src/test/cpu_scheduler/main.cc | 119 ++++++++++--------- 3 files changed, 79 insertions(+), 89 deletions(-) diff --git a/repos/base-hw/src/core/kernel/scheduler.cc b/repos/base-hw/src/core/kernel/scheduler.cc index dff191b197..5dbd7f2c18 100644 --- a/repos/base-hw/src/core/kernel/scheduler.cc +++ b/repos/base-hw/src/core/kernel/scheduler.cc @@ -75,15 +75,13 @@ void Scheduler::_account_priotized(Context &c, unsigned const r) void Scheduler::_account_slack(Context &c, unsigned const r) { - if (_slack_list.head() != &c) - return; - - if (r) + if (r) { c._slack_time_left = r; - else { - c._slack_time_left = _slack_quota; - _slack_list.head_to_tail(); + return; } + + c._slack_time_left = _slack_quota; + if (c.ready()) _slack_list.to_tail(&c._slack_le); } @@ -129,8 +127,8 @@ void Scheduler::update(time_t time) _last_time = time; /* do not detract the quota of idle or removed context */ - if (_current) { - unsigned const r = (_state != YIELD) ? _current_quantum - duration : 0; + if (_current && _current != &_idle) { + unsigned const r = (_state != YIELD) ? _current_quantum - duration : 0; if (_current->_priotized_time_left) _account_priotized(*_current, r); else _account_slack(*_current, r); } @@ -155,30 +153,23 @@ void Scheduler::ready(Context &c) c._ready = true; - bool out_of_date = false; + bool keep_current = + (_current->_priotized_time_left && + !c._priotized_time_left) || + (_current->_priotized_time_left && + (_current->_priority > c._priority)); if (c._quota) { - _upl[c._priority].remove(&c._priotized_le); - if (c._priotized_time_left) { - + if (c._priotized_time_left) _rpl[c._priority].insert_head(&c._priotized_le); - if (_current && _current->_priotized_time_left) { - - if (c._priority >= _current->_priority) - out_of_date = true; - } else out_of_date = true; - } else { - _rpl[c._priority].insert_tail(&c._priotized_le);; - } + else + _rpl[c._priority].insert_tail(&c._priotized_le); } - c._slack_time_left = _slack_quota; - _slack_list.insert_tail(&c._slack_le); + _slack_list.insert_head(&c._slack_le); - if (!_current || _current == &_idle) out_of_date = true; - - if (out_of_date && _state == UP_TO_DATE) _state = OUT_OF_DATE; + if (!keep_current && _state == UP_TO_DATE) _state = OUT_OF_DATE; } @@ -225,6 +216,8 @@ void Scheduler::insert(Context &c) { assert(!c.ready()); + c._slack_time_left = _slack_quota; + if (!c._quota) return; diff --git a/repos/base-hw/src/core/kernel/scheduler.h b/repos/base-hw/src/core/kernel/scheduler.h index 48e0bc9cb3..7273027894 100644 --- a/repos/base-hw/src/core/kernel/scheduler.h +++ b/repos/base-hw/src/core/kernel/scheduler.h @@ -145,7 +145,6 @@ class Kernel::Scheduler _last = le; } - void to_tail(List_element * const le) { remove(le); @@ -157,9 +156,6 @@ class Kernel::Scheduler remove(le); insert_head(le); } - - void head_to_tail() { - to_tail(_list.first()); } }; enum State { UP_TO_DATE, OUT_OF_DATE, YIELD }; diff --git a/repos/base-hw/src/test/cpu_scheduler/main.cc b/repos/base-hw/src/test/cpu_scheduler/main.cc index 6479a0de6c..9f673e198d 100644 --- a/repos/base-hw/src/test/cpu_scheduler/main.cc +++ b/repos/base-hw/src/test/cpu_scheduler/main.cc @@ -452,7 +452,7 @@ Scheduler_test::Main::Main(Env &env) _construct_context(6, __LINE__); _scheduler.ready(_context(6)); - _update_current_and_check(120, 700, 2, 100, __LINE__); + _update_current_and_check(120, 700, 6, 100, __LINE__); _scheduler.ready(_context(4)); _update_current_and_check( 80, 780, 4, 90, __LINE__); @@ -460,10 +460,10 @@ Scheduler_test::Main::Main(Env &env) _scheduler.unready(_context(4)); _scheduler.ready(_context(1)); _update_current_and_check( 50, 830, 1, 10, __LINE__); - _update_current_and_check( 50, 840, 1, 100, __LINE__); - _update_current_and_check( 50, 890, 1, 50, __LINE__); - _update_current_and_check(100, 940, 2, 20, __LINE__); - _update_current_and_check( 60, 960, 6, 40, __LINE__); + _update_current_and_check( 50, 840, 1, 50, __LINE__); + _update_current_and_check( 50, 890, 6, 20, __LINE__); + _update_current_and_check(100, 910, 2, 90, __LINE__); + _update_current_and_check( 60, 970, 2, 30, __LINE__); _update_current_and_check( 60, 0, 3, 110, __LINE__); @@ -519,8 +519,8 @@ Scheduler_test::Main::Main(Env &env) _update_current_and_check( 40, 810, 4, 100, __LINE__); _scheduler.ready(_context(3)); - _update_current_and_check( 30, 840, 4, 70, __LINE__); - _update_current_and_check( 80, 910, 1, 90, __LINE__); + _update_current_and_check( 30, 840, 3, 100, __LINE__); + _update_current_and_check( 70, 910, 3, 30, __LINE__); _scheduler.ready(_context(7)); _scheduler.ready(_context(8)); @@ -557,15 +557,16 @@ Scheduler_test::Main::Main(Env &env) _scheduler.unready(_context(8)); _scheduler.yield(); - _update_current_and_check( 40, 260, 1, 90, __LINE__); + _update_current_and_check( 40, 260, 2, 10, __LINE__); + _update_current_and_check( 40, 270, 1, 100, __LINE__); _scheduler.unready(_context(1)); - _update_current_and_check( 50, 310, 2, 100, __LINE__); + _update_current_and_check( 40, 310, 2, 100, __LINE__); _update_current_and_check( 10, 320, 2, 90, __LINE__); - _set_context_ready_and_check(1, false, __LINE__); - _update_current_and_check(200, 410, 1, 100, __LINE__); - _update_current_and_check( 10, 420, 1, 90, __LINE__); + _set_context_ready_and_check(1, true, __LINE__); + _update_current_and_check(200, 410, 1, 60, __LINE__); + _update_current_and_check( 10, 420, 1, 50, __LINE__); _scheduler.unready(_context(1)); _update_current_and_check( 10, 430, 2, 100, __LINE__); @@ -574,36 +575,36 @@ Scheduler_test::Main::Main(Env &env) _update_current_and_check( 10, 440, 5, 120, __LINE__); _scheduler.yield(); - _update_current_and_check( 90, 530, 2, 90, __LINE__); + _update_current_and_check( 90, 530, 5, 100, __LINE__); _scheduler.yield(); - _update_current_and_check( 10, 540, 5, 100, __LINE__); + _update_current_and_check( 10, 540, 2, 90, __LINE__); _set_context_ready_and_check(7, true, __LINE__); _update_current_and_check( 10, 550, 7, 180, __LINE__); _scheduler.yield(); - _update_current_and_check( 10, 560, 5, 90, __LINE__); + _update_current_and_check( 10, 560, 7, 100, __LINE__); _scheduler.yield(); - _update_current_and_check( 10, 570, 2, 100, __LINE__); + _update_current_and_check( 10, 570, 2, 80, __LINE__); _scheduler.yield(); - _update_current_and_check( 10, 580, 7, 100, __LINE__); + _update_current_and_check( 10, 580, 5, 100, __LINE__); _scheduler.unready(_context(5)); - _update_current_and_check( 10, 590, 7, 90, __LINE__); + _update_current_and_check( 10, 590, 7, 100, __LINE__); _scheduler.unready(_context(7)); _set_context_ready_and_check(5, true, __LINE__); - _update_current_and_check( 10, 600, 2, 100, __LINE__); + _update_current_and_check( 10, 600, 5, 90, __LINE__); - _set_context_ready_and_check(7, false, __LINE__); - _update_current_and_check(200, 700, 5, 100, __LINE__); + _set_context_ready_and_check(7, true, __LINE__); + _update_current_and_check(200, 690, 7, 90, __LINE__); _scheduler.unready(_context(5)); _scheduler.unready(_context(7)); - _update_current_and_check( 10, 710, 2, 100, __LINE__); + _update_current_and_check( 20, 710, 2, 100, __LINE__); _scheduler.unready(_context(2)); _update_current_and_check( 10, 720, 0, 100, __LINE__); @@ -613,25 +614,25 @@ Scheduler_test::Main::Main(Env &env) _set_context_ready_and_check(9, true, __LINE__); _update_current_and_check( 10, 840, 9, 100, __LINE__); - _set_context_ready_and_check(6, false, __LINE__); - _update_current_and_check( 20, 860, 9, 80, __LINE__); + _set_context_ready_and_check(6, true, __LINE__); + _update_current_and_check( 20, 860, 6, 100, __LINE__); - _set_context_ready_and_check(8, false, __LINE__); - _update_current_and_check( 10, 870, 9, 70, __LINE__); + _set_context_ready_and_check(8, true, __LINE__); + _update_current_and_check( 10, 870, 8, 100, __LINE__); _scheduler.yield(); - _update_current_and_check( 10, 880, 6, 100, __LINE__); + _update_current_and_check( 10, 880, 6, 90, __LINE__); _scheduler.yield(); - _update_current_and_check( 10, 890, 8, 100, __LINE__); + _update_current_and_check( 10, 890, 9, 80, __LINE__); - _set_context_ready_and_check(7, false, __LINE__); + _set_context_ready_and_check(7, true, __LINE__); _scheduler.yield(); - _update_current_and_check( 20, 910, 9, 90, __LINE__); + _update_current_and_check( 20, 910, 7, 70, __LINE__); _scheduler.unready(_context(8)); _scheduler.unready(_context(9)); - _update_current_and_check( 10, 920, 6, 80, __LINE__); + _update_current_and_check( 10, 920, 7, 60, __LINE__); _scheduler.unready(_context(6)); _scheduler.unready(_context(7)); @@ -649,7 +650,7 @@ Scheduler_test::Main::Main(Env &env) _update_current_and_check( 10, 970, 3, 30, __LINE__); _scheduler.unready(_context(3)); - _update_current_and_check( 10, 980, 1, 20, __LINE__); + _update_current_and_check( 10, 980, 5, 20, __LINE__); _set_context_ready_and_check(3, true, __LINE__); _update_current_and_check( 10, 990, 3, 10, __LINE__); @@ -684,9 +685,9 @@ Scheduler_test::Main::Main(Env &env) _scheduler.unready(_context(5)); _update_current_and_check( 10, 200, 9, 30, __LINE__); - _set_context_ready_and_check(6, false, __LINE__); + _set_context_ready_and_check(6, true, __LINE__); _construct_context(4, __LINE__); - _update_current_and_check( 10, 210, 9, 20, __LINE__); + _update_current_and_check( 10, 210, 6, 100, __LINE__); _destroy_context(5, __LINE__); _set_context_ready_and_check(4, true, __LINE__); @@ -695,7 +696,7 @@ Scheduler_test::Main::Main(Env &env) _update_current_and_check( 10, 320, 4, 90, __LINE__); _destroy_context(4, __LINE__); - _update_current_and_check(200, 410, 9, 10, __LINE__); + _update_current_and_check(200, 410, 6, 90, __LINE__); _construct_context(5, __LINE__); _scheduler.ready(_context(5)); @@ -703,7 +704,7 @@ Scheduler_test::Main::Main(Env &env) _construct_context(4, __LINE__); _scheduler.yield(); - _update_current_and_check( 10, 430, 6, 100, __LINE__); + _update_current_and_check( 10, 430, 5, 100, __LINE__); _set_context_ready_and_check(4, true, __LINE__); _scheduler.yield(); @@ -711,14 +712,14 @@ Scheduler_test::Main::Main(Env &env) _destroy_context(6, __LINE__); _scheduler.yield(); - _update_current_and_check( 20, 500, 5, 100, __LINE__); + _update_current_and_check( 20, 500, 4, 100, __LINE__); _destroy_context(9, __LINE__); - _update_current_and_check(200, 600, 4, 100, __LINE__); + _update_current_and_check(200, 600, 5, 100, __LINE__); _construct_context(7, __LINE__); _construct_context(8, __LINE__); - _update_current_and_check(200, 700, 5, 100, __LINE__); + _update_current_and_check(200, 700, 4, 100, __LINE__); _set_context_ready_and_check(1, true, __LINE__); _set_context_ready_and_check(7, true, __LINE__); @@ -776,16 +777,16 @@ Scheduler_test::Main::Main(Env &env) _scheduler.unready(_context(1)); _update_current_and_check(100, 270, 4, 90, __LINE__); - _update_current_and_check(100, 360, 4, 100, __LINE__); + _update_current_and_check(100, 360, 4, 90, __LINE__); _scheduler.quota(_context(1), 110); - _update_current_and_check( 10, 370, 4, 90, __LINE__); + _update_current_and_check( 10, 370, 4, 80, __LINE__); _scheduler.quota(_context(1), 120); - _update_current_and_check( 20, 390, 4, 70, __LINE__); + _update_current_and_check( 20, 390, 4, 60, __LINE__); _scheduler.quota(_context(4), 210); - _update_current_and_check( 10, 400, 4, 60, __LINE__); + _update_current_and_check( 10, 400, 4, 50, __LINE__); _scheduler.ready(_context(1)); _update_current_and_check( 10, 410, 1, 110, __LINE__); @@ -813,43 +814,43 @@ Scheduler_test::Main::Main(Env &env) _scheduler.unready(_context(2)); _scheduler.quota(_context(4), 80); - _update_current_and_check( 70, 630, 8, 100, __LINE__); - _update_current_and_check( 50, 680, 8, 50, __LINE__); + _update_current_and_check( 70, 630, 8, 60, __LINE__); + _update_current_and_check( 50, 680, 8, 10, __LINE__); _scheduler.unready(_context(8)); - _update_current_and_check( 10, 690, 4, 50, __LINE__); + _update_current_and_check( 10, 690, 4, 40, __LINE__); _construct_context(3, __LINE__); - _update_current_and_check( 30, 720, 4, 20, __LINE__); + _update_current_and_check( 30, 720, 4, 10, __LINE__); _scheduler.quota(_context(3), 210); _scheduler.yield(); _scheduler.unready(_context(4)); - _update_current_and_check( 20, 740, 5, 90, __LINE__); + _update_current_and_check( 20, 730, 9, 100, __LINE__); _scheduler.unready(_context(9)); - _set_context_ready_and_check(4, false, __LINE__); - _update_current_and_check( 50, 790, 5, 40, __LINE__); + _set_context_ready_and_check(4, true, __LINE__); + _update_current_and_check( 60, 790, 4, 100, __LINE__); _set_context_ready_and_check(2, true, __LINE__); _update_current_and_check( 40, 830, 2, 50, __LINE__); - _update_current_and_check( 60, 880, 2, 100, __LINE__); - _update_current_and_check( 10, 890, 2, 90, __LINE__); + _update_current_and_check( 60, 880, 2, 90, __LINE__); + _update_current_and_check( 10, 890, 2, 80, __LINE__); _scheduler.yield(); _set_context_ready_and_check(9, true, __LINE__); - _update_current_and_check( 60, 950, 6, 50, __LINE__); + _update_current_and_check( 60, 950, 9, 40, __LINE__); _scheduler.unready(_context(6)); - _update_current_and_check( 20, 970, 1, 30, __LINE__); + _update_current_and_check( 20, 970, 9, 20, __LINE__); _scheduler.yield(); _scheduler.ready(_context(8)); - _update_current_and_check( 10, 980, 4, 20, __LINE__); + _update_current_and_check( 10, 980, 8, 20, __LINE__); _scheduler.unready(_context(8)); _scheduler.yield(); - _update_current_and_check( 10, 990, 5, 10, __LINE__); + _update_current_and_check( 10, 990, 4, 10, __LINE__); _scheduler.yield(); _update_current_and_check( 20, 0, 9, 40, __LINE__); @@ -896,9 +897,9 @@ Scheduler_test::Main::Main(Env &env) _destroy_context(3, __LINE__); _update_current_and_check( 90, 840, 9, 40, __LINE__); - _update_current_and_check( 60, 880, 2, 100, __LINE__); - _update_current_and_check(120, 980, 1, 20, __LINE__); - _update_current_and_check( 80, 0, 9, 40, __LINE__); + _update_current_and_check( 60, 880, 5, 20, __LINE__); + _update_current_and_check(120, 900, 1, 100, __LINE__); + _update_current_and_check(100, 0, 9, 40, __LINE__); _env.parent().exit(0);