hw: move Processor_client to processor.h

ref #1088
This commit is contained in:
Martin Stein 2014-03-11 01:21:56 +01:00 committed by Norman Feske
parent 8818d810a1
commit 852785324f
11 changed files with 305 additions and 273 deletions

View File

@ -263,7 +263,7 @@ extern "C" void init_kernel_multiprocessor()
_main_thread_utcb->start_info()->init(t.id(), Genode::Native_capability());
t.ip = (addr_t)CORE_MAIN;;
t.sp = (addr_t)s + STACK_SIZE;
t.init(processor_pool()->select(processor_id), core_id(), &utcb, 1);
t.init(processor_pool()->processor(processor_id), core_id(), &utcb, 1);
/* kernel initialization finished */
init_platform();
@ -282,7 +282,7 @@ extern "C" void kernel()
/* determine local processor scheduler */
unsigned const processor_id = Processor::executing_id();
Processor * const processor = processor_pool()->select(processor_id);
Processor * const processor = processor_pool()->processor(processor_id);
Processor_scheduler * const scheduler = processor->scheduler();
/*

View File

@ -1,5 +1,5 @@
/*
* \brief Provide a processor object for every available processor
* \brief A multiplexable common instruction processor
* \author Martin Stein
* \date 2014-01-14
*/
@ -13,12 +13,76 @@
/* core includes */
#include <kernel/processor.h>
#include <kernel/irq.h>
#include <pic.h>
#include <timer.h>
using namespace Kernel;
Processor_pool * Kernel::processor_pool()
namespace Kernel
{
static Processor_pool s;
return &s;
Pic * pic();
Timer * timer();
}
void Kernel::Processor_client::_interrupt(unsigned const processor_id)
{
/* determine handling for specific interrupt */
unsigned irq_id;
Pic * const ic = pic();
if (ic->take_request(irq_id))
{
/* check wether the interrupt is a processor-scheduling timeout */
if (timer()->interrupt_id(processor_id) == irq_id) {
__processor->scheduler()->yield_occupation();
timer()->clear_interrupt(processor_id);
/* check wether the interrupt is our inter-processor interrupt */
} else if (ic->is_ip_interrupt(irq_id, processor_id)) {
/*
* This interrupt solely denotes that another processor has
* modified the scheduling plan of this processor and thus
* a more prior user context than the current one might be
* available.
*/
/* after all it must be a user interrupt */
} else {
/* try to inform the user interrupt-handler */
Irq::occurred(irq_id);
}
}
/* end interrupt request at controller */
ic->finish_request();
}
void Kernel::Processor_client::_schedule()
{
/* schedule thread */
__processor->scheduler()->insert(this);
/* let processor of the scheduled thread notice the change immediately */
unsigned const processor_id = __processor->id();
if (processor_id != Processor::executing_id()) {
pic()->trigger_ip_interrupt(processor_id);
}
}
void Kernel::Processor_client::_unschedule()
{
assert(__processor->id() == Processor::executing_id());
__processor->scheduler()->remove(this);
}
void Kernel::Processor_client::_yield()
{
assert(__processor->id() == Processor::executing_id());
__processor->scheduler()->yield_occupation();
}

View File

@ -1,5 +1,5 @@
/*
* \brief Provide a processor object for every available processor
* \brief A multiplexable common instruction processor
* \author Martin Stein
* \date 2014-01-14
*/
@ -14,75 +14,103 @@
#ifndef _KERNEL__PROCESSOR_H_
#define _KERNEL__PROCESSOR_H_
/* base includes */
#include <unmanaged_singleton.h>
/* core includes */
#include <kernel/thread.h>
#include <processor_driver.h>
#include <kernel/scheduler.h>
namespace Kernel
{
/**
* Thread that consumes processor time if no other thread is available
* A single user of a multiplexable processor
*/
class Idle_thread;
class Processor_client;
/**
* Representation of a single common instruction processor
* Multiplexes a single processor to multiple processor clients
*/
typedef Scheduler<Processor_client> Processor_scheduler;
/**
* A multiplexable common instruction processor
*/
class Processor;
/**
* Provides a processor object for every provided processor
*/
class Processor_pool;
/**
* Return Processor_pool singleton
*/
Processor_pool * processor_pool();
/**
* Return kernel name of the core protection-domain
*/
unsigned core_id();
}
class Kernel::Idle_thread : public Thread
class Kernel::Processor_client : public Processor_scheduler::Item
{
private:
enum {
STACK_SIZE = 4 * 1024,
STACK_ALIGNM = Processor_driver::DATA_ACCESS_ALIGNM,
};
Processor * __processor;
char _stack[STACK_SIZE] __attribute__((aligned(STACK_ALIGNM)));
protected:
/**
* Main function of all idle threads
* Handle an interrupt exception that occured during execution
*
* \param processor_id kernel name of targeted processor
*/
static void _main()
void _interrupt(unsigned const processor_id);
/**
* Insert context into the processor scheduling
*/
void _schedule();
/**
* Remove context from the processor scheduling
*/
void _unschedule();
/**
* Yield currently scheduled processor share of the context
*/
void _yield();
/***************
** Accessors **
***************/
void _processor(Processor * const processor)
{
while (1) { Processor_driver::wait_for_interrupt(); }
__processor = processor;
}
public:
/**
* Handle an exception that occured during execution
*
* \param processor_id kernel name of targeted processor
*/
virtual void exception(unsigned const processor_id) = 0;
/**
* Continue execution
*
* \param processor_id kernel name of targeted processor
*/
virtual void proceed(unsigned const processor_id) = 0;
/**
* Constructor
*
* \param processor kernel object of targeted processor
* \param priority scheduling priority
*/
Idle_thread(Processor * const processor)
Processor_client(Processor * const processor, Priority const priority)
:
Thread(Priority::MAX, "idle")
Processor_scheduler::Item(priority),
__processor(processor)
{ }
/**
* Destructor
*/
~Processor_client()
{
ip = (addr_t)&_main;
sp = (addr_t)&_stack[STACK_SIZE];
init(processor, core_id(), 0, 0);
if (!_scheduled()) { return; }
_unschedule();
}
};
@ -91,7 +119,6 @@ class Kernel::Processor : public Processor_driver
private:
unsigned const _id;
Idle_thread _idle;
Processor_scheduler _scheduler;
public:
@ -99,11 +126,12 @@ class Kernel::Processor : public Processor_driver
/**
* Constructor
*
* \param id kernel name of the processor object
* \param id kernel name of the processor object
* \param idle_client client that gets scheduled on idle
*/
Processor(unsigned const id)
Processor(unsigned const id, Processor_client * const idle_client)
:
_id(id), _idle(this), _scheduler(&_idle)
_id(id), _scheduler(idle_client)
{ }
@ -116,43 +144,4 @@ class Kernel::Processor : public Processor_driver
Processor_scheduler * scheduler() { return &_scheduler; }
};
class Kernel::Processor_pool
{
private:
char _data[PROCESSORS][sizeof(Processor)];
public:
/**
* Initialize the objects of one of the available processors
*
* \param id kernel name of the targeted processor
*/
Processor_pool()
{
for (unsigned i = 0; i < PROCESSORS; i++) {
new (_data[i]) Processor(i);
}
}
/**
* Return the object of a specific processor
*
* \param id kernel name of the targeted processor
*/
Processor * select(unsigned const id) const
{
return id < PROCESSORS ? (Processor *)_data[id] : 0;
}
/**
* Return the object of the primary processor
*/
Processor * primary() const
{
return (Processor *)_data[Processor::primary_id()];
}
};
#endif /* _KERNEL__PROCESSOR_H_ */

View File

@ -0,0 +1,24 @@
/*
* \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()
{
static Processor_pool s;
return &s;
}

View File

@ -0,0 +1,134 @@
/*
* \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.
*/
#ifndef _KERNEL__PROCESSOR_POOL_H_
#define _KERNEL__PROCESSOR_POOL_H_
/* base includes */
#include <unmanaged_singleton.h>
/* core includes */
#include <kernel/thread.h>
namespace Kernel
{
/**
* Return kernel name of core domain
*/
unsigned core_id();
/**
* 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 = 4 * 1024,
STACK_ALIGNM = Processor_driver::DATA_ACCESS_ALIGNM,
};
char _stack[STACK_SIZE] __attribute__((aligned(STACK_ALIGNM)));
/**
* Main function of all idle threads
*/
static void _main()
{
while (1) { Processor_driver::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_id(), 0, 0);
}
};
class Kernel::Processor_pool
{
private:
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));
}
}
/**
* 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

@ -1,88 +0,0 @@
/*
* \brief Round-robin scheduler
* \author Martin Stein
* \date 2014-02-28
*/
/*
* Copyright (C) 2012-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.h>
#include <kernel/irq.h>
#include <pic.h>
#include <timer.h>
using namespace Kernel;
namespace Kernel
{
Pic * pic();
Timer * timer();
}
void Kernel::Processor_client::_interrupt(unsigned const processor_id)
{
/* determine handling for specific interrupt */
unsigned irq_id;
Pic * const ic = pic();
if (ic->take_request(irq_id))
{
/* check wether the interrupt is a processor-scheduling timeout */
if (timer()->interrupt_id(processor_id) == irq_id) {
__processor->scheduler()->yield_occupation();
timer()->clear_interrupt(processor_id);
/* check wether the interrupt is our inter-processor interrupt */
} else if (ic->is_ip_interrupt(irq_id, processor_id)) {
/*
* This interrupt solely denotes that another processor has
* modified the scheduling plan of this processor and thus
* a more prior user context than the current one might be
* available.
*/
/* after all it must be a user interrupt */
} else {
/* try to inform the user interrupt-handler */
Irq::occurred(irq_id);
}
}
/* end interrupt request at controller */
ic->finish_request();
}
void Kernel::Processor_client::_schedule()
{
/* schedule thread */
__processor->scheduler()->insert(this);
/* let processor of the scheduled thread notice the change immediately */
unsigned const processor_id = __processor->id();
if (processor_id != Processor::executing_id()) {
pic()->trigger_ip_interrupt(processor_id);
}
}
void Kernel::Processor_client::_unschedule()
{
assert(__processor->id() == Processor::executing_id());
__processor->scheduler()->remove(this);
}
void Kernel::Processor_client::_yield()
{
assert(__processor->id() == Processor::executing_id());
__processor->scheduler()->yield_occupation();
}

