From 03ce614c23790f49fa4432c038c69fcf4ac33965 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 3 Apr 2014 14:18:52 +0200 Subject: [PATCH] base: add cpu_session parameter to thread creation Fixes #1114 --- base-codezero/src/base/thread/thread_start.cc | 14 +++++--- base-foc/src/base/thread/thread.cc | 8 ++++- base-foc/src/base/thread/thread_start.cc | 16 +++++---- base-hw/src/base/thread/thread_bootstrap.cc | 7 ++-- base-hw/src/base/thread_support.cc | 10 +++--- base-linux/src/base/thread/thread_linux.cc | 12 ++++--- base-linux/src/platform/lx_hybrid.cc | 25 +++++++------ base-nova/src/base/server/server.cc | 3 +- base-nova/src/base/thread/thread_nova.cc | 16 +++++---- base/include/base/thread.h | 33 +++++++++++++++-- base/run/thread.run | 3 +- base/src/base/thread/thread.cc | 18 ++++++---- base/src/base/thread/thread_start.cc | 15 ++++---- base/src/test/thread/main.cc | 35 +++++++++++++++++++ tool/autopilot.list | 1 + 15 files changed, 156 insertions(+), 60 deletions(-) diff --git a/base-codezero/src/base/thread/thread_start.cc b/base-codezero/src/base/thread/thread_start.cc index e02a81853..7292329f0 100644 --- a/base-codezero/src/base/thread/thread_start.cc +++ b/base-codezero/src/base/thread/thread_start.cc @@ -41,32 +41,36 @@ void Thread_base::_thread_start() void Thread_base::_deinit_platform_thread() { - env()->cpu_session()->kill_thread(_thread_cap); + _cpu_session->kill_thread(_thread_cap); env()->rm_session()->remove_client(_pager_cap); } void Thread_base::start() { + /* if no cpu session is given, use it from the environment */ + if (!_cpu_session) + _cpu_session = env()->cpu_session(); + /* create thread at core */ char buf[48]; name(buf, sizeof(buf)); - _thread_cap = env()->cpu_session()->create_thread(buf); + _thread_cap = _cpu_session->create_thread(buf); /* assign thread to protection domain */ env()->pd_session()->bind_thread(_thread_cap); /* create new pager object and assign it to the new thread */ _pager_cap = env()->rm_session()->add_client(_thread_cap); - env()->cpu_session()->set_pager(_thread_cap, _pager_cap); + _cpu_session->set_pager(_thread_cap, _pager_cap); /* register initial IP and SP at core */ - env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, _context->stack_top()); + _cpu_session->start(_thread_cap, (addr_t)_thread_start, _context->stack_top()); } void Thread_base::cancel_blocking() { Codezero::l4_mutex_unlock(utcb()->running_lock()); - env()->cpu_session()->cancel_blocking(_thread_cap); + _cpu_session->cancel_blocking(_thread_cap); } diff --git a/base-foc/src/base/thread/thread.cc b/base-foc/src/base/thread/thread.cc index a09c38d98..9fbbdb746 100644 --- a/base-foc/src/base/thread/thread.cc +++ b/base-foc/src/base/thread/thread.cc @@ -186,8 +186,10 @@ void Thread_base::free_secondary_stack(void* stack_addr) } -Thread_base::Thread_base(const char *name, size_t stack_size, Type const type) +Thread_base::Thread_base(const char *name, size_t stack_size, Type const type, + Cpu_session *cpu_session) : + _cpu_session(cpu_session), _context(type == REINITIALIZED_MAIN ? _context : _alloc_context(stack_size, type == MAIN)), _join_lock(Lock::LOCKED) @@ -197,6 +199,10 @@ Thread_base::Thread_base(const char *name, size_t stack_size, Type const type) } +Thread_base::Thread_base(const char *name, size_t stack_size, Type type) +: Thread_base(name, stack_size, type, nullptr) { } + + Thread_base::~Thread_base() { _deinit_platform_thread(); diff --git a/base-foc/src/base/thread/thread_start.cc b/base-foc/src/base/thread/thread_start.cc index 605196d38..bf388a5d6 100644 --- a/base-foc/src/base/thread/thread_start.cc +++ b/base-foc/src/base/thread/thread_start.cc @@ -33,7 +33,7 @@ void Thread_base::_deinit_platform_thread() if (_context->utcb && _thread_cap.valid()) { Cap_index *i = (Cap_index*)l4_utcb_tcr_u(_context->utcb)->user[UTCB_TCR_BADGE]; cap_map()->remove(i); - env()->cpu_session()->kill_thread(_thread_cap); + _cpu_session->kill_thread(_thread_cap); env()->rm_session()->remove_client(_pager_cap); } } @@ -41,12 +41,16 @@ void Thread_base::_deinit_platform_thread() void Thread_base::_init_platform_thread(Type type) { + /* if no cpu session is given, use it from the environment */ + if (!_cpu_session) + _cpu_session = env()->cpu_session(); + if (type == NORMAL) { /* create thread at core */ char buf[48]; name(buf, sizeof(buf)); - _thread_cap = env()->cpu_session()->create_thread(buf); + _thread_cap = _cpu_session->create_thread(buf); /* assign thread to protection domain */ env()->pd_session()->bind_thread(_thread_cap); @@ -68,11 +72,11 @@ void Thread_base::start() /* create new pager object and assign it to the new thread */ _pager_cap = env()->rm_session()->add_client(_thread_cap); - env()->cpu_session()->set_pager(_thread_cap, _pager_cap); + _cpu_session->set_pager(_thread_cap, _pager_cap); /* get gate-capability and badge of new thread */ Thread_state state; - try { state = env()->cpu_session()->state(_thread_cap); } + try { state = _cpu_session->state(_thread_cap); } catch (...) { throw Cpu_session::Thread_creation_failed(); } _tid = state.kcap; _context->utcb = state.utcb; @@ -82,11 +86,11 @@ void Thread_base::start() l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this; /* register initial IP and SP at core */ - env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, _context->stack_top()); + _cpu_session->start(_thread_cap, (addr_t)_thread_start, _context->stack_top()); } void Thread_base::cancel_blocking() { - env()->cpu_session()->cancel_blocking(_thread_cap); + _cpu_session->cancel_blocking(_thread_cap); } diff --git a/base-hw/src/base/thread/thread_bootstrap.cc b/base-hw/src/base/thread/thread_bootstrap.cc index 7c3cc925d..8b74d4476 100644 --- a/base-hw/src/base/thread/thread_bootstrap.cc +++ b/base-hw/src/base/thread/thread_bootstrap.cc @@ -73,14 +73,17 @@ void Thread_base::_thread_bootstrap() void Thread_base::_init_platform_thread(Type type) { + /* if no cpu session is given, use it from the environment */ + if (!_cpu_session) + _cpu_session = env()->cpu_session(); + /* nothing platform specific to do if this is not a special thread */ if (type == NORMAL) { /* create server object */ char buf[48]; name(buf, sizeof(buf)); - Cpu_session * cpu = env()->cpu_session(); - _thread_cap = cpu->create_thread(buf, (addr_t)&_context->utcb); + _thread_cap = _cpu_session->create_thread(buf, (addr_t)&_context->utcb); return; } diff --git a/base-hw/src/base/thread_support.cc b/base-hw/src/base/thread_support.cc index da20d9892..5468b1608 100644 --- a/base-hw/src/base/thread_support.cc +++ b/base-hw/src/base/thread_support.cc @@ -52,7 +52,7 @@ void Thread_base::_deinit_platform_thread() env_context_area_rm_session()->detach(utcb); /* destroy server object */ - env()->cpu_session()->kill_thread(_thread_cap); + _cpu_session->kill_thread(_thread_cap); if (_pager_cap.valid()) { env()->rm_session()->remove_client(_pager_cap); } @@ -66,11 +66,11 @@ void Thread_base::start() /* create pager object and assign it to the thread */ _pager_cap = env()->rm_session()->add_client(_thread_cap); - env()->cpu_session()->set_pager(_thread_cap, _pager_cap); + _cpu_session->set_pager(_thread_cap, _pager_cap); /* attach userland thread-context */ try { - Ram_dataspace_capability ds = env()->cpu_session()->utcb(_thread_cap); + Ram_dataspace_capability ds = _cpu_session->utcb(_thread_cap); size_t const size = sizeof(_context->utcb); addr_t dst = Context_allocator::addr_to_base(_context) + Native_config::context_virtual_size() - size - @@ -81,11 +81,11 @@ void Thread_base::start() sleep_forever(); } /* start thread with its initial IP and aligned SP */ - env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, _context->stack_top()); + _cpu_session->start(_thread_cap, (addr_t)_thread_start, _context->stack_top()); } void Thread_base::cancel_blocking() { - env()->cpu_session()->cancel_blocking(_thread_cap); + _cpu_session->cancel_blocking(_thread_cap); } diff --git a/base-linux/src/base/thread/thread_linux.cc b/base-linux/src/base/thread/thread_linux.cc index ba8ad4d42..40678bc16 100644 --- a/base-linux/src/base/thread/thread_linux.cc +++ b/base-linux/src/base/thread/thread_linux.cc @@ -53,7 +53,7 @@ void Thread_base::_thread_start() Thread_base * const thread = Thread_base::myself(); /* inform core about the new thread and process ID of the new thread */ - Linux_cpu_session *cpu = dynamic_cast(env()->cpu_session()); + Linux_cpu_session *cpu = dynamic_cast(thread->_cpu_session); if (cpu) cpu->thread_id(thread->cap(), thread->tid().pid, thread->tid().tid); @@ -71,9 +71,13 @@ void Thread_base::_thread_start() void Thread_base::_init_platform_thread(Type type) { + /* if no cpu session is given, use it from the environment */ + if (!_cpu_session) + _cpu_session = env()->cpu_session(); + /* for normal threads create an object at the CPU session */ if (type == NORMAL) { - _thread_cap = env()->cpu_session()->create_thread(_context->name); + _thread_cap = _cpu_session->create_thread(_context->name); return; } /* adjust initial object state for main threads */ @@ -109,7 +113,7 @@ void Thread_base::_deinit_platform_thread() } /* inform core about the killed thread */ - env()->cpu_session()->kill_thread(_thread_cap); + _cpu_session->kill_thread(_thread_cap); } @@ -141,5 +145,5 @@ void Thread_base::start() void Thread_base::cancel_blocking() { - env()->cpu_session()->cancel_blocking(_thread_cap); + _cpu_session->cancel_blocking(_thread_cap); } diff --git a/base-linux/src/platform/lx_hybrid.cc b/base-linux/src/platform/lx_hybrid.cc index 8fb9f220e..6684d8a80 100644 --- a/base-linux/src/platform/lx_hybrid.cc +++ b/base-linux/src/platform/lx_hybrid.cc @@ -276,9 +276,9 @@ namespace Genode { /** * Return Linux-specific extension of the Env::CPU session interface */ -Linux_cpu_session *cpu_session() +Linux_cpu_session *cpu_session(Cpu_session * cpu_session) { - Linux_cpu_session *cpu = dynamic_cast(env()->cpu_session()); + Linux_cpu_session *cpu = dynamic_cast(cpu_session); if (!cpu) { PERR("could not obtain Linux extension to CPU session interface"); @@ -401,7 +401,9 @@ void Thread_base::join() } -Thread_base::Thread_base(const char *name, size_t stack_size, Type) +Thread_base::Thread_base(const char *name, size_t stack_size, Type type, + Cpu_session * cpu_sess) +: _cpu_session(cpu_sess) { _tid.meta_data = new (env()->heap()) Thread_meta_data_created(this); @@ -416,19 +418,16 @@ Thread_base::Thread_base(const char *name, size_t stack_size, Type) _tid.meta_data->wait_for_construction(); - Linux_cpu_session *cpu = dynamic_cast(env()->cpu_session()); + Linux_cpu_session *cpu = cpu_session(_cpu_session); - if (!cpu) { - PERR("could not obtain Linux extension to CPU session interface"); - struct Could_not_access_linux_cpu_session { }; - throw Could_not_access_linux_cpu_session(); - } - - _thread_cap = cpu_session()->create_thread(name); - cpu_session()->thread_id(_thread_cap, _tid.pid, _tid.tid); + _thread_cap = cpu->create_thread(name); + cpu->thread_id(_thread_cap, _tid.pid, _tid.tid); } +Thread_base::Thread_base(const char *name, size_t stack_size, Type type) +: Thread_base(name, stack_size, type, env()->cpu_session()) { } + void Thread_base::cancel_blocking() { /* @@ -457,5 +456,5 @@ Thread_base::~Thread_base() _tid.meta_data = 0; /* inform core about the killed thread */ - cpu_session()->kill_thread(_thread_cap); + cpu_session(_cpu_session)->kill_thread(_thread_cap); } diff --git a/base-nova/src/base/server/server.cc b/base-nova/src/base/server/server.cc index ea001a333..9c8aa513c 100644 --- a/base-nova/src/base/server/server.cc +++ b/base-nova/src/base/server/server.cc @@ -20,7 +20,6 @@ /* NOVA includes */ #include -#include #include using namespace Genode; @@ -206,7 +205,7 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, /* place new thread on the specified CPU */ if (location.valid()) - env()->cpu_session()->affinity(_thread_cap, location); + _cpu_session->affinity(_thread_cap, location); /* magic value evaluated by thread_nova.cc to start a local thread */ _tid.ec_sel = Native_thread::INVALID_INDEX - 1; diff --git a/base-nova/src/base/thread/thread_nova.cc b/base-nova/src/base/thread/thread_nova.cc index 575cb0bf0..a65f46c9b 100644 --- a/base-nova/src/base/thread/thread_nova.cc +++ b/base-nova/src/base/thread/thread_nova.cc @@ -87,11 +87,15 @@ void Thread_base::_init_platform_thread(Type type) if (_tid.exc_pt_sel == Native_thread::INVALID_INDEX) throw Cpu_session::Thread_creation_failed(); + /* if no cpu session is given, use it from the environment */ + if (!_cpu_session) + _cpu_session = env()->cpu_session(); + /* create thread at core */ char buf[48]; name(buf, sizeof(buf)); - _thread_cap = env()->cpu_session()->create_thread(buf); + _thread_cap = _cpu_session->create_thread(buf); if (!_thread_cap.valid()) throw Cpu_session::Thread_creation_failed(); @@ -121,7 +125,7 @@ void Thread_base::_deinit_platform_thread() /* de-announce thread */ if (_thread_cap.valid()) - env()->cpu_session()->kill_thread(_thread_cap); + _cpu_session->kill_thread(_thread_cap); if (_pager_cap.valid()) env()->rm_session()->remove_client(_pager_cap); @@ -146,7 +150,7 @@ void Thread_base::start() if (!_pager_cap.valid()) throw Cpu_session::Thread_creation_failed(); - if (env()->cpu_session()->set_pager(_thread_cap, _pager_cap)) + if (_cpu_session->set_pager(_thread_cap, _pager_cap)) throw Cpu_session::Thread_creation_failed(); /* create EC at core */ @@ -157,10 +161,10 @@ void Thread_base::start() /* local thread have no start instruction pointer - set via portal entry */ addr_t thread_ip = global ? reinterpret_cast(_thread_start) : 0; - try { env()->cpu_session()->state(_thread_cap, state); } + try { _cpu_session->state(_thread_cap, state); } catch (...) { throw Cpu_session::Thread_creation_failed(); } - if (env()->cpu_session()->start(_thread_cap, thread_ip, _context->stack_top())) + if (_cpu_session->start(_thread_cap, thread_ip, _context->stack_top())) throw Cpu_session::Thread_creation_failed(); /* request native EC thread cap */ @@ -184,7 +188,7 @@ void Thread_base::start() if (global) /* request creation of SC to let thread run*/ - env()->cpu_session()->resume(_thread_cap); + _cpu_session->resume(_thread_cap); } diff --git a/base/include/base/thread.h b/base/include/base/thread.h index 3ac3afc33..bbfa99d95 100644 --- a/base/include/base/thread.h +++ b/base/include/base/thread.h @@ -64,7 +64,7 @@ #include #include /* for 'Ram_dataspace_capability' type */ #include /* for 'Thread_capability' type */ - +#include /* for 'Cpu_session_capability' type */ namespace Genode { @@ -284,6 +284,11 @@ namespace Genode { */ Genode::Pager_capability _pager_cap; + /** + * Pointer to cpu session used for this thread + */ + Genode::Cpu_session *_cpu_session; + /** * Pointer to primary thread context */ @@ -321,7 +326,7 @@ namespace Genode { /** * Hook for platform-specific constructor supplements * - * \param main_thread wether this is the main thread + * \param main_thread whether this is the main thread */ void _init_platform_thread(Type type); @@ -352,6 +357,21 @@ namespace Genode { Thread_base(const char *name, size_t stack_size, Type type = NORMAL); + /** + * Constructor + * + * \param name thread name for debugging + * \param stack_size stack size + * \param type enables selection of special construction + * \param cpu_session capability to cpu session used for construction + * + * \throw Stack_too_large + * \throw Stack_alloc_failed + * \throw Context_alloc_failed + */ + Thread_base(const char *name, size_t stack_size, Type type, + Cpu_session *); + /** * Destructor */ @@ -498,6 +518,15 @@ namespace Genode { */ explicit Thread(const char *name, Type type = NORMAL) : Thread_base(name, STACK_SIZE, type) { } + + /** + * Constructor + * + * \param name thread name (for debugging) + * \param cpu_session thread created via specific cpu session + */ + explicit Thread(const char *name, Cpu_session * cpu_session) + : Thread_base(name, STACK_SIZE, Type::NORMAL, cpu_session) { } }; } diff --git a/base/run/thread.run b/base/run/thread.run index 4a02c6f04..a08610f0f 100644 --- a/base/run/thread.run +++ b/base/run/thread.run @@ -7,6 +7,7 @@ install_config { + @@ -21,6 +22,6 @@ build_boot_image "core init test-thread" append qemu_args "-nographic -m 64" -run_genode_until "child exited with exit value 0.*\n" 10 +run_genode_until "child exited with exit value 0.*\n" 20 puts "Test succeeded" diff --git a/base/src/base/thread/thread.cc b/base/src/base/thread/thread.cc index dae638ba3..e2f531613 100644 --- a/base/src/base/thread/thread.cc +++ b/base/src/base/thread/thread.cc @@ -26,6 +26,7 @@ using namespace Genode; * This function is provided by the process environment. */ namespace Genode { + Rm_session *env_context_area_rm_session(); Ram_session *env_context_area_ram_session(); } @@ -108,7 +109,7 @@ Thread_base::_alloc_context(size_t stack_size, bool main_thread) ds_cap = env_context_area_ram_session()->alloc(ds_size); addr_t attach_addr = ds_addr - Native_config::context_area_virtual_base(); if (attach_addr != (addr_t)env_context_area_rm_session()->attach_at(ds_cap, attach_addr, ds_size)) - throw Stack_alloc_failed(); + throw Stack_alloc_failed(); } catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); } @@ -172,10 +173,7 @@ Thread_base *Thread_base::myself() } -void Thread_base::join() -{ - _join_lock.lock(); -} +void Thread_base::join() { _join_lock.lock(); } void* Thread_base::alloc_secondary_stack(char const *name, size_t stack_size) @@ -193,10 +191,12 @@ void Thread_base::free_secondary_stack(void* stack_addr) } -Thread_base::Thread_base(const char *name, size_t stack_size, Type type) +Thread_base::Thread_base(const char *name, size_t stack_size, Type type, + Cpu_session *cpu_session) : + _cpu_session(cpu_session), _context(type == REINITIALIZED_MAIN ? - _context : _alloc_context(stack_size, type == MAIN)), + _context : _alloc_context(stack_size, type == MAIN)), _join_lock(Lock::LOCKED) { strncpy(_context->name, name, sizeof(_context->name)); @@ -204,6 +204,10 @@ Thread_base::Thread_base(const char *name, size_t stack_size, Type type) } +Thread_base::Thread_base(const char *name, size_t stack_size, Type type) +: Thread_base(name, stack_size, type, nullptr) { } + + Thread_base::~Thread_base() { _deinit_platform_thread(); diff --git a/base/src/base/thread/thread_start.cc b/base/src/base/thread/thread_start.cc index 443390920..17e040cb0 100644 --- a/base/src/base/thread/thread_start.cc +++ b/base/src/base/thread/thread_start.cc @@ -38,31 +38,34 @@ void Thread_base::_thread_start() void Thread_base::_deinit_platform_thread() { - env()->cpu_session()->kill_thread(_thread_cap); + _cpu_session->kill_thread(_thread_cap); } void Thread_base::start() { + /* if no cpu session is given, use it from the environment */ + if (!_cpu_session) + _cpu_session = env()->cpu_session(); + /* create thread at core */ char buf[48]; name(buf, sizeof(buf)); - Cpu_session * cpu = env()->cpu_session(); - _thread_cap = cpu->create_thread(buf, (addr_t)&_context->utcb); + _thread_cap = _cpu_session->create_thread(buf, (addr_t)&_context->utcb); /* assign thread to protection domain */ env()->pd_session()->bind_thread(_thread_cap); /* create new pager object and assign it to the new thread */ Pager_capability pager_cap = env()->rm_session()->add_client(_thread_cap); - env()->cpu_session()->set_pager(_thread_cap, pager_cap); + _cpu_session->set_pager(_thread_cap, pager_cap); /* register initial IP and SP at core */ - env()->cpu_session()->start(_thread_cap, (addr_t)_thread_start, _context->stack_top()); + _cpu_session->start(_thread_cap, (addr_t)_thread_start, _context->stack_top()); } void Thread_base::cancel_blocking() { - env()->cpu_session()->cancel_blocking(_thread_cap); + _cpu_session->cancel_blocking(_thread_cap); } diff --git a/base/src/test/thread/main.cc b/base/src/test/thread/main.cc index e23a8a880..8392da6cb 100644 --- a/base/src/test/thread/main.cc +++ b/base/src/test/thread/main.cc @@ -15,6 +15,8 @@ /* Genode includes */ #include #include +#include +#include using namespace Genode; @@ -149,12 +151,45 @@ static void test_main_thread() } +/****************************************** + ** Using cpu-session for thread creation * + ******************************************/ + +struct Cpu_helper : Thread<0x1000> +{ + Cpu_helper(const char * name, Cpu_session * cpu) + : Thread<0x1000>(name, cpu) { } + + void entry() + { + printf("%s : _cpu_session=0x%p env()->cpu_session()=0x%p\n", _context->name, _cpu_session, env()->cpu_session()); + } +}; + +static void test_cpu_session() +{ + Cpu_helper thread0("prio high ", env()->cpu_session()); + thread0.start(); + thread0.join(); + + Cpu_connection con1("prio middle", Cpu_session::PRIORITY_LIMIT / 4); + Cpu_helper thread1("prio middle", &con1); + thread1.start(); + thread1.join(); + + Cpu_connection con2("prio low", Cpu_session::PRIORITY_LIMIT / 2); + Cpu_helper thread2("prio low ", &con2); + thread2.start(); + thread2.join(); +} + int main() { try { test_context_alloc(); test_stack_alignment(); test_main_thread(); + test_cpu_session(); } catch (int error) { return error; } diff --git a/tool/autopilot.list b/tool/autopilot.list index 9aadeb81d..267487fe5 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -40,3 +40,4 @@ xml_generator blk_cache rump_ext2 virtualbox_auto_disk +thread