mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-07 19:34:56 +00:00
sel4: use notification objects for Genode::Lock
Fixes #1717 Issue #2044
This commit is contained in:
parent
1472c0629b
commit
bee0e11049
@ -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
|
||||
*/
|
||||
|
@ -59,6 +59,7 @@ class Genode::Platform_thread : public List<Platform_thread>::Element
|
||||
*/
|
||||
Cap_sel _fault_handler_sel { 0 };
|
||||
Cap_sel _ep_sel { 0 };
|
||||
Cap_sel _lock_sel { 0 };
|
||||
|
||||
friend class Platform_pd;
|
||||
|
||||
|
@ -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<Endpoint_kobj>(phys_alloc, platform.core_cnode().sel(), ep_sel);
|
||||
|
||||
/* allocate asynchronous object within core's CSpace */
|
||||
lock_sel = platform.core_sel_alloc().alloc();
|
||||
create<Notification_kobj>(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 */
|
||||
|
@ -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<Notification_kobj>(*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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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); \
|
||||
|
@ -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
|
||||
|
@ -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 <base/log.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
/* seL4 includes */
|
||||
#include <base/internal/capability_space_sel4.h>
|
||||
#include <sel4/sel4.h>
|
||||
|
||||
|
||||
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_ */
|
||||
|
@ -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_ */
|
||||
|
@ -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; };
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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 <base/cancelable_lock.h>
|
||||
#include <cpu/atomic.h>
|
||||
#include <cpu/memory_barrier.h>
|
||||
|
||||
/* seL4 includes */
|
||||
#include <sel4/sel4.h>
|
||||
|
||||
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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
#include <base/internal/native_thread.h>
|
||||
#include <base/internal/capability_space_sel4.h>
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user