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() void Cpu_job::_deactivate_own_share()
{ {
assert(_cpu->id() == Cpu::executing_id()); 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) void Cpu_job::affinity(Cpu &cpu)
{ {
_cpu = &cpu; _cpu = &cpu;
_cpu->scheduler().insert(this); _cpu->scheduler().insert(*this);
} }
void Cpu_job::quota(unsigned const q) 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); } else { Cpu_share::quota(q); }
} }
@ -93,7 +93,7 @@ Cpu_job::Cpu_job(Cpu_priority const p, unsigned const q)
Cpu_job::~Cpu_job() Cpu_job::~Cpu_job()
{ {
if (!_cpu) { return; } 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) void Cpu::schedule(Job * const job)
{ {
if (_id == executing_id()) { _scheduler.ready(&job->share()); } if (_id == executing_id()) { _scheduler.ready(job->share()); }
else if (_scheduler.ready_check(&job->share())) { trigger_ip_interrupt(); } 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) Inter_processor_work_list & global_work_list)
: :
_id(id), _timer(*this), _id(id), _timer(*this),
_scheduler(&_idle, _quota(), _fill()), _idle(*this), _scheduler(_idle, _quota(), _fill()), _idle(*this),
_ipi_irq(*this), _ipi_irq(*this),
_global_work_list(global_work_list) _global_work_list(global_work_list)
{ _arch_init(); } { _arch_init(); }

View File

@ -169,7 +169,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
* Returns the currently active job * Returns the currently active job
*/ */
Job & scheduled_job() const { 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; } unsigned id() const { return _id; }
Cpu_scheduler &scheduler() { return _scheduler; } 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_quota = q;
_head_claims = c; _head_claims = c;
_head = s; _head = &s;
} }
@ -84,7 +84,7 @@ bool Cpu_scheduler::_claim_for_head()
if (!item) { continue; } if (!item) { continue; }
Cpu_share &share { item->payload() }; Cpu_share &share { item->payload() };
if (!share._claim) { continue; } if (!share._claim) { continue; }
_set_head(&share, share._claim, 1); _set_head(share, share._claim, 1);
return 1; return 1;
} }
return 0; return 0;
@ -98,12 +98,12 @@ bool Cpu_scheduler::_fill_for_head()
return 0; return 0;
} }
Share &share = item->payload(); Share &share = item->payload();
_set_head(&share, share._fill, 0); _set_head(share, share._fill, 0);
return 1; 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); q = Genode::min(Genode::min(q, _head_quota), _residual);
if (!_head_yields) { return _head_quota - q; } 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); } if (s._ready) { _rcl[s._prio].insert_tail(&s._claim_item); }
else { _ucl[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); } if (s._ready) { _rcl[s._prio].remove(&s._claim_item); }
else { _ucl[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); } 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); assert(_head);
@ -162,15 +162,15 @@ bool Cpu_scheduler::ready_check(Share * const s1)
if (_need_to_schedule) return _need_to_schedule; if (_need_to_schedule) return _need_to_schedule;
Share * s2 = _head; Share * s2 = _head;
if (!s1->_claim) { if (!s1._claim) {
_need_to_schedule = s2 == _idle; _need_to_schedule = s2 == &_idle;
} else if (!_head_claims) { } else if (!_head_claims) {
_need_to_schedule = true; _need_to_schedule = true;
} 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 ( for (
; s2 && s2 != s1; ; s2 && s2 != &s1;
s2 = s2 =
Double_list<Cpu_share>::next(&s2->_claim_item) != nullptr ? Double_list<Cpu_share>::next(&s2->_claim_item) != nullptr ?
&Double_list<Cpu_share>::next(&s2->_claim_item)->payload() : &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; _need_to_schedule = true;
s->_ready = 1; s._ready = 1;
s->_fill = _fill; s._fill = _fill;
_fills.insert_tail(&s->_fill_item); _fills.insert_tail(&s._fill_item);
if (!s->_quota) { return; } if (!s._quota) { return; }
_ucl[s->_prio].remove(&s->_claim_item); _ucl[s._prio].remove(&s._claim_item);
if (s->_claim) { _rcl[s->_prio].insert_head(&s->_claim_item); } if (s._claim) { _rcl[s._prio].insert_head(&s._claim_item); }
else { _rcl[s->_prio].insert_tail(&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; _need_to_schedule = true;
s->_ready = 0; s._ready = 0;
_fills.remove(&s->_fill_item); _fills.remove(&s._fill_item);
if (!s->_quota) { return; } if (!s._quota) { return; }
_rcl[s->_prio].remove(&s->_claim_item); _rcl[s._prio].remove(&s._claim_item);
_ucl[s->_prio].insert_tail(&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; _need_to_schedule = true;
if (s == _head) _head = nullptr; if (&s == _head) _head = nullptr;
if (s->_ready) { _fills.remove(&s->_fill_item); } if (s._ready) { _fills.remove(&s._fill_item); }
if (!s->_quota) { return; } if (!s._quota) { return; }
if (s->_ready) { _rcl[s->_prio].remove(&s->_claim_item); } if (s._ready) { _rcl[s._prio].remove(&s._claim_item); }
else { _ucl[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; _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->_claim_item); _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); assert(&s != &_idle);
if (s->_quota) { _quota_adaption(s, q); } if (s._quota) { _quota_adaption(s, q); }
else if (q) { _quota_introduction(s); } 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) unsigned const f)
: _idle(i), _quota(q), _residual(q), _fill(f) : _idle(i), _quota(q), _residual(q), _fill(f)
{ _set_head(i, f, 0); } { _set_head(i, f, 0); }

View File

@ -60,7 +60,7 @@ class Kernel::Cpu_priority
* Standard operators * Standard operators
*/ */
Cpu_priority & operator =(signed const v) Cpu_priority &operator =(signed const v)
{ {
_value = Genode::min(v, MAX); _value = Genode::min(v, MAX);
return *this; return *this;
@ -109,19 +109,19 @@ class Kernel::Cpu_scheduler
typedef Cpu_share Share; typedef Cpu_share Share;
typedef Cpu_priority Prio; typedef Cpu_priority Prio;
Double_list<Cpu_share> _rcl[Prio::MAX + 1]; /* ready claims */ Double_list<Cpu_share> _rcl[Prio::MAX + 1]; /* ready claims */
Double_list<Cpu_share> _ucl[Prio::MAX + 1]; /* unready claims */ Double_list<Cpu_share> _ucl[Prio::MAX + 1]; /* unready claims */
Double_list<Cpu_share> _fills { }; /* ready fills */ Double_list<Cpu_share> _fills { }; /* ready fills */
Share * const _idle; Share &_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); } }
@ -131,28 +131,28 @@ class Kernel::Cpu_scheduler
void _reset_claims(unsigned const p); void _reset_claims(unsigned const p);
void _next_round(); void _next_round();
void _consumed(unsigned const q); 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 _next_fill();
void _head_claimed(unsigned const r); void _head_claimed(unsigned const r);
void _head_filled(unsigned const r); void _head_filled(unsigned const r);
bool _claim_for_head(); bool _claim_for_head();
bool _fill_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 * 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 * 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' * 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: public:
@ -164,7 +164,7 @@ class Kernel::Cpu_scheduler
* \param q total amount of time quota that can be claimed by shares * \param q total amount of time quota that can be claimed by shares
* \param f time-slice length of the fill round-robin * \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; } bool need_to_schedule() { return _need_to_schedule; }
void timeout() { _need_to_schedule = true; } void timeout() { _need_to_schedule = true; }
@ -177,17 +177,17 @@ class Kernel::Cpu_scheduler
/** /**
* Set 's1' ready and return wether this outdates current head * 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 * Set share 's' ready
*/ */
void ready(Share * const s); void ready(Share &s);
/** /**
* Set share 's' unready * Set share 's' unready
*/ */
void unready(Share * const s); void unready(Share &s);
/** /**
* Current head looses its current claim/fill for this round * Current head looses its current claim/fill for this round
@ -197,23 +197,23 @@ class Kernel::Cpu_scheduler
/** /**
* Remove share 's' from scheduler * Remove share 's' from scheduler
*/ */
void remove(Share * const s); void remove(Share &s);
/** /**
* Insert share 's' into scheduler * Insert share 's' into scheduler
*/ */
void insert(Share * const s); void insert(Share &s);
/** /**
* Set quota of share 's' to 'q' * Set quota of share 's' to 'q'
*/ */
void quota(Share * const s, unsigned const q); void quota(Share &s, unsigned const q);
/* /*
* Accessors * Accessors
*/ */
Share * head() const { return _head; } Share &head() const;
unsigned head_quota() const { unsigned head_quota() const {
return Genode::min(_head_quota, _residual); } return Genode::min(_head_quota, _residual); }
unsigned quota() const { return _quota; } unsigned quota() const { return _quota; }

View File

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