base-hw: cpu scheduler without inheritance

Ref #3308
This commit is contained in:
Martin Stein 2019-12-23 23:01:42 +01:00 committed by Christian Helmuth
parent eef7b5e168
commit c146a215fb
2 changed files with 65 additions and 78 deletions

View File

@ -18,14 +18,16 @@
using namespace Kernel;
void Cpu_scheduler::_reset(Claim &c) {
_share(&c)->_claim = _share(&c)->_quota; }
void Cpu_scheduler::_reset(Cpu_share &share)
{
share._claim = share._quota;
}
void Cpu_scheduler::_reset_claims(unsigned const p)
{
_rcl[p].for_each([&] (Claim &c) { _reset(c); });
_ucl[p].for_each([&] (Claim &c) { _reset(c); });
_rcl[p].for_each([&] (Cpu_share &share) { _reset(share); });
_ucl[p].for_each([&] (Cpu_share &share) { _reset(share); });
}
@ -63,13 +65,13 @@ void Cpu_scheduler::_head_claimed(unsigned const r)
if (!_head->_quota) { return; }
_head->_claim = r > _head->_quota ? _head->_quota : r;
if (_head->_claim || !_head->_ready) { return; }
_rcl[_head->_prio].to_tail(_head);
_rcl[_head->_prio].to_tail(&_head->_claim_item);
}
void Cpu_scheduler::_head_filled(unsigned const r)
{
if (_fills.head() != _head) { return; }
if (_fills.head() != &_head->_fill_item) { return; }
if (r) { _head->_fill = r; }
else { _next_fill(); }
}
@ -78,10 +80,11 @@ void Cpu_scheduler::_head_filled(unsigned const r)
bool Cpu_scheduler::_claim_for_head()
{
for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) {
Share * const s = _share(_rcl[p].head());
if (!s) { continue; }
if (!s->_claim) { continue; }
_set_head(s, s->_claim, 1);
Double_list_item<Cpu_share> *const item { _rcl[p].head() };
if (!item) { continue; }
Cpu_share &share { item->payload() };
if (!share._claim) { continue; }
_set_head(&share, share._claim, 1);
return 1;
}
return 0;
@ -90,9 +93,12 @@ bool Cpu_scheduler::_claim_for_head()
bool Cpu_scheduler::_fill_for_head()
{
Share * const s = _share(_fills.head());
if (!s) { return 0; }
_set_head(s, s->_fill, 0);
Double_list_item<Cpu_share> *const item { _fills.head() };
if (!item) {
return 0;
}
Share &share = item->payload();
_set_head(&share, share._fill, 0);
return 1;
}
@ -108,15 +114,15 @@ unsigned Cpu_scheduler::_trim_consumption(unsigned & q)
void Cpu_scheduler::_quota_introduction(Share * const s)
{
if (s->_ready) { _rcl[s->_prio].insert_tail(s); }
else { _ucl[s->_prio].insert_tail(s); }
if (s->_ready) { _rcl[s->_prio].insert_tail(&s->_claim_item); }
else { _ucl[s->_prio].insert_tail(&s->_claim_item); }
}
void Cpu_scheduler::_quota_revokation(Share * const s)
{
if (s->_ready) { _rcl[s->_prio].remove(s); }
else { _ucl[s->_prio].remove(s); }
if (s->_ready) { _rcl[s->_prio].remove(&s->_claim_item); }
else { _ucl[s->_prio].remove(&s->_claim_item); }
}
@ -163,7 +169,13 @@ bool Cpu_scheduler::ready_check(Share * const s1)
} else if (s1->_prio != s2->_prio) {
_need_to_schedule = s1->_prio > s2->_prio;
} else {
for (; s2 && s2 != s1; s2 = _share(Claim_list::next(s2))) ;
for (
; s2 && s2 != s1;
s2 =
Double_list<Cpu_share>::next(&s2->_claim_item) != nullptr ?
&Double_list<Cpu_share>::next(&s2->_claim_item)->payload() :
nullptr) ;
_need_to_schedule = !s2;
}
return _need_to_schedule;
@ -178,11 +190,11 @@ void Cpu_scheduler::ready(Share * const s)
s->_ready = 1;
s->_fill = _fill;
_fills.insert_tail(s);
_fills.insert_tail(&s->_fill_item);
if (!s->_quota) { return; }
_ucl[s->_prio].remove(s);
if (s->_claim) { _rcl[s->_prio].insert_head(s); }
else { _rcl[s->_prio].insert_tail(s); }
_ucl[s->_prio].remove(&s->_claim_item);
if (s->_claim) { _rcl[s->_prio].insert_head(&s->_claim_item); }
else { _rcl[s->_prio].insert_tail(&s->_claim_item); }
}
@ -193,10 +205,10 @@ void Cpu_scheduler::unready(Share * const s)
_need_to_schedule = true;
s->_ready = 0;
_fills.remove(s);
_fills.remove(&s->_fill_item);
if (!s->_quota) { return; }
_rcl[s->_prio].remove(s);
_ucl[s->_prio].insert_tail(s);
_rcl[s->_prio].remove(&s->_claim_item);
_ucl[s->_prio].insert_tail(&s->_claim_item);
}
@ -213,10 +225,10 @@ void Cpu_scheduler::remove(Share * const s)
_need_to_schedule = true;
if (s == _head) _head = nullptr;
if (s->_ready) { _fills.remove(s); }
if (s->_ready) { _fills.remove(&s->_fill_item); }
if (!s->_quota) { return; }
if (s->_ready) { _rcl[s->_prio].remove(s); }
else { _ucl[s->_prio].remove(s); }
if (s->_ready) { _rcl[s->_prio].remove(&s->_claim_item); }
else { _ucl[s->_prio].remove(&s->_claim_item); }
}
@ -226,7 +238,7 @@ void Cpu_scheduler::insert(Share * const s)
_need_to_schedule = true;
if (!s->_quota) { return; }
s->_claim = s->_quota;
_ucl[s->_prio].insert_head(s);
_ucl[s->_prio].insert_head(&s->_claim_item);
}

