hw: multiprocessor aware processor scheduling

ref #1076
This commit is contained in:
Martin Stein 2014-03-06 14:21:13 +01:00 committed by Norman Feske
parent f545fa0e36
commit 49bf33e404
3 changed files with 34 additions and 14 deletions

View File

@ -277,12 +277,28 @@ extern "C" void init_kernel_multiprocessor()
*/
extern "C" void kernel()
{
/* ensure that no other processor accesses kernel data while we do */
data_lock().lock();
/* determine local processor scheduler */
unsigned const processor_id = Processor::executing_id();
Processor * const processor = processor_pool()->select(processor_id);
Processor_scheduler * const scheduler = processor->scheduler();
scheduler->head()->exception(processor_id);
scheduler->head()->proceed(processor_id);
/*
* Request the current processor occupant without any update. While this
* processor was outside the kernel, another processor may have changed the
* scheduling of the local activities in a way that an update would return
* an occupant other than that whose exception caused the kernel entry.
*/
scheduler->occupant()->exception(processor_id);
/*
* The processor local as well as remote exception-handling may have
* changed the scheduling of the local activities. Hence we must update the
* processor occupant.
*/
scheduler->update_occupant()->proceed(processor_id);
}

View File

@ -37,7 +37,7 @@ void Kernel::Execution_context::_interrupt(unsigned const processor_id)
if (timer()->interrupt_id(processor_id) == irq_id)
{
/* handle scheduling timeout */
__processor->scheduler()->yield();
__processor->scheduler()->yield_occupation();
timer()->clear_interrupt(processor_id);
reset_lap_time(processor_id);
} else {
@ -65,5 +65,5 @@ void Kernel::Execution_context::_unschedule()
void Kernel::Execution_context::_yield()
{
__processor->scheduler()->yield();
__processor->scheduler()->yield_occupation();
}

View File

@ -240,7 +240,7 @@ class Kernel::Scheduler
protected:
T * const _idle;
T * _current;
T * _occupant;
Double_list<T> _items[Priority::MAX + 1];
public:
@ -250,27 +250,29 @@ class Kernel::Scheduler
/**
* Constructor
*/
Scheduler(T * const idle) : _idle(idle), _current(0) { }
Scheduler(T * const idle) : _idle(idle), _occupant(0) { }
/**
* Get currently scheduled item
* Adjust occupant reference to the current scheduling plan
*
* \return updated occupant reference
*/
T * head()
T * update_occupant()
{
for (int i = Priority::MAX; i >= 0 ; i--) {
_current = _items[i].head();
if (_current) return _current;
_occupant = _items[i].head();
if (_occupant) { return _occupant; }
}
return _idle;
}
/**
* End turn of currently scheduled item
* Adjust scheduling plan to the fact that the current occupant yileds
*/
void yield()
void yield_occupation()
{
if (!_current) return;
_items[_current->priority()].head_to_tail();
if (!_occupant) { return; }
_items[_occupant->priority()].head_to_tail();
}
/**
@ -292,6 +294,8 @@ class Kernel::Scheduler
** Accessors **
***************/
T * occupant() { return _occupant ? _occupant : _idle; }
T * idle() const { return _idle; }
};