hw: idle execution context is no thread anymore

Previously, Idle_thread inherited from Thread which caused an extra
processor_pool.h and processor_pool.cc and also made class models for
processor and scheduling more complex. However, this inheritance makes
not much sense anyway as an idle context doesn't trigger most of the code
in Thread.

ref #1225
This commit is contained in:
Martin Stein 2014-08-21 15:14:26 +02:00 committed by Christian Helmuth
parent ec6c19a487
commit b3bc9bd549
6 changed files with 128 additions and 173 deletions

View File

@ -55,7 +55,6 @@ SRC_CC += kernel/signal_receiver.cc
SRC_CC += kernel/irq.cc
SRC_CC += kernel/pd.cc
SRC_CC += kernel/processor.cc
SRC_CC += kernel/processor_pool.cc
# add assembly sources
SRC_S += boot_modules.s

View File

@ -20,6 +20,9 @@
#include <cpu.h>
#include <kernel/scheduler.h>
/* base includes */
#include <unmanaged_singleton.h>
namespace Kernel
{
/**
@ -32,6 +35,11 @@ namespace Kernel
*/
class Processor_domain_update;
/**
* Execution context that is scheduled on CPU idle
*/
class Cpu_idle;
/**
* Multiplexes a single processor to multiple processor clients
*/
@ -41,6 +49,16 @@ namespace Kernel
* A multiplexable common instruction processor
*/
class Processor;
/**
* Provides a processor object for every available processor
*/
class Processor_pool;
/**
* Return Processor_pool singleton
*/
Processor_pool * processor_pool();
}
class Kernel::Processor_domain_update
@ -184,11 +202,50 @@ class Kernel::Processor_client : public Processor_scheduler::Item
unsigned tics_consumed() { return _tics_consumed; }
};
class Kernel::Cpu_idle : public Cpu::User_context, public Processor_client
{
private:
static constexpr size_t stack_size = sizeof(addr_t) * 32;
char _stack[stack_size] __attribute__((aligned(16)));
/**
* Main function of all idle threads
*/
static void _main() { while (1) { Cpu::wait_for_interrupt(); } }
public:
/**
* Construct idle context for CPU 'cpu'
*/
Cpu_idle(Processor * const cpu);
/**
* Handle exception that occured during execution on CPU 'cpu'
*/
void exception(unsigned const cpu)
{
switch (cpu_exception) {
case INTERRUPT_REQUEST: _interrupt(cpu); return;
case FAST_INTERRUPT_REQUEST: _interrupt(cpu); return;
case RESET: return;
default: assert(0); }
}
/**
* Continue execution on CPU 'cpu_id'
*/
void proceed(unsigned const cpu_id);
};
class Kernel::Processor : public Cpu
{
private:
unsigned const _id;
Cpu_idle _idle;
Processor_scheduler _scheduler;
bool _ip_interrupt_pending;
Timer * const _timer;
@ -212,15 +269,13 @@ class Kernel::Processor : public Cpu
/**
* Constructor
*
* \param id kernel name of the processor object
* \param idle_client client that gets scheduled on idle
* \param timer timer that is used for scheduling the processor
* \param id kernel name of the processor
* \param timer scheduling timer
*/
Processor(unsigned const id, Processor_client * const idle_client,
Timer * const timer)
Processor(unsigned const id, Timer * const timer)
:
_id(id), _scheduler(idle_client), _ip_interrupt_pending(false),
_timer(timer)
_id(id), _idle(this), _scheduler(&_idle),
_ip_interrupt_pending(false), _timer(timer)
{ }
/**
@ -273,4 +328,39 @@ class Kernel::Processor : public Cpu
Processor_scheduler * scheduler() { return &_scheduler; }
};
class Kernel::Processor_pool
{
private:
Timer _timer;
char _processors[PROCESSORS][sizeof(Processor)];
public:
/**
* Constructor
*/
Processor_pool()
{
for (unsigned id = 0; id < PROCESSORS; id++) {
new (_processors[id]) Processor(id, &_timer); }
}
/**
* Return the kernel object of processor 'id'
*/
Processor * processor(unsigned const id) const
{
assert(id < PROCESSORS);
char * const p = const_cast<char *>(_processors[id]);
return reinterpret_cast<Processor *>(p);
}
/**
* Return the object of the primary processor
*/
Processor * primary_processor() const {
return processor(Processor::primary_id()); }
};
#endif /* _KERNEL__PROCESSOR_H_ */

View File

@ -1,129 +0,0 @@
/*
* \brief Provide a processor object for every available processor
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2014-01-14
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _KERNEL__PROCESSOR_POOL_H_
#define _KERNEL__PROCESSOR_POOL_H_
/* base includes */
#include <unmanaged_singleton.h>
/* core includes */
#include <kernel/kernel.h>
#include <kernel/thread.h>
namespace Kernel
{
/**
* Thread that consumes processor time if no other thread is available
*/
class Idle_thread;
/**
* Provides a processor object for every available processor
*/
class Processor_pool;
/**
* Return Processor_pool singleton
*/
Processor_pool * processor_pool();
}
class Kernel::Idle_thread : public Thread
{
private:
enum {
STACK_SIZE = sizeof(addr_t) * 32,
STACK_ALIGNM = Cpu::data_access_align,
};
char _stack[STACK_SIZE] __attribute__((aligned(STACK_ALIGNM)));
/**
* Main function of all idle threads
*/
static void _main() { while (1) { Cpu::wait_for_interrupt(); } }
public:
/**
* Constructor
*
* \param processor kernel object of targeted processor
*/
Idle_thread(Processor * const processor)
:
Thread(Priority::MAX, "idle")
{
ip = (addr_t)&_main;
sp = (addr_t)&_stack[STACK_SIZE];
init(processor, core_pd(), 0, 0);
}
};
class Kernel::Processor_pool
{
private:
Timer _timer;
char _processors[PROCESSORS][sizeof(Processor)];
char _idle_threads[PROCESSORS][sizeof(Idle_thread)];
/**
* Return idle thread of a specific processor
*
* \param processor_id kernel name of the targeted processor
*/
Idle_thread * _idle_thread(unsigned const processor_id) const
{
char * const p = const_cast<char *>(_idle_threads[processor_id]);
return reinterpret_cast<Idle_thread *>(p);
}
public:
/**
* Constructor
*/
Processor_pool()
{
for (unsigned i = 0; i < PROCESSORS; i++) {
new (_idle_threads[i]) Idle_thread(processor(i));
new (_processors[i]) Processor(i, _idle_thread(i), &_timer);
}
}
/**
* Return the object of a specific processor
*
* \param id kernel name of the targeted processor
*/
Processor * processor(unsigned const id) const
{
assert(id < PROCESSORS);
char * const p = const_cast<char *>(_processors[id]);
return reinterpret_cast<Processor *>(p);
}
/**
* Return the object of the primary processor
*/
Processor * primary_processor() const
{
return processor(Processor::primary_id());
}
};
#endif /* _KERNEL__PROCESSOR_POOL_H_ */

View File

@ -20,7 +20,6 @@
/* core includes */
#include <kernel/kernel.h>
#include <kernel/pd.h>
#include <kernel/processor_pool.h>
#include <kernel/signal_receiver.h>
namespace Kernel

View File

@ -14,12 +14,14 @@
/* core includes */
#include <kernel/processor.h>
#include <kernel/processor_pool.h>
#include <kernel/kernel.h>
#include <kernel/thread.h>
#include <kernel/irq.h>
#include <pic.h>
#include <timer.h>
using namespace Kernel;
namespace Kernel
{
/**
@ -29,6 +31,9 @@ namespace Kernel
Pic * pic();
Timer * timer();
Processor_pool * processor_pool() {
return unmanaged_singleton<Processor_pool>(); }
}
class Kernel::Processor_domain_update_list
@ -53,11 +58,8 @@ namespace Kernel
/**
* Return singleton of the processor domain-udpate list
*/
Processor_domain_update_list * processor_domain_update_list()
{
static Processor_domain_update_list s;
return &s;
}
Processor_domain_update_list * processor_domain_update_list() {
return unmanaged_singleton<Processor_domain_update_list>(); }
}
@ -65,7 +67,7 @@ namespace Kernel
** Processor_client **
**********************/
void Kernel::Processor_client::_interrupt(unsigned const processor_id)
void Processor_client::_interrupt(unsigned const processor_id)
{
/* determine handling for specific interrupt */
unsigned irq_id;
@ -94,14 +96,29 @@ void Kernel::Processor_client::_interrupt(unsigned const processor_id)
}
void Kernel::Processor_client::_schedule() { _processor->schedule(this); }
void Processor_client::_schedule() { _processor->schedule(this); }
/********************
** Processor_idle **
********************/
Cpu_idle::Cpu_idle(Processor * const cpu) : Processor_client(cpu, 0)
{
cpu_exception = RESET;
ip = (addr_t)&_main;
sp = (addr_t)&_stack[stack_size];
init_thread((addr_t)core_pd()->translation_table(), core_pd()->id());
}
void Cpu_idle::proceed(unsigned const cpu) { mtc()->continue_user(this, cpu); }
/***************
** Processor **
***************/
void Kernel::Processor::schedule(Processor_client * const client)
void Processor::schedule(Processor_client * const client)
{
if (_id != executing_id()) {
@ -127,7 +144,7 @@ void Kernel::Processor::schedule(Processor_client * const client)
}
void Kernel::Processor::trigger_ip_interrupt()
void Processor::trigger_ip_interrupt()
{
if (!_ip_interrupt_pending) {
pic()->trigger_ip_interrupt(_id);
@ -136,14 +153,14 @@ void Kernel::Processor::trigger_ip_interrupt()
}
void Kernel::Processor_client::_unschedule()
void Processor_client::_unschedule()
{
assert(_processor->id() == Processor::executing_id());
_processor->scheduler()->remove(this);
}
void Kernel::Processor_client::_yield()
void Processor_client::_yield()
{
assert(_processor->id() == Processor::executing_id());
_processor->scheduler()->yield_occupation();
@ -154,7 +171,7 @@ void Kernel::Processor_client::_yield()
** Processor_domain_update **
*****************************/
void Kernel::Processor_domain_update::_perform_locally()
void Processor_domain_update::_perform_locally()
{
/* perform domain update locally and get pending bit */
unsigned const processor_id = Processor::executing_id();
@ -173,7 +190,7 @@ void Kernel::Processor_domain_update::_perform_locally()
}
bool Kernel::Processor_domain_update::_perform(unsigned const domain_id)
bool Processor_domain_update::_perform(unsigned const domain_id)
{
/* perform locally and leave it at that if in uniprocessor mode */
_domain_id = domain_id;

View File

@ -1,21 +0,0 @@
/*
* \brief Provide a processor object for every available processor
* \author Martin Stein
* \date 2014-01-14
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* core includes */
#include <kernel/processor_pool.h>
using namespace Kernel;
Processor_pool * Kernel::processor_pool() {
return unmanaged_singleton<Processor_pool>(); }