hw: schedule on demand (Fix #3157)

This commit is contained in:
Stefan Kalkowski 2019-02-20 15:26:56 +01:00 committed by Christian Helmuth
parent a58fcc3b1e
commit 2ecf1d887b
7 changed files with 79 additions and 28 deletions

View File

@ -164,22 +164,20 @@ bool Cpu::interrupt(unsigned const irq_id)
Cpu_job & Cpu::schedule()
{
/* update scheduler */
time_t quota = _timer.update_time();
Job & old_job = scheduled_job();
old_job.exception(*this);
_timer.process_timeouts();
_scheduler.update(quota);
/* get new job */
Job & new_job = scheduled_job();
quota = _scheduler.head_quota();
_timer.set_timeout(this, quota);
_timer.schedule_timeout();
if (_scheduler.need_to_schedule()) {
time_t quota = _timer.update_time();
_timer.process_timeouts();
_scheduler.update(quota);
quota = _scheduler.head_quota();
_timer.set_timeout(this, quota);
_timer.schedule_timeout();
}
/* return new job */
return new_job;
return scheduled_job();
}
@ -195,9 +193,9 @@ addr_t Cpu::stack_start() {
Cpu::Cpu(unsigned const id, Pic & pic,
Inter_processor_work_list & global_work_list)
:
_id(id), _pic(pic), _timer(_id),
_id(id), _pic(pic), _timer(*this),
_scheduler(&_idle, _quota(), _fill()), _idle(*this),
_ipi_irq(*this), _timer_irq(_timer.interrupt_id(), *this),
_ipi_irq(*this),
_global_work_list(global_work_list)
{ _arch_init(); }

View File

@ -116,7 +116,6 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
Cpu_scheduler _scheduler;
Idle_thread _idle;
Ipi _ipi_irq;
Irq _timer_irq; /* timer IRQ implemented as empty event */
Inter_processor_work_list &_global_work_list;
Inter_processor_work_list _local_work_list {};

View File

@ -101,7 +101,7 @@ unsigned Cpu_scheduler::_trim_consumption(unsigned & q)
{
q = Genode::min(Genode::min(q, _head_quota), _residual);
if (!_head_yields) { return _head_quota - q; }
_head_yields = 0;
_head_yields = false;
return 0;
}
@ -129,6 +129,8 @@ void Cpu_scheduler::_quota_adaption(Share * const s, unsigned const q)
void Cpu_scheduler::update(unsigned q)
{
_need_to_schedule = false;
/* do not detract the quota if the head context was removed even now */
if (_head) {
unsigned const r = _trim_consumption(q);
@ -148,12 +150,21 @@ bool Cpu_scheduler::ready_check(Share * const s1)
assert(_head);
ready(s1);
if (_need_to_schedule) return _need_to_schedule;
Share * s2 = _head;
if (!s1->_claim) { return s2 == _idle; }
if (!_head_claims) { return 1; }
if (s1->_prio != s2->_prio) { return s1->_prio > s2->_prio; }
for (; s2 && s2 != s1; s2 = _share(Claim_list::next(s2))) ;
return !s2;
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 {
for (; s2 && s2 != s1; s2 = _share(Claim_list::next(s2))) ;
_need_to_schedule = !s2;
}
return _need_to_schedule;
}
@ -161,6 +172,8 @@ void Cpu_scheduler::ready(Share * const s)
{
assert(!s->_ready && s != _idle);
_need_to_schedule = true;
s->_ready = 1;
s->_fill = _fill;
_fills.insert_tail(s);
@ -174,6 +187,9 @@ void Cpu_scheduler::ready(Share * const s)
void Cpu_scheduler::unready(Share * const s)
{
assert(s->_ready && s != _idle);
_need_to_schedule = true;
s->_ready = 0;
_fills.remove(s);
if (!s->_quota) { return; }
@ -182,13 +198,18 @@ void Cpu_scheduler::unready(Share * const s)
}
void Cpu_scheduler::yield() { _head_yields = 1; }
void Cpu_scheduler::yield()
{
_head_yields = true;
_need_to_schedule = true;
}
void Cpu_scheduler::remove(Share * const s)
{
assert(s != _idle);
_need_to_schedule = true;
if (s == _head) _head = nullptr;
if (s->_ready) { _fills.remove(s); }
if (!s->_quota) { return; }
@ -200,6 +221,7 @@ void Cpu_scheduler::remove(Share * const s)
void Cpu_scheduler::insert(Share * const s)
{
assert(!s->_ready);
_need_to_schedule = true;
if (!s->_quota) { return; }
s->_claim = s->_quota;
_ucl[s->_prio].insert_head(s);
@ -217,5 +239,5 @@ void Cpu_scheduler::quota(Share * const s, unsigned const q)
Cpu_scheduler::Cpu_scheduler(Share * const i, unsigned const q,
unsigned const f)
: _idle(i), _head_yields(0), _quota(q), _residual(q), _fill(f)
: _idle(i), _quota(q), _residual(q), _fill(f)
{ _set_head(i, f, 0); }

View File

@ -128,10 +128,11 @@ class Kernel::Cpu_scheduler
Share * _head = nullptr;
unsigned _head_quota = 0;
bool _head_claims = false;
bool _head_yields;
bool _head_yields = false;
unsigned const _quota;
unsigned _residual;
unsigned const _fill;
bool _need_to_schedule { true };
template <typename F> void _for_each_prio(F f) {
for (signed p = Prio::MAX; p > Prio::MIN - 1; p--) { f(p); } }
@ -179,6 +180,9 @@ class Kernel::Cpu_scheduler
*/
Cpu_scheduler(Share * const i, unsigned const q, unsigned const f);
bool need_to_schedule() { return _need_to_schedule; }
void timeout() { _need_to_schedule = true; }
/**
* Update head according to the consumption of quota 'q'
*/

View File

@ -12,6 +12,7 @@
*/
/* Core includes */
#include <kernel/cpu.h>
#include <kernel/timer.h>
#include <kernel/configuration.h>
#include <hw/assert.h>
@ -19,6 +20,13 @@
using namespace Kernel;
void Timer::Irq::occurred() { _cpu.scheduler().timeout(); }
Timer::Irq::Irq(unsigned id, Cpu &cpu)
: Kernel::Irq(id, cpu.irq_pool()), _cpu(cpu) {}
time_t Timer::timeout_age_us(Timeout const * const timeout) const
{
time_t const age = (time_t)_time - timeout->_start;
@ -131,7 +139,8 @@ void Timer::process_timeouts()
}
Timer::Timer(unsigned cpu_id) : _cpu_id(cpu_id), _driver(cpu_id)
Timer::Timer(Cpu & cpu)
: _driver(cpu.id()), _irq(interrupt_id(), cpu)
{
/*
* The timer frequency should allow a good accuracy on the smallest

View File

@ -16,6 +16,7 @@
/* base-hw includes */
#include <kernel/types.h>
#include <kernel/irq.h>
/* Genode includes */
#include <util/list.h>
@ -25,6 +26,7 @@
namespace Kernel
{
class Cpu;
class Timeout;
class Timer;
}
@ -61,10 +63,23 @@ class Kernel::Timer
{
private:
class Irq : private Kernel::Irq
{
private:
Cpu & _cpu;
public:
Irq(unsigned id, Cpu & cpu);
void occurred() override;
};
using Driver = Timer_driver;
unsigned const _cpu_id;
Driver _driver;
Irq _irq;
time_t _time = 0;
bool _time_period = false;
Genode::List<Timeout> _timeout_list[2];
@ -82,11 +97,12 @@ class Kernel::Timer
public:
Timer(unsigned cpu_id);
Timer(Cpu & cpu);
void schedule_timeout();
time_t update_time();
void process_timeouts();
void set_timeout(Timeout * const timeout, time_t const duration);

View File

@ -21,12 +21,15 @@ using namespace Kernel;
void Thread::Pd_update::execute() {}
void Thread::exception(Cpu&)
void Thread::exception(Cpu & cpu)
{
using Context = Genode::Cpu::Context;
if (regs->is_irq())
if (regs->is_irq()) {
/* there are only cpu-local timer interrupts right now */
cpu.interrupt(5);
return;
}
switch(regs->cpu_exception) {
case Context::ECALL_FROM_USER: