/* * \brief NOVA-specific implementation of the Thread API * \author Norman Feske * \author Sebastian Sumpf * \date 2010-01-19 */ /* * Copyright (C) 2010-2012 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. */ /* Genode includes */ #include #include #include #include #include #include #include /* NOVA includes */ #include #include #include using namespace Genode; /** * Entry point entered by new threads */ void Thread_base::_thread_start() { Genode::Thread_base::myself()->entry(); Genode::sleep_forever(); } /***************** ** Thread base ** *****************/ void Thread_base::_init_platform_thread() { using namespace Nova; /* * Allocate capability selectors for the thread's execution context, * running semaphore and exception handler portals. */ _tid.ec_sel = ~0UL; _tid.rs_sel = cap_selector_allocator()->alloc(); _tid.pd_sel = cap_selector_allocator()->pd_sel(); _tid.exc_pt_sel = cap_selector_allocator()->alloc(NUM_INITIAL_PT_LOG2); /* create thread at core */ char buf[48]; name(buf, sizeof(buf)); _thread_cap = env()->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_capability pager_cap = env()->rm_session()->add_client(_thread_cap); env()->cpu_session()->set_pager(_thread_cap, pager_cap); /* create running semaphore required for locking */ uint8_t res = create_sm(_tid.rs_sel, _tid.pd_sel, 0); if (res != NOVA_OK) { PERR("create_sm returned %u", res); throw Cpu_session::Thread_creation_failed(); } } void Thread_base::_deinit_platform_thread() { // Nova::revoke(Nova::Obj_crd(_tid.ec_sel, 0)); Nova::revoke(Nova::Obj_crd(_tid.rs_sel, 0)); Nova::revoke(Nova::Obj_crd(_tid.exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2)); // cap_selector_allocator()->free(_tid.ec_sel, 0); cap_selector_allocator()->free(_tid.rs_sel, 0); cap_selector_allocator()->free(_tid.exc_pt_sel, Nova::NUM_INITIAL_PT_LOG2); /* revoke utcb */ Nova::Rights rwx(true, true, true); addr_t utcb = reinterpret_cast(&_context->utcb); Nova::revoke(Nova::Mem_crd(utcb >> 12, 0, rwx)); /* de-announce thread */ env()->cpu_session()->kill_thread(_thread_cap); revoke(_thread_cap.local_name(), 0); cap_selector_allocator()->free(_thread_cap.local_name(), 0); } void Thread_base::start() { if (_tid.ec_sel != ~0UL) throw Cpu_session::Thread_creation_failed(); using namespace Genode; /* 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); /* create EC at core */ addr_t thread_sp = reinterpret_cast(&_context->stack[-4]); Genode::Nova_cpu_connection cpu; if (cpu.start_exc_base_vcpu(_thread_cap, (addr_t)_thread_start, thread_sp, _tid.exc_pt_sel)) throw Cpu_session::Thread_creation_failed(); /* request native EC thread cap */ Native_capability ec_cap = cpu.native_cap(_thread_cap); _tid.ec_sel = ec_cap.local_name(); using namespace Nova; /* request exception portals */ request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_STARTUP); request_event_portal(pager_cap, _tid.exc_pt_sel, PT_SEL_PAGE_FAULT); /* request creation of SC to let thread run*/ env()->cpu_session()->resume(_thread_cap); } void Thread_base::cancel_blocking() { Nova::sm_ctrl(_tid.rs_sel, Nova::SEMAPHORE_UP); }