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:
Martin Stein 2022-12-21 19:33:23 +01:00 committed by Christian Helmuth
parent f74962bdad
commit 0467b4aaf3
2 changed files with 45 additions and 1 deletions

View File

@ -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) {

View File

@ -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
*/