base-hw: no pointers in scheduler interface

Ref #3308
This commit is contained in:
Martin Stein 2020-01-02 12:42:47 +01:00 committed by Christian Helmuth
parent c146a215fb
commit 0d5f185267
5 changed files with 104 additions and 97 deletions

View File

@ -40,7 +40,7 @@ void Cpu_job::_activate_own_share() { _cpu->schedule(this); }
void Cpu_job::_deactivate_own_share()
{
assert(_cpu->id() == Cpu::executing_id());
_cpu->scheduler().unready(this);
_cpu->scheduler().unready(*this);
}
@ -74,13 +74,13 @@ void Cpu_job::_interrupt(unsigned const /* cpu_id */)
void Cpu_job::affinity(Cpu &cpu)
{
_cpu = &cpu;
_cpu->scheduler().insert(this);
_cpu->scheduler().insert(*this);
}
void Cpu_job::quota(unsigned const q)
{
if (_cpu) { _cpu->scheduler().quota(this, q); }
if (_cpu) { _cpu->scheduler().quota(*this, q); }
else { Cpu_share::quota(q); }
}
@ -93,7 +93,7 @@ Cpu_job::Cpu_job(Cpu_priority const p, unsigned const q)
Cpu_job::~Cpu_job()
{
if (!_cpu) { return; }
_cpu->scheduler().remove(this);
_cpu->scheduler().remove(*this);
}
@ -115,8 +115,8 @@ Cpu::Idle_thread::Idle_thread(Cpu &cpu)
void Cpu::schedule(Job * const job)
{
if (_id == executing_id()) { _scheduler.ready(&job->share()); }
else if (_scheduler.ready_check(&job->share())) { trigger_ip_interrupt(); }
if (_id == executing_id()) { _scheduler.ready(job->share()); }
else if (_scheduler.ready_check(job->share())) { trigger_ip_interrupt(); }
}
@ -162,7 +162,7 @@ Cpu::Cpu(unsigned const id,
Inter_processor_work_list & global_work_list)
:
_id(id), _timer(*this),
_scheduler(&_idle, _quota(), _fill()), _idle(*this),
_scheduler(_idle, _quota(), _fill()), _idle(*this),
_ipi_irq(*this),
_global_work_list(global_work_list)
{ _arch_init(); }

View File

@ -169,7 +169,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
* Returns the currently active job
*/
Job & scheduled_job() const {
return *static_cast<Job *>(_scheduler.head())->helping_sink(); }
return *static_cast<Job *>(&_scheduler.head())->helping_sink(); }
unsigned id() const { return _id; }
Cpu_scheduler &scheduler() { return _scheduler; }

View File

