From 56e4588e9121e6c1138bb5b0b0b47e7e7c5ae4ff Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Fri, 7 Mar 2014 15:55:02 +0100 Subject: [PATCH] hw: provide processor broadcasts in core A processor broadcast executes a function on all available processors which is needed at least to do MMU cache-flushes globally. ref #1076 --- .../src/core/include/processor_broadcast.h | 207 ++++++++++++++++++ base-hw/src/core/processor_broadcast.cc | 24 ++ base-hw/src/core/target.inc | 1 + 3 files changed, 232 insertions(+) create mode 100644 base-hw/src/core/include/processor_broadcast.h create mode 100644 base-hw/src/core/processor_broadcast.cc diff --git a/base-hw/src/core/include/processor_broadcast.h b/base-hw/src/core/include/processor_broadcast.h new file mode 100644 index 0000000000..88e5b7de07 --- /dev/null +++ b/base-hw/src/core/include/processor_broadcast.h @@ -0,0 +1,207 @@ +/* + * \brief Utility to execute a function on all available processors + * \author Martin Stein + * \date 2014-03-07 + */ + +/* + * 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 _PROCESSOR_BROADCAST_H_ +#define _PROCESSOR_BROADCAST_H_ + +/* Genode includes */ +#include +#include + +namespace Genode { + + enum { PROCESSOR_BROADCAST_RECEIVER_STACK_SIZE = 4 * 1024 }; + + /** + * Functionality that can be broadcasted on all available processors + */ + class Processor_broadcast_operation; + + /** + * Wrapper for the signalling between broadcast and receiver + */ + class Processor_broadcast_signal; + + /** + * Processor local receiver of broadcasted functions + */ + class Processor_broadcast_receiver; + + /** + * Executes a function on all available processors + */ + class Processor_broadcast; + + /** + * Return broadcast singleton + */ + Processor_broadcast * processor_broadcast(); +} + +class Genode::Processor_broadcast_operation +{ + public: + + typedef void (*Entry)(void * const); + + private: + + Entry const _entry; + void * const _data; + + public: + + /** + * Constructor + * + * \param entry entry to the operation code + * \param data pointer to operation specific input/output data + */ + Processor_broadcast_operation(Entry const entry, void * const data) + : + _entry(entry), _data(data) + { } + + /** + * Execute operation processor-locally + */ + void execute() const { _entry(_data); } +}; + +class Genode::Processor_broadcast_signal +{ + private: + + Signal_context _context; + Signal_receiver _receiver; + Signal_transmitter _transmitter; + + public: + + /** + * Constructor + */ + Processor_broadcast_signal() + : + _transmitter(_receiver.manage(&_context)) + { } + + /** + * Submit the signal + */ + void submit() { _transmitter.submit(); } + + /** + * Wait for signal submission + */ + void await() { _receiver.wait_for_signal(); } +}; + +class Genode::Processor_broadcast_receiver +: + public Thread +{ + private: + + typedef Processor_broadcast_operation Operation; + typedef Processor_broadcast_signal Signal; + + Operation const * _operation; + Signal _start; + Signal _end; + + public: + + /** + * Constructor + */ + Processor_broadcast_receiver() : Thread("processor_broadcast") { } + + /** + * Start receiver on a specific processor + * + * \param processor_id kernel name of targeted processor + */ + void init(unsigned const processor_id) + { + Thread::utcb()->core_start_info()->init(processor_id); + Thread::start(); + } + + /** + * Start remote execution of an operation + * + * \param operation desired operation + */ + void start_executing(Operation const * const operation) + { + _operation = operation; + _start.submit(); + } + + /** + * Wait until the remote execution of the current operation is done + */ + void end_executing() { _end.await(); } + + + /***************** + ** Thread_base ** + *****************/ + + void entry() + { + while (1) { + _start.await(); + _operation->execute(); + _end.submit(); + } + } +}; + +class Genode::Processor_broadcast +{ + private: + + typedef Processor_broadcast_operation Operation; + typedef Processor_broadcast_receiver Receiver; + + Receiver _receiver[PROCESSORS]; + + public: + + /** + * Constructor + */ + Processor_broadcast() + { + for (unsigned i = 0; i < PROCESSORS; i++) { _receiver[i].init(i); } + } + + /** + * Execute operation on all available processors + * + * \param operation desired operation + */ + void execute(Operation const * const operation) + { + for (unsigned i = 0; i < PROCESSORS; i++) { + _receiver[i].start_executing(operation); + } + for (unsigned i = 0; i < PROCESSORS; i++) { + _receiver[i].end_executing(); + } + } +}; + +#endif /* _PROCESSOR_BROADCAST_H_ */ diff --git a/base-hw/src/core/processor_broadcast.cc b/base-hw/src/core/processor_broadcast.cc new file mode 100644 index 0000000000..97231d5cd1 --- /dev/null +++ b/base-hw/src/core/processor_broadcast.cc @@ -0,0 +1,24 @@ +/* + * \brief Utility to execute a function on all available processors + * \author Martin Stein + * \date 2014-03-07 + */ + +/* + * 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 Genode; + + +Processor_broadcast * Genode::processor_broadcast() +{ + static Processor_broadcast s; + return &s; +} diff --git a/base-hw/src/core/target.inc b/base-hw/src/core/target.inc index 17beb827ea..af953f8a70 100644 --- a/base-hw/src/core/target.inc +++ b/base-hw/src/core/target.inc @@ -54,6 +54,7 @@ SRC_CC += console.cc \ kernel/irq.cc \ kernel/scheduler.cc \ kernel/processor.cc \ + processor_broadcast.cc \ rm_session_support.cc \ trustzone.cc \ pager.cc \