View File

@ -27,26 +27,6 @@ namespace Kernel
*/
class Cpu_priority;
/**
* Scheduling context that has quota and priority (low-latency)
*/
class Cpu_claim : public Double_list_item<Cpu_claim> {
public:
Cpu_claim() : Double_list_item<Cpu_claim>(*this) {}
};
/**
* Scheduling context that has no quota or priority (best effort)
*/
class Cpu_fill : public Double_list_item<Cpu_fill> {
public:
Cpu_fill() : Double_list_item<Cpu_fill>(*this) {}
};
/**
* Scheduling context that is both claim and fill
*/
@ -89,17 +69,19 @@ class Kernel::Cpu_priority
operator signed() const { return _value; }
};
class Kernel::Cpu_share : public Cpu_claim, public Cpu_fill
class Kernel::Cpu_share
{
friend class Cpu_scheduler;
private:
signed const _prio;
unsigned _quota;
unsigned _claim;
unsigned _fill = 0;
bool _ready = false;
Double_list_item<Cpu_share> _fill_item { *this };
Double_list_item<Cpu_share> _claim_item { *this };
signed const _prio;
unsigned _quota;
unsigned _claim;
unsigned _fill { 0 };
bool _ready { false };
public:
@ -124,34 +106,27 @@ class Kernel::Cpu_scheduler
{
private:
typedef Cpu_share Share;
typedef Cpu_fill Fill;
typedef Cpu_claim Claim;
typedef Double_list<Claim> Claim_list;
typedef Double_list<Fill> Fill_list;
typedef Cpu_priority Prio;
typedef Cpu_share Share;
typedef Cpu_priority Prio;
Claim_list _rcl[Prio::MAX + 1]; /* ready claims */
Claim_list _ucl[Prio::MAX + 1]; /* unready claims */
Fill_list _fills { }; /* ready fills */
Share * const _idle;
Share * _head = nullptr;
unsigned _head_quota = 0;
bool _head_claims = false;
bool _head_yields = false;
unsigned const _quota;
unsigned _residual;
unsigned const _fill;
bool _need_to_schedule { true };
time_t _last_time { 0 };
Double_list<Cpu_share> _rcl[Prio::MAX + 1]; /* ready claims */
Double_list<Cpu_share> _ucl[Prio::MAX + 1]; /* unready claims */
Double_list<Cpu_share> _fills { }; /* ready fills */
Share * const _idle;
Share * _head = nullptr;
unsigned _head_quota = 0;
bool _head_claims = false;
bool _head_yields = false;
unsigned const _quota;
unsigned _residual;
unsigned const _fill;
bool _need_to_schedule { true };
time_t _last_time { 0 };
template <typename F> void _for_each_prio(F f) {
for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) { f(p); } }
template <typename T>
static Share * _share(T * const t) { return static_cast<Share *>(t); }
static void _reset(Claim &c);
static void _reset(Cpu_share &share);
void _reset_claims(unsigned const p);
void _next_round();