diff --git a/repos/base-sel4/src/core/include/cnode.h b/repos/base-sel4/src/core/include/cnode.h index ee113a6a6..964663790 100644 --- a/repos/base-sel4/src/core/include/cnode.h +++ b/repos/base-sel4/src/core/include/cnode.h @@ -66,6 +66,26 @@ class Genode::Cnode_base void copy(Cnode_base const &from, Index idx) { copy(from, idx, idx); } + /** + * Mint selector from another CNode + */ + void mint(Cnode_base const &from, Index from_idx, Index to_idx) + { + seL4_CNode const service = sel().value(); + seL4_Word const dest_index = to_idx.value(); + uint8_t const dest_depth = size_log2(); + seL4_CNode const src_root = from.sel().value(); + seL4_Word const src_index = from_idx.value(); + uint8_t const src_depth = from.size_log2(); + seL4_CapRights const rights = seL4_AllRights; + seL4_CapData_t const badge = seL4_CapData_Badge_new(to_idx.value()); + + int const ret = seL4_CNode_Mint(service, dest_index, dest_depth, + src_root, src_index, src_depth, + rights, badge); + ASSERT(ret == seL4_NoError); + } + /** * Delete selector from CNode */ diff --git a/repos/base-sel4/src/core/include/platform_thread.h b/repos/base-sel4/src/core/include/platform_thread.h index d6ffdd1e3..1aacf8cdb 100644 --- a/repos/base-sel4/src/core/include/platform_thread.h +++ b/repos/base-sel4/src/core/include/platform_thread.h @@ -59,6 +59,7 @@ class Genode::Platform_thread : public List::Element */ Cap_sel _fault_handler_sel { 0 }; Cap_sel _ep_sel { 0 }; + Cap_sel _lock_sel { 0 }; friend class Platform_pd; diff --git a/repos/base-sel4/src/core/include/thread_sel4.h b/repos/base-sel4/src/core/include/thread_sel4.h index bb6852c87..ebfe54176 100644 --- a/repos/base-sel4/src/core/include/thread_sel4.h +++ b/repos/base-sel4/src/core/include/thread_sel4.h @@ -34,6 +34,7 @@ namespace Genode { { Cap_sel tcb_sel { 0 }; Cap_sel ep_sel { 0 }; + Cap_sel lock_sel { 0 }; addr_t ipc_buffer_phys = 0; @@ -42,6 +43,8 @@ namespace Genode { Thread_info() { } inline void init(addr_t const utcb_virt_addr); + inline void destruct(); + }; /** @@ -69,6 +72,10 @@ void Genode::Thread_info::init(addr_t const utcb_virt_addr) ep_sel = platform.core_sel_alloc().alloc(); create(phys_alloc, platform.core_cnode().sel(), ep_sel); + /* allocate asynchronous object within core's CSpace */ + lock_sel = platform.core_sel_alloc().alloc(); + create(phys_alloc, platform.core_cnode().sel(), lock_sel); + /* assign IPC buffer to thread */ { /* determine page frame selector of the allocated IPC buffer */ @@ -85,6 +92,30 @@ void Genode::Thread_info::init(addr_t const utcb_virt_addr) } +void Genode::Thread_info::destruct() +{ + if (lock_sel.value()) { + seL4_CNode_Delete(seL4_CapInitThreadCNode, lock_sel.value(), 32); + platform_specific()->core_sel_alloc().free(lock_sel); + } + if (ep_sel.value()) { + seL4_CNode_Delete(seL4_CapInitThreadCNode, ep_sel.value(), 32); + platform_specific()->core_sel_alloc().free(ep_sel); + } + if (tcb_sel.value()) { + seL4_CNode_Delete(seL4_CapInitThreadCNode, tcb_sel.value(), 32); + platform_specific()->core_sel_alloc().free(tcb_sel); + } + + if (ipc_buffer_phys) { + Platform &platform = *platform_specific(); + Range_allocator &phys_alloc = *platform.ram_alloc(); + Untyped_memory::convert_to_untyped_frames(ipc_buffer_phys, 4096); + Untyped_memory::free_page(phys_alloc, ipc_buffer_phys); + } +} + + void Genode::start_sel4_thread(Cap_sel tcb_sel, addr_t ip, addr_t sp) { /* set register values for the instruction pointer and stack pointer */ diff --git a/repos/base-sel4/src/core/platform.cc b/repos/base-sel4/src/core/platform.cc index c52d43adb..c61d4d085 100644 --- a/repos/base-sel4/src/core/platform.cc +++ b/repos/base-sel4/src/core/platform.cc @@ -430,6 +430,22 @@ Platform::Platform() _core_page_table_registry, "core") { + /* create notification object for Genode::Lock used by this first thread */ + Cap_sel lock_sel (INITIAL_SEL_LOCK); + Cap_sel core_sel = _core_sel_alloc.alloc(); + + create(*ram_alloc(), core_cnode().sel(), core_sel); + + /* mint a copy of the notification object with badge of lock_sel */ + _core_cnode.mint(_core_cnode, core_sel, lock_sel); + + /* test signal/wakeup once */ + seL4_Word sender; + seL4_Signal(lock_sel.value()); + seL4_Wait(lock_sel.value(), &sender); + + ASSERT(sender == INITIAL_SEL_LOCK); + /* I/O port allocator (only meaningful for x86) */ _io_port_alloc.add_range(0, 0x10000); diff --git a/repos/base-sel4/src/core/platform_pd.cc b/repos/base-sel4/src/core/platform_pd.cc index e29711371..7f96cacab 100644 --- a/repos/base-sel4/src/core/platform_pd.cc +++ b/repos/base-sel4/src/core/platform_pd.cc @@ -61,11 +61,17 @@ bool Platform_pd::bind_thread(Platform_thread *thread) thread->_fault_handler_sel = alloc_sel(); /* allocate endpoint selector in the PD's CSpace */ thread->_ep_sel = alloc_sel(); + /* allocate asynchronous selector used for locks in the PD's CSpace */ + thread->_lock_sel = thread->_utcb ? alloc_sel() : Cap_sel(INITIAL_SEL_LOCK); } catch (Platform_pd::Sel_bit_alloc::Out_of_indices) { if (thread->_fault_handler_sel.value()) { free_sel(thread->_fault_handler_sel); thread->_fault_handler_sel = Cap_sel(0); } + if (thread->_ep_sel.value()) { + free_sel(thread->_ep_sel); + thread->_ep_sel = Cap_sel(0); + } return false; } @@ -95,6 +101,11 @@ void Platform_pd::unbind_thread(Platform_thread *thread) if (!thread) return; + if (thread->_utcb) + free_sel(thread->_lock_sel); + free_sel(thread->_fault_handler_sel); + free_sel(thread->_ep_sel); + if (thread->_utcb) _vm_space.unmap(thread->_utcb, 1); else diff --git a/repos/base-sel4/src/core/platform_thread.cc b/repos/base-sel4/src/core/platform_thread.cc index 120a1e43e..7b1f8aecf 100644 --- a/repos/base-sel4/src/core/platform_thread.cc +++ b/repos/base-sel4/src/core/platform_thread.cc @@ -80,7 +80,8 @@ void Genode::install_mapping(Mapping const &mapping, unsigned long pager_object_ ** Utilities to support the Platform_thread interface ** ********************************************************/ -static void prepopulate_ipc_buffer(addr_t ipc_buffer_phys, Cap_sel ep_sel) +static void prepopulate_ipc_buffer(addr_t ipc_buffer_phys, Cap_sel ep_sel, + Cap_sel lock_sel) { /* IPC buffer is one page */ size_t const page_rounded_size = get_page_size(); @@ -99,6 +100,7 @@ static void prepopulate_ipc_buffer(addr_t ipc_buffer_phys, Cap_sel ep_sel) /* populate IPC buffer with thread information */ Native_utcb &utcb = *(Native_utcb *)virt_addr; utcb.ep_sel = ep_sel.value(); + utcb.lock_sel = lock_sel.value(); /* unmap IPC buffer from core */ unmap_local((addr_t)virt_addr, 1); @@ -128,12 +130,16 @@ int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no) _pd->cspace_cnode(_ep_sel).copy(platform_specific()->core_cnode(), _info.ep_sel, _ep_sel); + /* install the thread's notification object to the PD's CSpace */ + _pd->cspace_cnode(_lock_sel).mint(platform_specific()->core_cnode(), + _info.lock_sel, _lock_sel); + /* * Populate the thread's IPC buffer with initial information about the * thread. Once started, the thread picks up this information in the * 'Thread::_thread_bootstrap' method. */ - prepopulate_ipc_buffer(_info.ipc_buffer_phys, _ep_sel); + prepopulate_ipc_buffer(_info.ipc_buffer_phys, _ep_sel, _lock_sel); /* bind thread to PD and CSpace */ seL4_CapData_t const guard_cap_data = @@ -211,7 +217,7 @@ Thread_state Platform_thread::state() void Platform_thread::cancel_blocking() { - warning(__PRETTY_FUNCTION__, " not implemented"); + seL4_Signal(_info.lock_sel.value()); } @@ -248,6 +254,16 @@ Platform_thread::~Platform_thread() _pd->unbind_thread(this); } + if (_pager) { + Cap_sel const pager_sel(Capability_space::ipc_cap_data(_pager->cap()).sel); + seL4_CNode_Revoke(seL4_CapInitThreadCNode, pager_sel.value(), 32); + } + + seL4_CNode_Revoke(seL4_CapInitThreadCNode, _info.lock_sel.value(), 32); + seL4_CNode_Revoke(seL4_CapInitThreadCNode, _info.ep_sel.value(), 32); + + _info.destruct(); + platform_thread_registry().remove(*this); platform_specific()->core_sel_alloc().free(_pager_obj_sel); } diff --git a/repos/base-sel4/src/core/thread_start.cc b/repos/base-sel4/src/core/thread_start.cc index 50955f07e..ef2e50562 100644 --- a/repos/base-sel4/src/core/thread_start.cc +++ b/repos/base-sel4/src/core/thread_start.cc @@ -33,6 +33,7 @@ void Thread::_init_platform_thread(size_t, Type type) if (type == MAIN) { native_thread().tcb_sel = seL4_CapInitThreadTCB; + native_thread().lock_sel = INITIAL_SEL_LOCK; return; } @@ -44,8 +45,9 @@ void Thread::_init_platform_thread(size_t, Type type) thread_info.ipc_buffer_phys, utcb_virt_addr); } - native_thread().tcb_sel = thread_info.tcb_sel.value(); - native_thread().ep_sel = thread_info.ep_sel.value(); + native_thread().tcb_sel = thread_info.tcb_sel.value(); + native_thread().ep_sel = thread_info.ep_sel.value(); + native_thread().lock_sel = thread_info.lock_sel.value(); Platform &platform = *platform_specific(); @@ -53,7 +55,15 @@ void Thread::_init_platform_thread(size_t, Type type) int const ret = seL4_TCB_SetSpace(native_thread().tcb_sel, 0, platform.top_cnode().sel().value(), no_cap_data, seL4_CapInitThreadPD, no_cap_data); - ASSERT(ret == 0); + ASSERT(ret == seL4_NoError); + + /* mint notification object with badge - used by Genode::Lock */ + Cap_sel unbadged_sel = thread_info.lock_sel; + Cap_sel lock_sel = platform.core_sel_alloc().alloc(); + + platform.core_cnode().mint(platform.core_cnode(), unbadged_sel, lock_sel); + + native_thread().lock_sel = lock_sel.value(); } diff --git a/repos/base-sel4/src/include/base/internal/assert.h b/repos/base-sel4/src/include/base/internal/assert.h index 2b4229043..fe0700f17 100644 --- a/repos/base-sel4/src/include/base/internal/assert.h +++ b/repos/base-sel4/src/include/base/internal/assert.h @@ -26,7 +26,7 @@ #define ASSERT(e) \ do { if (!(e)) { \ char line_buf[32]; \ - snprintf(line_buf, sizeof(line_buf), "%d", __LINE__); \ + Genode::snprintf(line_buf, sizeof(line_buf), "%d", __LINE__); \ kernel_debugger_outstring(ESC_ERR "Assertion failed: " #e ESC_END "\n"); \ kernel_debugger_outstring(__FILE__ ":"); \ kernel_debugger_outstring(line_buf); \ diff --git a/repos/base-sel4/src/include/base/internal/capability_space_sel4.h b/repos/base-sel4/src/include/base/internal/capability_space_sel4.h index 342f3fd3c..eefed772e 100644 --- a/repos/base-sel4/src/include/base/internal/capability_space_sel4.h +++ b/repos/base-sel4/src/include/base/internal/capability_space_sel4.h @@ -95,6 +95,7 @@ namespace Genode { namespace Capability_space { namespace Genode { enum { + INITIAL_SEL_LOCK = 0, INITIAL_SEL_PARENT = 1, INITIAL_SEL_CNODE = 2, INITIAL_SEL_END diff --git a/repos/base-sel4/src/include/base/internal/lock_helper.h b/repos/base-sel4/src/include/base/internal/lock_helper.h index 8f2c9a95f..9fc81e315 100644 --- a/repos/base-sel4/src/include/base/internal/lock_helper.h +++ b/repos/base-sel4/src/include/base/internal/lock_helper.h @@ -2,12 +2,10 @@ * \brief seL4-specific helper functions for the Lock implementation * \author Norman Feske * \date 2015-05-07 - * - * Based on the lock implementation of base-fiasco/src/base/lock/. */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2016 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. @@ -16,10 +14,47 @@ #ifndef _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ #define _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ +#include +#include + /* seL4 includes */ +#include #include static inline void thread_yield() { seL4_Yield(); } + +static inline void thread_switch_to(Genode::Thread *thread) +{ + Genode::warning(__FUNCTION__, " not implemented"); +} + + +static inline bool thread_check_stopped_and_restart(Genode::Thread *thread) +{ + unsigned lock_sel = Genode::INITIAL_SEL_LOCK; /* main thread */ + + if (thread) + lock_sel = thread->native_thread().lock_sel; + + seL4_Signal(lock_sel); + + return true; +} + + +static inline void thread_stop_myself() +{ + Genode::Thread *myself = Genode::Thread::myself(); + + unsigned lock_sel = Genode::INITIAL_SEL_LOCK; /* main thread */ + + if (myself) + lock_sel = Genode::Thread::myself()->native_thread().lock_sel; + + seL4_Word sender = ~0U; + seL4_Wait(lock_sel, &sender); +} + #endif /* _INCLUDE__BASE__INTERNAL__LOCK_HELPER_H_ */ diff --git a/repos/base-sel4/src/include/base/internal/native_thread.h b/repos/base-sel4/src/include/base/internal/native_thread.h index ff9c96af6..b1350c718 100644 --- a/repos/base-sel4/src/include/base/internal/native_thread.h +++ b/repos/base-sel4/src/include/base/internal/native_thread.h @@ -23,6 +23,7 @@ struct Genode::Native_thread unsigned tcb_sel = 0; unsigned ep_sel = 0; unsigned rcv_sel = 0; + unsigned lock_sel = 0; }; #endif /* _INCLUDE__BASE__INTERNAL__NATIVE_THREAD_H_ */ diff --git a/repos/base-sel4/src/include/base/internal/native_utcb.h b/repos/base-sel4/src/include/base/internal/native_utcb.h index b404bfbb4..effc319de 100644 --- a/repos/base-sel4/src/include/base/internal/native_utcb.h +++ b/repos/base-sel4/src/include/base/internal/native_utcb.h @@ -30,7 +30,7 @@ struct Genode::Native_utcb addr_t raw[IPC_BUFFER_SIZE/sizeof(addr_t)]; - struct { addr_t ep_sel; }; + struct { addr_t ep_sel; addr_t lock_sel; }; }; }; diff --git a/repos/base-sel4/src/lib/base/lock.cc b/repos/base-sel4/src/lib/base/lock.cc deleted file mode 100644 index 45fe97c53..000000000 --- a/repos/base-sel4/src/lib/base/lock.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * \brief Lock implementation - * \author Norman Feske - * \date 2007-10-15 - */ - -/* - * Copyright (C) 2007-2013 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 - -/* seL4 includes */ -#include - -using namespace Genode; - - -Cancelable_lock::Cancelable_lock(Cancelable_lock::State initial) -: _state(UNLOCKED), _owner(nullptr) -{ - if (initial == LOCKED) - lock(); -} - - -void Cancelable_lock::lock() -{ - while (!Genode::cmpxchg(&_state, UNLOCKED, LOCKED)) - seL4_Yield(); -} - - -void Cancelable_lock::unlock() -{ - Genode::memory_barrier(); - _state = UNLOCKED; -} diff --git a/repos/base-sel4/src/lib/base/thread_bootstrap.cc b/repos/base-sel4/src/lib/base/thread_bootstrap.cc index f6919dcfa..a443f6fef 100644 --- a/repos/base-sel4/src/lib/base/thread_bootstrap.cc +++ b/repos/base-sel4/src/lib/base/thread_bootstrap.cc @@ -34,5 +34,6 @@ void Genode::Thread::_thread_bootstrap() { if (native_thread().ep_sel == 0) { native_thread().ep_sel = _stack->utcb().ep_sel; + native_thread().lock_sel = _stack->utcb().lock_sel; } } diff --git a/repos/base-sel4/src/lib/base/thread_init.cc b/repos/base-sel4/src/lib/base/thread_init.cc index f46086baa..66ce9a5b5 100644 --- a/repos/base-sel4/src/lib/base/thread_init.cc +++ b/repos/base-sel4/src/lib/base/thread_init.cc @@ -14,6 +14,7 @@ /* Genode includes */ #include #include +#include using namespace Genode; @@ -25,4 +26,9 @@ void Thread::_init_platform_thread(size_t, Type type) * and associations the thread, like IPCbuffer in ipc.cc. */ native_thread() = Native_thread(); + + if (type == MAIN) { + native_thread().lock_sel = INITIAL_SEL_LOCK; + return; + } }