diff --git a/base-hw/src/core/kernel/kernel.cc b/base-hw/src/core/kernel/kernel.cc index 7cfa269363..fd7b695171 100644 --- a/base-hw/src/core/kernel/kernel.cc +++ b/base-hw/src/core/kernel/kernel.cc @@ -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(); /* diff --git a/base-hw/src/core/kernel/processor.cc b/base-hw/src/core/kernel/processor.cc index b9a569710a..38fad9e099 100644 --- a/base-hw/src/core/kernel/processor.cc +++ b/base-hw/src/core/kernel/processor.cc @@ -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 +#include +#include +#include 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(); } diff --git a/base-hw/src/core/kernel/processor.h b/base-hw/src/core/kernel/processor.h index 12606b46f4..c587763a40 100644 --- a/base-hw/src/core/kernel/processor.h +++ b/base-hw/src/core/kernel/processor.h @@ -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 - /* core includes */ -#include #include +#include 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_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_ */ diff --git a/base-hw/src/core/kernel/processor_pool.cc b/base-hw/src/core/kernel/processor_pool.cc new file mode 100644 index 0000000000..3b2fc2c805 --- /dev/null +++ b/base-hw/src/core/kernel/processor_pool.cc @@ -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 + +using namespace Kernel; + + +Processor_pool * Kernel::processor_pool() +{ + static Processor_pool s; + return &s; +} diff --git a/base-hw/src/core/kernel/processor_pool.h b/base-hw/src/core/kernel/processor_pool.h new file mode 100644 index 0000000000..fee399ccf9 --- /dev/null +++ b/base-hw/src/core/kernel/processor_pool.h @@ -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 + +/* core includes */ +#include + +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(_idle_threads[processor_id]); + return reinterpret_cast(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(_processors[id]); + return reinterpret_cast(p); + } + + /** + * Return the object of the primary processor + */ + Processor * primary_processor() const + { + return processor(Processor::primary_id()); + } +}; + +#endif /* _KERNEL__PROCESSOR_POOL_H_ */ diff --git a/base-hw/src/core/kernel/scheduler.cc b/base-hw/src/core/kernel/scheduler.cc deleted file mode 100644 index 7e0933521f..0000000000 --- a/base-hw/src/core/kernel/scheduler.cc +++ /dev/null @@ -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 -#include -#include -#include - -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(); -} diff --git a/base-hw/src/core/kernel/scheduler.h b/base-hw/src/core/kernel/scheduler.h index 1960cba190..eb4ada4084 100644 --- a/base-hw/src/core/kernel/scheduler.h +++ b/base-hw/src/core/kernel/scheduler.h @@ -14,17 +14,12 @@ #ifndef _KERNEL__SCHEDULER_H_ #define _KERNEL__SCHEDULER_H_ -/* Genode includes */ -#include - /* core includes */ #include #include 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 class Scheduler; - - /** - * Kernel object that can be scheduled for the CPU - */ - class Processor_client; - - typedef Scheduler Processor_scheduler; } template @@ -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_ */ diff --git a/base-hw/src/core/kernel/thread.cc b/base-hw/src/core/kernel/thread.cc index fc5289d3b2..d1e06fb59c 100644 --- a/base-hw/src/core/kernel/thread.cc +++ b/base-hw/src/core/kernel/thread.cc @@ -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); diff --git a/base-hw/src/core/kernel/thread.h b/base-hw/src/core/kernel/thread.h index e5a614808a..428536b2a5 100644 --- a/base-hw/src/core/kernel/thread.h +++ b/base-hw/src/core/kernel/thread.h @@ -16,10 +16,9 @@ /* core includes */ #include -#include #include #include -#include +#include #include namespace Kernel diff --git a/base-hw/src/core/kernel/vm.h b/base-hw/src/core/kernel/vm.h index 8d8dc17775..76cc9dcd4c 100644 --- a/base-hw/src/core/kernel/vm.h +++ b/base-hw/src/core/kernel/vm.h @@ -18,10 +18,9 @@ #include /* core includes */ -#include #include #include -#include +#include #include namespace Kernel @@ -62,7 +61,8 @@ class Kernel::Vm : public Object, 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) { } diff --git a/base-hw/src/core/target.inc b/base-hw/src/core/target.inc index af953f8a70..366be47f4d 100644 --- a/base-hw/src/core/target.inc +++ b/base-hw/src/core/target.inc @@ -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 \