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; using namespace Kernel;
void Cpu_scheduler::_reset(Claim &c) { void Cpu_scheduler::_reset(Cpu_share &share)
_share(&c)->_claim = _share(&c)->_quota; } {
share._claim = share._quota;
}
void Cpu_scheduler::_reset_claims(unsigned const p) void Cpu_scheduler::_reset_claims(unsigned const p)
{ {
_rcl[p].for_each([&] (Claim &c) { _reset(c); }); _rcl[p].for_each([&] (Cpu_share &share) { _reset(share); });
_ucl[p].for_each([&] (Claim &c) { _reset(c); }); _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; } if (!_head->_quota) { return; }
_head->_claim = r > _head->_quota ? _head->_quota : r; _head->_claim = r > _head->_quota ? _head->_quota : r;
if (_head->_claim || !_head->_ready) { return; } 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) 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; } if (r) { _head->_fill = r; }
else { _next_fill(); } else { _next_fill(); }
} }
@ -78,10 +80,11 @@ void Cpu_scheduler::_head_filled(unsigned const r)
bool Cpu_scheduler::_claim_for_head() bool Cpu_scheduler::_claim_for_head()
{ {
for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) { for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) {
Share * const s = _share(_rcl[p].head()); Double_list_item<Cpu_share> *const item { _rcl[p].head() };
if (!s) { continue; } if (!item) { continue; }
if (!s->_claim) { continue; } Cpu_share &share { item->payload() };
_set_head(s, s->_claim, 1); if (!share._claim) { continue; }
_set_head(&share, share._claim, 1);
return 1; return 1;
} }
return 0; return 0;
@ -90,9 +93,12 @@ bool Cpu_scheduler::_claim_for_head()
bool Cpu_scheduler::_fill_for_head() bool Cpu_scheduler::_fill_for_head()
{ {
Share * const s = _share(_fills.head()); Double_list_item<Cpu_share> *const item { _fills.head() };
if (!s) { return 0; } if (!item) {
_set_head(s, s->_fill, 0); return 0;
}
Share &share = item->payload();
_set_head(&share, share._fill, 0);
return 1; return 1;
} }
@ -108,15 +114,15 @@ unsigned Cpu_scheduler::_trim_consumption(unsigned & q)
void Cpu_scheduler::_quota_introduction(Share * const s) void Cpu_scheduler::_quota_introduction(Share * const s)
{ {
if (s->_ready) { _rcl[s->_prio].insert_tail(s); } if (s->_ready) { _rcl[s->_prio].insert_tail(&s->_claim_item); }
else { _ucl[s->_prio].insert_tail(s); } else { _ucl[s->_prio].insert_tail(&s->_claim_item); }
} }
void Cpu_scheduler::_quota_revokation(Share * const s) void Cpu_scheduler::_quota_revokation(Share * const s)
{ {
if (s->_ready) { _rcl[s->_prio].remove(s); } if (s->_ready) { _rcl[s->_prio].remove(&s->_claim_item); }
else { _ucl[s->_prio].remove(s); } 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) { } else if (s1->_prio != s2->_prio) {
_need_to_schedule = s1->_prio > s2->_prio; _need_to_schedule = s1->_prio > s2->_prio;
} else { } 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; _need_to_schedule = !s2;
} }
return _need_to_schedule; return _need_to_schedule;
@ -178,11 +190,11 @@ void Cpu_scheduler::ready(Share * const s)
s->_ready = 1; s->_ready = 1;
s->_fill = _fill; s->_fill = _fill;
_fills.insert_tail(s); _fills.insert_tail(&s->_fill_item);
if (!s->_quota) { return; } if (!s->_quota) { return; }
_ucl[s->_prio].remove(s); _ucl[s->_prio].remove(&s->_claim_item);
if (s->_claim) { _rcl[s->_prio].insert_head(s); } if (s->_claim) { _rcl[s->_prio].insert_head(&s->_claim_item); }
else { _rcl[s->_prio].insert_tail(s); } else { _rcl[s->_prio].insert_tail(&s->_claim_item); }
} }
@ -193,10 +205,10 @@ void Cpu_scheduler::unready(Share * const s)
_need_to_schedule = true; _need_to_schedule = true;
s->_ready = 0; s->_ready = 0;
_fills.remove(s); _fills.remove(&s->_fill_item);
if (!s->_quota) { return; } if (!s->_quota) { return; }
_rcl[s->_prio].remove(s); _rcl[s->_prio].remove(&s->_claim_item);
_ucl[s->_prio].insert_tail(s); _ucl[s->_prio].insert_tail(&s->_claim_item);
} }
@ -213,10 +225,10 @@ void Cpu_scheduler::remove(Share * const s)
_need_to_schedule = true; _need_to_schedule = true;
if (s == _head) _head = nullptr; 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->_quota) { return; }
if (s->_ready) { _rcl[s->_prio].remove(s); } if (s->_ready) { _rcl[s->_prio].remove(&s->_claim_item); }
else { _ucl[s->_prio].remove(s); } else { _ucl[s->_prio].remove(&s->_claim_item); }
} }
@ -226,7 +238,7 @@ void Cpu_scheduler::insert(Share * const s)
_need_to_schedule = true; _need_to_schedule = true;
if (!s->_quota) { return; } if (!s->_quota) { return; }
s->_claim = s->_quota; 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; 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 * Scheduling context that is both claim and fill
*/ */
@ -89,17 +69,19 @@ class Kernel::Cpu_priority
operator signed() const { return _value; } operator signed() const { return _value; }
}; };
class Kernel::Cpu_share : public Cpu_claim, public Cpu_fill class Kernel::Cpu_share
{ {
friend class Cpu_scheduler; friend class Cpu_scheduler;
private: private:
signed const _prio; Double_list_item<Cpu_share> _fill_item { *this };
unsigned _quota; Double_list_item<Cpu_share> _claim_item { *this };
unsigned _claim; signed const _prio;
unsigned _fill = 0; unsigned _quota;
bool _ready = false; unsigned _claim;
unsigned _fill { 0 };
bool _ready { false };
public: public:
@ -124,34 +106,27 @@ class Kernel::Cpu_scheduler
{ {
private: private:
typedef Cpu_share Share; typedef Cpu_share Share;
typedef Cpu_fill Fill; typedef Cpu_priority Prio;
typedef Cpu_claim Claim;
typedef Double_list<Claim> Claim_list;
typedef Double_list<Fill> Fill_list;
typedef Cpu_priority Prio;
Claim_list _rcl[Prio::MAX + 1]; /* ready claims */ Double_list<Cpu_share> _rcl[Prio::MAX + 1]; /* ready claims */
Claim_list _ucl[Prio::MAX + 1]; /* unready claims */ Double_list<Cpu_share> _ucl[Prio::MAX + 1]; /* unready claims */
Fill_list _fills { }; /* ready fills */ Double_list<Cpu_share> _fills { }; /* ready fills */
Share * const _idle; Share * const _idle;
Share * _head = nullptr; Share * _head = nullptr;
unsigned _head_quota = 0; unsigned _head_quota = 0;
bool _head_claims = false; bool _head_claims = false;
bool _head_yields = false; bool _head_yields = false;
unsigned const _quota; unsigned const _quota;
unsigned _residual; unsigned _residual;
unsigned const _fill; unsigned const _fill;
bool _need_to_schedule { true }; bool _need_to_schedule { true };
time_t _last_time { 0 }; time_t _last_time { 0 };
template <typename F> void _for_each_prio(F f) { template <typename F> void _for_each_prio(F f) {
for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) { f(p); } } for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) { f(p); } }
template <typename T> static void _reset(Cpu_share &share);
static Share * _share(T * const t) { return static_cast<Share *>(t); }
static void _reset(Claim &c);
void _reset_claims(unsigned const p); void _reset_claims(unsigned const p);
void _next_round(); void _next_round();