@ -45,11 +45,11 @@ void Cpu_scheduler::_consumed(unsigned const q)
}
void Cpu_scheduler::_set_head(Share * const s, unsigned const q, bool const c)
void Cpu_scheduler::_set_head(Share &s, unsigned const q, bool const c)
{
_head_quota = q;
_head_claims = c;
_head = s;
_head = &s;
}
@ -84,7 +84,7 @@ bool Cpu_scheduler::_claim_for_head()
if (!item) { continue; }
Cpu_share &share { item->payload() };
if (!share._claim) { continue; }
_set_head(&share, share._claim, 1);
_set_head(share, share._claim, 1);
return 1;
}
return 0;
@ -98,12 +98,12 @@ bool Cpu_scheduler::_fill_for_head()
return 0;
}
Share &share = item->payload();
_set_head(&share, share._fill, 0);
_set_head(share, share._fill, 0);
return 1;
}
unsigned Cpu_scheduler::_trim_consumption(unsigned & q)
unsigned Cpu_scheduler::_trim_consumption(unsigned &q)
{
q = Genode::min(Genode::min(q, _head_quota), _residual);
if (!_head_yields) { return _head_quota - q; }
@ -112,23 +112,23 @@ unsigned Cpu_scheduler::_trim_consumption(unsigned & q)
}
void Cpu_scheduler::_quota_introduction(Share * const s)
void Cpu_scheduler::_quota_introduction(Share &s)
{
if (s->_ready) { _rcl[s->_prio].insert_tail(&s->_claim_item); }
else { _ucl[s->_prio].insert_tail(&s->_claim_item); }
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)
void Cpu_scheduler::_quota_revokation(Share &s)
{
if (s->_ready) { _rcl[s->_prio].remove(&s->_claim_item); }
else { _ucl[s->_prio].remove(&s->_claim_item); }
if (s._ready) { _rcl[s._prio].remove(&s._claim_item); }
else { _ucl[s._prio].remove(&s._claim_item); }
}
void Cpu_scheduler::_quota_adaption(Share * const s, unsigned const q)
void Cpu_scheduler::_quota_adaption(Share &s, unsigned const q)
{
if (q) { if (s->_claim > q) { s->_claim = q; } }
if (q) { if (s._claim > q) { s._claim = q; } }
else { _quota_revokation(s); }
}
@ -153,7 +153,7 @@ void Cpu_scheduler::update(time_t time)
}
bool Cpu_scheduler::ready_check(Share * const s1)
bool Cpu_scheduler::ready_check(Share &s1)
{
assert(_head);
@ -162,15 +162,15 @@ bool Cpu_scheduler::ready_check(Share * const s1)
if (_need_to_schedule) return _need_to_schedule;
Share * s2 = _head;
if (!s1->_claim) {
_need_to_schedule = s2 == _idle;
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 if (s1._prio != s2->_prio) {
_need_to_schedule = s1._prio > s2->_prio;
} else {
for (
; s2 && s2 != s1;
; s2 && s2 != &s1;
s2 =
Double_list<Cpu_share>::next(&s2->_claim_item) != nullptr ?
&Double_list<Cpu_share>::next(&s2->_claim_item)->payload() :
@ -182,33 +182,33 @@ bool Cpu_scheduler::ready_check(Share * const s1)
}
void Cpu_scheduler::ready(Share * const s)
void Cpu_scheduler::ready(Share &s)
{
assert(!s->_ready && s != _idle);
assert(!s._ready && &s != &_idle);
_need_to_schedule = true;
s->_ready = 1;
s->_fill = _fill;
_fills.insert_tail(&s->_fill_item);
if (!s->_quota) { return; }
_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); }
s._ready = 1;
s._fill = _fill;
_fills.insert_tail(&s._fill_item);
if (!s._quota) { return; }
_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); }
}
void Cpu_scheduler::unready(Share * const s)
void Cpu_scheduler::unready(Share &s)
{
assert(s->_ready && s != _idle);
assert(s._ready && &s != &_idle);
_need_to_schedule = true;
s->_ready = 0;
_fills.remove(&s->_fill_item);
if (!s->_quota) { return; }
_rcl[s->_prio].remove(&s->_claim_item);
_ucl[s->_prio].insert_tail(&s->_claim_item);
s._ready = 0;
_fills.remove(&s._fill_item);
if (!s._quota) { return; }
_rcl[s._prio].remove(&s._claim_item);
_ucl[s._prio].insert_tail(&s._claim_item);
}
@ -219,39 +219,46 @@ void Cpu_scheduler::yield()
}
void Cpu_scheduler::remove(Share * const s)
void Cpu_scheduler::remove(Share &s)
{
assert(s != _idle);
assert(&s != &_idle);
_need_to_schedule = true;
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); }
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); }
}
void Cpu_scheduler::insert(Share * const s)
void Cpu_scheduler::insert(Share &s)
{
assert(!s->_ready);
assert(!s._ready);
_need_to_schedule = true;
if (!s->_quota) { return; }
s->_claim = s->_quota;
_ucl[s->_prio].insert_head(&s->_claim_item);
if (!s._quota) { return; }
s._claim = s._quota;
_ucl[s._prio].insert_head(&s._claim_item);
}
void Cpu_scheduler::quota(Share * const s, unsigned const q)
void Cpu_scheduler::quota(Share &s, unsigned const q)
{
assert(s != _idle);
if (s->_quota) { _quota_adaption(s, q); }
assert(&s != &_idle);
if (s._quota) { _quota_adaption(s, q); }
else if (q) { _quota_introduction(s); }
s->_quota = q;
s._quota = q;
}
Cpu_scheduler::Cpu_scheduler(Share * const i, unsigned const q,
Cpu_share &Cpu_scheduler::head() const
{
assert(_head);
return *_head;
}
Cpu_scheduler::Cpu_scheduler(Share &i, unsigned const q,
unsigned const f)
: _idle(i), _quota(q), _residual(q), _fill(f)
{ _set_head(i, f, 0); }

View File

@ -60,7 +60,7 @@ class Kernel::Cpu_priority
* Standard operators
*/
Cpu_priority & operator =(signed const v)
Cpu_priority &operator =(signed const v)
{
_value = Genode::min(v, MAX);
return *this;
@ -109,19 +109,19 @@ class Kernel::Cpu_scheduler
typedef Cpu_share Share;
typedef Cpu_priority Prio;
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 };
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 &_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); } }
@ -131,28 +131,28 @@ class Kernel::Cpu_scheduler
void _reset_claims(unsigned const p);
void _next_round();
void _consumed(unsigned const q);
void _set_head(Share * const s, unsigned const q, bool const c);
void _set_head(Share &s, unsigned const q, bool const c);
void _next_fill();
void _head_claimed(unsigned const r);
void _head_filled(unsigned const r);
bool _claim_for_head();
bool _fill_for_head();
unsigned _trim_consumption(unsigned & q);
unsigned _trim_consumption(unsigned &q);
/**
* Fill 's' becomes a claim due to a quota donation
*/
void _quota_introduction(Share * const s);
void _quota_introduction(Share &s);
/**
* Claim 's' looses its state as claim due to quota revokation
*/
void _quota_revokation(Share * const s);
void _quota_revokation(Share &s);
/**
* The quota of claim 's' changes to 'q'
*/
void _quota_adaption(Share * const s, unsigned const q);
void _quota_adaption(Share &s, unsigned const q);
public:
@ -164,7 +164,7 @@ class Kernel::Cpu_scheduler
* \param q total amount of time quota that can be claimed by shares
* \param f time-slice length of the fill round-robin
*/
Cpu_scheduler(Share * const i, unsigned const q, unsigned const f);
Cpu_scheduler(Share &i, unsigned const q, unsigned const f);
bool need_to_schedule() { return _need_to_schedule; }
void timeout() { _need_to_schedule = true; }
@ -177,17 +177,17 @@ class Kernel::Cpu_scheduler
/**
* Set 's1' ready and return wether this outdates current head
*/
bool ready_check(Share * const s1);
bool ready_check(Share &s1);
/**
* Set share 's' ready
*/
void ready(Share * const s);
void ready(Share &s);
/**
* Set share 's' unready
*/
void unready(Share * const s);
void unready(Share &s);
/**
* Current head looses its current claim/fill for this round
@ -197,23 +197,23 @@ class Kernel::Cpu_scheduler
/**
* Remove share 's' from scheduler
*/
void remove(Share * const s);
void remove(Share &s);
/**
* Insert share 's' into scheduler
*/
void insert(Share * const s);
void insert(Share &s);
/**
* Set quota of share 's' to 'q'
*/
void quota(Share * const s, unsigned const q);
void quota(Share &s, unsigned const q);
/*
* Accessors
*/
Share * head() const { return _head; }
Share &head() const;
unsigned head_quota() const {
return Genode::min(_head_quota, _residual); }
unsigned quota() const { return _quota; }

