mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-21 02:01:38 +00:00
base-hw scheduler: optimize quota depletion events
This is an optimization for the case that a prioritized scheduling context needs slightly more time during a round than granted via quota. If this is the case, we move the scheduling context to the front of the unprioritized schedule once its quota gets depleted and thereby at least ensure that it does not have to wait for all unprioritized scheduling contexts as well before being scheduled again. Note that this introduces the possibility of undeserved starvation of unprioritized scheduling contexts to the scheduling scheme. If there are enough prioritized contexts that deplete their quota during a round, they may cover up also the rest of the round with their unprioritized time slices. If this happens every round, contexts without a priority/quota may never get a turn. In the previous scheduling scheme, this could not occur as the unprioritized schedule was completely independent from prioritized schedules and rounds. Ref #4151 Ref #4710
This commit is contained in:
parent
f74962bdad
commit
0467b4aaf3
@ -73,6 +73,17 @@ void Cpu_scheduler::_head_claimed(unsigned const r)
|
||||
return;
|
||||
|
||||
_rcl[_head->_prio].to_tail(&_head->_claim_item);
|
||||
|
||||
/*
|
||||
* This is an optimization for the case that a prioritized scheduling
|
||||
* context needs sligtly more time during a round than granted via quota.
|
||||
* If this is the case, we move the scheduling context to the front of
|
||||
* the unprioritized schedule once its quota gets depleted and thereby
|
||||
* at least ensure that it does not have to wait for all unprioritized
|
||||
* scheduling contexts as well before being scheduled again.
|
||||
*/
|
||||
if (!_head_yields)
|
||||
_fills.to_head(&_head->_fill_item);
|
||||
}
|
||||
|
||||
|
||||
@ -128,7 +139,6 @@ unsigned Cpu_scheduler::_trim_consumption(unsigned &q)
|
||||
if (!_head_yields)
|
||||
return _head_quota - q;
|
||||
|
||||
_head_yields = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -178,6 +188,7 @@ void Cpu_scheduler::update(time_t time)
|
||||
else
|
||||
_head_filled(r);
|
||||
|
||||
_head_yields = false;
|
||||
_consumed(duration);
|
||||
|
||||
} else if (_head_was_removed) {
|
||||
|
@ -75,6 +75,31 @@ class Kernel::Double_list
|
||||
_tail = i;
|
||||
}
|
||||
|
||||
void _to_head(Item * const i)
|
||||
{
|
||||
if (i == _head)
|
||||
return;
|
||||
|
||||
_connect_neighbors(i);
|
||||
i->_next = _head;
|
||||
i->_prev = 0;
|
||||
_head->_prev = i;
|
||||
_head = i;
|
||||
}
|
||||
|
||||
void _tail_to_head()
|
||||
{
|
||||
if (_tail == 0 || _tail == _head)
|
||||
return;
|
||||
|
||||
_tail->_next = _head;
|
||||
_head->_prev = _tail;
|
||||
_tail = _tail->_prev;
|
||||
_tail->_next = 0;
|
||||
_head = _head->_prev;
|
||||
_head->_prev = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -91,6 +116,14 @@ class Kernel::Double_list
|
||||
else { _to_tail(i); }
|
||||
}
|
||||
|
||||
void to_head(Item * const i)
|
||||
{
|
||||
if (i == _tail)
|
||||
_tail_to_head();
|
||||
else
|
||||
_to_head(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert item 'i' as new tail into list
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user