View File

@ -14,17 +14,12 @@
#ifndef _KERNEL__SCHEDULER_H_
#define _KERNEL__SCHEDULER_H_
/* Genode includes */
#include <util/misc_math.h>
/* core includes */
#include <kernel/configuration.h>
#include <assert.h>
namespace Kernel
{
class Processor;
/**
* Inheritable ability for objects of type T to be item in a double list
*/
@ -53,13 +48,6 @@ namespace Kernel
*/
template <typename T>
class Scheduler;
/**
* Kernel object that can be scheduled for the CPU
*/
class Processor_client;
typedef Scheduler<Processor_client> Processor_scheduler;
}
template <typename T>
@ -306,82 +294,4 @@ class Kernel::Scheduler
T * idle() const { return _idle; }
};
class Kernel::Processor_client : public Processor_scheduler::Item
{
private:
Processor * __processor;
protected:
/**
* Handle an interrupt exception that occured during execution
*
* \param processor_id kernel name of targeted processor
*/
void _interrupt(unsigned const processor_id);
/**
* Insert context into the processor scheduling
*/
void _schedule();
/**
* Remove context from the processor scheduling
*/
void _unschedule();
/**
* Yield currently scheduled processor share of the context
*/
void _yield();
/***************
** Accessors **
***************/
void _processor(Processor * const processor)
{
__processor = processor;
}
public:
/**
* Handle an exception that occured during execution
*
* \param processor_id kernel name of targeted processor
*/
virtual void exception(unsigned const processor_id) = 0;
/**
* Continue execution
*
* \param processor_id kernel name of targeted processor
*/
virtual void proceed(unsigned const processor_id) = 0;
/**
* Constructor
*
* \param processor kernel object of targeted processor
* \param priority scheduling priority
*/
Processor_client(Processor * const processor, Priority const priority)
:
Processor_scheduler::Item(priority),
__processor(processor)
{ }
/**
* Destructor
*/
~Processor_client()
{
if (!_scheduled()) { return; }
_unschedule();
}
};
#endif /* _KERNEL__SCHEDULER_H_ */

View File

@ -366,7 +366,7 @@ void Thread::_call_start_thread()
}
/* lookup targeted processor */
unsigned const processor_id = user_arg_2();
Processor * const processor = processor_pool()->select(processor_id);
Processor * const processor = processor_pool()->processor(processor_id);
if (!processor) {
PERR("unknown processor");
user_arg_0(0);

View File

@ -16,10 +16,9 @@
/* core includes */
#include <kernel/configuration.h>
#include <kernel/scheduler.h>
#include <kernel/signal_receiver.h>
#include <kernel/ipc_node.h>
#include <processor_driver.h>
#include <kernel/processor.h>
#include <cpu_support.h>
namespace Kernel

View File

@ -18,10 +18,9 @@
#include <cpu/cpu_state.h>
/* core includes */
#include <kernel/scheduler.h>
#include <kernel/kernel.h>
#include <kernel/pd.h>
#include <kernel/processor.h>
#include <kernel/processor_pool.h>
#include <kernel/signal_receiver.h>
namespace Kernel
@ -62,7 +61,8 @@ class Kernel::Vm : public Object<Vm, MAX_VMS, Vm_ids, vm_ids, vm_pool>,
Vm(void * const state,
Signal_context * const context)
:
Processor_client(processor_pool()->primary(), Priority::MIN),
Processor_client(processor_pool()->primary_processor(),
Priority::MIN),
_state((Vm_state * const)state),
_context(context)
{ }

View File

@ -52,8 +52,8 @@ SRC_CC += console.cc \
kernel/vm.cc \
kernel/signal_receiver.cc \
kernel/irq.cc \
kernel/scheduler.cc \
kernel/processor.cc \
kernel/processor_pool.cc \
processor_broadcast.cc \
rm_session_support.cc \
trustzone.cc \