View File

@ -33,7 +33,7 @@ struct Data
Cpu_scheduler scheduler;
char shares[9][sizeof(Cpu_share)];
Data() : idle(0, 0), scheduler(&idle, 1000, 100) { }
Data() : idle(0, 0), scheduler(idle, 1000, 100) { }
};
Data * data()
@ -79,13 +79,13 @@ void create(unsigned const id)
case 9: new (p) Cpu_share(2, 0); break;
default: return;
}
data()->scheduler.insert(s);
data()->scheduler.insert(*s);
}
void destroy(unsigned const id)
{
Cpu_share * const s = share(id);
data()->scheduler.remove(s);
data()->scheduler.remove(*s);
s->~Cpu_share();
}
@ -104,10 +104,10 @@ void update_check(unsigned const l, unsigned const c, unsigned const t,
Genode::log("wrong time ", st, " in line ", l);
done();
}
Cpu_share * const hs = data()->scheduler.head();
Cpu_share &hs = data()->scheduler.head();
unsigned const hq = data()->scheduler.head_quota();
if (hs != share(s)) {
unsigned const hi = share_id(hs);
if (&hs != share(s)) {
unsigned const hi = share_id(&hs);
Genode::log("wrong share ", hi, " in line ", l);
done();
}
@ -119,7 +119,7 @@ void update_check(unsigned const l, unsigned const c, unsigned const t,
void ready_check(unsigned const l, unsigned const s, bool const x)
{
bool const y = data()->scheduler.ready_check(share(s));
bool const y = data()->scheduler.ready_check(*share(s));
if (y != x) {
Genode::log("wrong check result ", y, " in line ", l);
done();
@ -133,10 +133,10 @@ void ready_check(unsigned const l, unsigned const s, bool const x)
#define C(s) create(s);
#define D(s) destroy(s);
#define A(s) data()->scheduler.ready(share(s));
#define I(s) data()->scheduler.unready(share(s));
#define A(s) data()->scheduler.ready(*share(s));
#define I(s) data()->scheduler.unready(*share(s));
#define Y data()->scheduler.yield();
#define Q(s, q) data()->scheduler.quota(share(s), q);
#define Q(s, q) data()->scheduler.quota(*share(s), q);
#define U(c, t, s, q) update_check(__LINE__, c, t, s, q);
#define O(s) ready_check(__LINE__, s, true);
#define N(s) ready_check(__LINE__, s, false);