mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-08 04:10:27 +00:00
base: hide internals of the Thread API
This patch moves details about the stack allocation and organization the base-internal headers. Thereby, I replaced the notion of "thread contexts" by "stacks" as this term is much more intuitive. The fact that we place thread-specific information at the bottom of the stack is not worth introducing new terminology. Issue #1832
This commit is contained in:
parent
3c686fc9c6
commit
7f73e5e879
@ -65,7 +65,7 @@ namespace Genode {
|
||||
/**
|
||||
* Empty UTCB type expected by the thread library
|
||||
*
|
||||
* On this kernel, UTCBs are not placed within the the context area. Each
|
||||
* On this kernel, UTCBs are not placed within the the stack area. Each
|
||||
* thread can request its own UTCB pointer using the kernel interface.
|
||||
*/
|
||||
typedef struct { } Native_utcb;
|
||||
@ -76,17 +76,17 @@ namespace Genode {
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration.
|
||||
* Stack area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
static constexpr addr_t stack_area_virtual_base() {
|
||||
return 0x40000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
|
||||
struct Native_pd_args { };
|
||||
|
@ -21,7 +21,7 @@ SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/context_allocator.cc
|
||||
SRC_CC += thread/stack_allocator.cc
|
||||
SRC_CC += sleep.cc
|
||||
SRC_CC += rm_session_client.cc
|
||||
|
||||
|
@ -8,7 +8,7 @@ LIBS += base-common
|
||||
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += cpu/cache.cc
|
||||
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc
|
||||
SRC_CC += env/env.cc env/stack_area.cc env/reinitialize.cc
|
||||
SRC_CC += thread/thread_start.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
SRC_CC += server/rpc_cap_alloc.cc
|
||||
|
@ -306,8 +306,8 @@ void Platform::_setup_mem_alloc()
|
||||
}
|
||||
|
||||
region.start = addr; region.end = addr + size;
|
||||
if (!region.intersects(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size())) {
|
||||
if (!region.intersects(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size())) {
|
||||
add_region(region, _ram_alloc);
|
||||
add_region(region, _core_address_ranges());
|
||||
}
|
||||
@ -411,9 +411,9 @@ void Platform::_setup_basics()
|
||||
_vm_start = _vm_start == 0 ? L4_PAGESIZE : _vm_start;
|
||||
_region_alloc.add_range(_vm_start, _vm_size);
|
||||
|
||||
/* preserve context area in core's virtual address space */
|
||||
_region_alloc.remove_range(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size());
|
||||
/* preserve stack area in core's virtual address space */
|
||||
_region_alloc.remove_range(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size());
|
||||
|
||||
/* I/O memory could be the whole user address space */
|
||||
/* FIXME if the kernel helps to find out max address - use info here */
|
||||
|
@ -2,7 +2,7 @@ TARGET = core
|
||||
|
||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
||||
SRC_CC += context_area.cc \
|
||||
SRC_CC += stack_area.cc \
|
||||
core_printf.cc \
|
||||
core_rpc_cap_alloc.cc \
|
||||
cpu_session_component.cc \
|
||||
@ -62,7 +62,7 @@ vpath signal_source_component.cc $(GEN_CORE_DIR)
|
||||
vpath trace_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath dataspace_component.cc $(GEN_CORE_DIR)
|
||||
vpath dump_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath context_area.cc $(GEN_CORE_DIR)
|
||||
vpath stack_area.cc $(GEN_CORE_DIR)
|
||||
vpath pager_object.cc $(GEN_CORE_DIR)
|
||||
vpath pager_ep.cc $(GEN_CORE_DIR)
|
||||
vpath core_printf.cc $(BASE_DIR)/src/base/console
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include <base/thread.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <core_env.h>
|
||||
@ -35,7 +38,7 @@ void Thread_base::start()
|
||||
{
|
||||
/* create and start platform thread */
|
||||
_tid.pt = new(platform()->core_mem_alloc())
|
||||
Platform_thread(0, _context->name);
|
||||
Platform_thread(0, _stack->name().string());
|
||||
|
||||
platform_specific()->core_pd()->bind_thread(_tid.pt);
|
||||
|
||||
|
@ -82,9 +82,29 @@ namespace Fiasco {
|
||||
namespace Genode {
|
||||
|
||||
typedef Fiasco::l4_cap_idx_t Native_thread_id;
|
||||
typedef Fiasco::l4_cap_idx_t Native_thread;
|
||||
|
||||
|
||||
struct Native_thread
|
||||
{
|
||||
Fiasco::l4_cap_idx_t kcap = 0;
|
||||
|
||||
Native_thread() { }
|
||||
explicit Native_thread(Fiasco::l4_cap_idx_t kcap) : kcap(kcap) { }
|
||||
};
|
||||
|
||||
|
||||
typedef Fiasco::l4_cap_idx_t Native_task;
|
||||
typedef Fiasco::l4_utcb_t* Native_utcb;
|
||||
|
||||
|
||||
struct Native_utcb
|
||||
{
|
||||
/*
|
||||
* The 'Native_utcb' is located within the stack slot of the thread.
|
||||
* We merely use it for remembering a pointer to the real UTCB, which
|
||||
* resides somewhere in the kernel's address space.
|
||||
*/
|
||||
Fiasco::l4_utcb_t *foc_utcb = nullptr;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
|
@ -24,9 +24,9 @@ namespace Genode {
|
||||
|
||||
struct Thread_state : Thread_state_base
|
||||
{
|
||||
Native_thread kcap; /* thread's gate cap in its pd */
|
||||
Fiasco::l4_cap_idx_t kcap; /* thread's gate cap in its pd */
|
||||
int id; /* id of gate capability */
|
||||
Native_utcb utcb; /* thread's utcb in its pd */
|
||||
addr_t utcb; /* thread's utcb in its pd */
|
||||
unsigned exceptions; /* counts exceptions raised by the thread */
|
||||
bool paused; /* indicates whether thread is stopped */
|
||||
bool in_exception; /* true if thread is in exception */
|
||||
|
@ -53,7 +53,7 @@ namespace Genode {
|
||||
_sem = call<Rpc_request_semaphore>();
|
||||
|
||||
l4_msgtag_t tag = l4_irq_attach(_sem.dst(), 0,
|
||||
Thread_base::myself()->tid());
|
||||
Thread_base::myself()->tid().kcap);
|
||||
if (l4_error(tag))
|
||||
PERR("l4_irq_attach failed with %ld!", l4_error(tag));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Platform-specific context area definitions
|
||||
* \brief Platform-specific stack area definitions
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-01-24
|
||||
*/
|
||||
@ -21,17 +21,17 @@ namespace Genode {
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration
|
||||
* Stack area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
static constexpr addr_t stack_area_virtual_base() {
|
||||
return 0x20000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Platform-specific context area definitions
|
||||
* \brief Platform-specific stack area definitions
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2014-01-24
|
||||
*/
|
||||
@ -21,17 +21,17 @@ namespace Genode {
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration
|
||||
* Stack area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
static constexpr addr_t stack_area_virtual_base() {
|
||||
return 0x40000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,8 @@ SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/context_allocator.cc
|
||||
SRC_CC += thread/stack_allocator.cc
|
||||
SRC_CC += thread/thread_utcb.cc
|
||||
SRC_CC += sleep.cc
|
||||
SRC_CC += rm_session_client.cc
|
||||
|
||||
|
@ -8,7 +8,7 @@ LIBS += base-common
|
||||
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += cpu/cache.cc
|
||||
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc \
|
||||
SRC_CC += env/env.cc env/stack_area.cc env/reinitialize.cc \
|
||||
env/cap_map_remove.cc env/cap_alloc.cc
|
||||
SRC_CC += thread/thread_start.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
namespace Fiasco {
|
||||
#include <l4/sys/utcb.h>
|
||||
}
|
||||
@ -30,8 +33,8 @@ void Thread_base::_deinit_platform_thread()
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
if (_context->utcb && _thread_cap.valid()) {
|
||||
Cap_index *i = (Cap_index*)l4_utcb_tcr_u(_context->utcb)->user[UTCB_TCR_BADGE];
|
||||
if (_tid.kcap && _thread_cap.valid()) {
|
||||
Cap_index *i = (Cap_index*)l4_utcb_tcr_u(utcb()->foc_utcb)->user[UTCB_TCR_BADGE];
|
||||
cap_map()->remove(i);
|
||||
_cpu_session->kill_thread(_thread_cap);
|
||||
env()->rm_session()->remove_client(_pager_cap);
|
||||
@ -59,7 +62,7 @@ void Thread_base::_init_platform_thread(size_t weight, Type type)
|
||||
return;
|
||||
}
|
||||
/* adjust values whose computation differs for a main thread */
|
||||
_tid = Fiasco::MAIN_THREAD_CAP;
|
||||
_tid.kcap = Fiasco::MAIN_THREAD_CAP;
|
||||
_thread_cap = env()->parent()->main_thread_cap();
|
||||
|
||||
if (!_thread_cap.valid())
|
||||
@ -83,15 +86,19 @@ void Thread_base::start()
|
||||
Thread_state state;
|
||||
try { state = _cpu_session->state(_thread_cap); }
|
||||
catch (...) { throw Cpu_session::Thread_creation_failed(); }
|
||||
_tid = state.kcap;
|
||||
_context->utcb = state.utcb;
|
||||
|
||||
/* remember UTCB of the new thread */
|
||||
Fiasco::l4_utcb_t * const foc_utcb = (Fiasco::l4_utcb_t *)state.utcb;
|
||||
utcb()->foc_utcb = foc_utcb;
|
||||
|
||||
_tid = Native_thread(state.kcap);
|
||||
|
||||
Cap_index *i = cap_map()->insert(state.id, state.kcap);
|
||||
l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_BADGE] = (unsigned long) i;
|
||||
l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
|
||||
l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_BADGE] = (unsigned long) i;
|
||||
l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
|
||||
|
||||
/* register initial IP and SP at core */
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _context->stack_top());
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _stack->top());
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,7 +43,7 @@ void Genode::Cpu_session_component::enable_vcpu(Genode::Thread_capability thread
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
Native_thread tid = thread->platform_thread()->thread().local.dst();
|
||||
l4_cap_idx_t tid = thread->platform_thread()->thread().local.dst();
|
||||
|
||||
l4_msgtag_t tag = l4_thread_vcpu_control(tid, vcpu_state);
|
||||
if (l4_msgtag_has_error(tag))
|
||||
@ -103,7 +103,7 @@ void Genode::Cpu_session_component::single_step(Genode::Thread_capability thread
|
||||
auto lambda = [&] (Cpu_thread_component *thread) {
|
||||
if (!thread) return;
|
||||
|
||||
Native_thread tid = thread->platform_thread()->thread().local.dst();
|
||||
Fiasco::l4_cap_idx_t tid = thread->platform_thread()->thread().local.dst();
|
||||
|
||||
enum { THREAD_SINGLE_STEP = 0x40000 };
|
||||
int flags = enable ? THREAD_SINGLE_STEP : 0;
|
||||
|
@ -38,7 +38,7 @@ class Genode::Irq_object
|
||||
|
||||
Signal_context_capability _sig_cap;
|
||||
|
||||
Native_thread _capability() const { return _cap->kcap(); }
|
||||
Fiasco::l4_cap_idx_t _capability() const { return _cap->kcap(); }
|
||||
|
||||
public:
|
||||
|
||||
|
@ -48,8 +48,8 @@ namespace Genode {
|
||||
|
||||
addr_t utcb_area_start()
|
||||
{
|
||||
return (Native_config::context_area_virtual_base() +
|
||||
THREAD_MAX * Native_config::context_virtual_size());
|
||||
return (Native_config::stack_area_virtual_base() +
|
||||
THREAD_MAX * Native_config::stack_virtual_size());
|
||||
}
|
||||
|
||||
Cap_mapping _task;
|
||||
|
@ -42,7 +42,7 @@ namespace Genode {
|
||||
Cap_mapping _gate;
|
||||
Cap_mapping _pager;
|
||||
Cap_mapping _irq;
|
||||
Native_utcb _utcb;
|
||||
addr_t _utcb;
|
||||
char _name[32]; /* thread name that will be
|
||||
registered at the kernel
|
||||
debugger */
|
||||
@ -185,7 +185,7 @@ namespace Genode {
|
||||
Cap_mapping& gate() { return _gate; }
|
||||
const char *name() const { return _name; }
|
||||
bool core_thread() const { return _core_thread; }
|
||||
Native_utcb utcb() const { return _utcb; }
|
||||
addr_t utcb() const { return _utcb; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ void Ipc_pager::reply_and_wait_for_fault()
|
||||
}
|
||||
l4_utcb_mr()->mr[1] = _reply_mapping.fpage().raw;
|
||||
|
||||
_tag = l4_ipc_send_and_wait(_last, l4_utcb(), snd_tag,
|
||||
_tag = l4_ipc_send_and_wait(_last.kcap, l4_utcb(), snd_tag,
|
||||
&label, L4_IPC_SEND_TIMEOUT_0);
|
||||
int err = l4_ipc_error(_tag, l4_utcb());
|
||||
if (err) {
|
||||
@ -119,7 +119,7 @@ void Ipc_pager::reply_and_wait_for_fault()
|
||||
|
||||
void Ipc_pager::acknowledge_wakeup()
|
||||
{
|
||||
l4_cap_idx_t dst = Fiasco::Capability::valid(_last) ? _last : L4_SYSF_REPLY;
|
||||
l4_cap_idx_t dst = Fiasco::Capability::valid(_last.kcap) ? _last.kcap : L4_SYSF_REPLY;
|
||||
|
||||
/* answer wakeup call from one of core's region-manager sessions */
|
||||
l4_ipc_send(dst, l4_utcb(), l4_msgtag(0, 0, 0, 0), L4_IPC_SEND_TIMEOUT_0);
|
||||
@ -129,7 +129,7 @@ void Ipc_pager::acknowledge_wakeup()
|
||||
void Ipc_pager::acknowledge_exception()
|
||||
{
|
||||
memcpy(l4_utcb_exc(), &_regs, sizeof(l4_exc_regs_t));
|
||||
l4_cap_idx_t dst = Fiasco::Capability::valid(_last) ? _last : L4_SYSF_REPLY;
|
||||
l4_cap_idx_t dst = Fiasco::Capability::valid(_last.kcap) ? _last.kcap : L4_SYSF_REPLY;
|
||||
l4_ipc_send(dst, l4_utcb(), l4_msgtag(0, L4_UTCB_EXCEPTION_REGS_SIZE, 0, 0), L4_IPC_SEND_TIMEOUT_0);
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ class Genode::Interrupt_handler : public Thread<2048*sizeof(long)>
|
||||
|
||||
void entry();
|
||||
|
||||
static Native_thread handler_cap()
|
||||
static Fiasco::l4_cap_idx_t handler_cap()
|
||||
{
|
||||
static Interrupt_handler handler;
|
||||
return handler._thread_cap.dst();
|
||||
|
@ -69,7 +69,7 @@ void Pager_entrypoint::entry()
|
||||
PDBG("Could not resolve pf=%p ip=%p",
|
||||
(void*)_pager.fault_addr(), (void*)_pager.fault_ip());
|
||||
} else {
|
||||
_pager.set_reply_dst(obj->badge());
|
||||
_pager.set_reply_dst(Native_thread(obj->badge()));
|
||||
reply_pending = true;
|
||||
return;
|
||||
}
|
||||
@ -99,7 +99,7 @@ void Pager_entrypoint::entry()
|
||||
}
|
||||
|
||||
/* send wake up message to requested thread */
|
||||
_pager.set_reply_dst(obj->badge());
|
||||
_pager.set_reply_dst(Native_thread(obj->badge()));
|
||||
_pager.acknowledge_exception();
|
||||
break;
|
||||
}
|
||||
@ -121,7 +121,7 @@ void Pager_entrypoint::entry()
|
||||
* that case we unblock it immediately.
|
||||
*/
|
||||
if (!obj->state.paused) {
|
||||
_pager.set_reply_dst(obj->badge());
|
||||
_pager.set_reply_dst(Native_thread(obj->badge()));
|
||||
reply_pending = true;
|
||||
}
|
||||
break;
|
||||
|
@ -327,8 +327,8 @@ void Platform::_setup_mem_alloc()
|
||||
}
|
||||
|
||||
region.start = addr; region.end = addr + size;
|
||||
if (!region.intersects(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size())) {
|
||||
if (!region.intersects(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size())) {
|
||||
add_region(region, _ram_alloc);
|
||||
add_region(region, _core_address_ranges());
|
||||
}
|
||||
@ -402,9 +402,9 @@ void Platform::_setup_basics()
|
||||
_vm_start = _vm_start == 0 ? L4_PAGESIZE : _vm_start;
|
||||
_region_alloc.add_range(_vm_start, _vm_size);
|
||||
|
||||
/* preserve context area in core's virtual address space */
|
||||
_region_alloc.remove_range(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size());
|
||||
/* preserve stack area in core's virtual address space */
|
||||
_region_alloc.remove_range(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size());
|
||||
|
||||
/* preserve utcb- area in core's virtual address space */
|
||||
_region_alloc.remove_range((addr_t)l4_utcb(), L4_PAGESIZE * 16);
|
||||
|
@ -54,16 +54,19 @@ int Platform_pd::bind_thread(Platform_thread *thread)
|
||||
if (_threads[i])
|
||||
continue;
|
||||
|
||||
_threads[i] = thread;
|
||||
_threads[i] = thread;
|
||||
|
||||
if (thread->core_thread())
|
||||
thread->_utcb = (l4_utcb_t*) (core_utcb_base() + i * L4_UTCB_OFFSET);
|
||||
thread->_utcb = (addr_t) (core_utcb_base() + i * L4_UTCB_OFFSET);
|
||||
else
|
||||
thread->_utcb =
|
||||
reinterpret_cast<l4_utcb_t*>(utcb_area_start() + i * L4_UTCB_OFFSET);
|
||||
Native_thread cap_offset = THREAD_AREA_BASE + i * THREAD_AREA_SLOT;
|
||||
thread->_gate.remote = cap_offset + THREAD_GATE_CAP;
|
||||
thread->_pager.remote = cap_offset + THREAD_PAGER_CAP;
|
||||
thread->_irq.remote = cap_offset + THREAD_IRQ_CAP;
|
||||
reinterpret_cast<addr_t>(utcb_area_start() + i * L4_UTCB_OFFSET);
|
||||
|
||||
Fiasco::l4_cap_idx_t cap_offset = THREAD_AREA_BASE + i * THREAD_AREA_SLOT;
|
||||
|
||||
thread->_gate.remote = cap_offset + THREAD_GATE_CAP;
|
||||
thread->_pager.remote = cap_offset + THREAD_PAGER_CAP;
|
||||
thread->_irq.remote = cap_offset + THREAD_IRQ_CAP;
|
||||
|
||||
/* if it's no core-thread we have to map parent and pager gate cap */
|
||||
if (!thread->core_thread()) {
|
||||
|
@ -45,7 +45,7 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
l4_thread_control_start();
|
||||
l4_thread_control_pager(_pager.remote);
|
||||
l4_thread_control_exc_handler(_pager.remote);
|
||||
l4_thread_control_bind(_utcb, _platform_pd->native_task().dst());
|
||||
l4_thread_control_bind((l4_utcb_t *)_utcb, _platform_pd->native_task().dst());
|
||||
l4_msgtag_t tag = l4_thread_control_commit(_thread.local.dst());
|
||||
if (l4_msgtag_has_error(tag)) {
|
||||
PWRN("l4_thread_control_commit for %lx failed!",
|
||||
|
@ -5,7 +5,7 @@ GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
||||
LIBS += base-common
|
||||
|
||||
SRC_CC += context_area.cc \
|
||||
SRC_CC += stack_area.cc \
|
||||
core_printf.cc \
|
||||
core_rpc_cap_alloc.cc \
|
||||
cpu_session_component.cc \
|
||||
@ -45,7 +45,7 @@ INC_DIR += $(REP_DIR)/src/core/include \
|
||||
|
||||
include $(GEN_CORE_DIR)/version.inc
|
||||
|
||||
vpath context_area.cc $(GEN_CORE_DIR)
|
||||
vpath stack_area.cc $(GEN_CORE_DIR)
|
||||
vpath cpu_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath dataspace_component.cc $(GEN_CORE_DIR)
|
||||
vpath dump_alloc.cc $(GEN_CORE_DIR)
|
||||
|
@ -16,6 +16,9 @@
|
||||
#include <base/thread.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <core_env.h>
|
||||
@ -43,19 +46,24 @@ void Thread_base::start()
|
||||
|
||||
/* create and start platform thread */
|
||||
Platform_thread *pt =
|
||||
new(platform()->core_mem_alloc()) Platform_thread(_context->name);
|
||||
new(platform()->core_mem_alloc()) Platform_thread(_stack->name().string());
|
||||
|
||||
if (platform_specific()->core_pd()->bind_thread(pt))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
_tid = pt->gate().remote;
|
||||
l4_utcb_t *foc_utcb = (l4_utcb_t *)(pt->utcb());
|
||||
|
||||
_tid = Native_thread(pt->gate().remote);
|
||||
|
||||
utcb()->foc_utcb = foc_utcb;
|
||||
|
||||
_thread_cap =
|
||||
reinterpret_cap_cast<Cpu_thread>(Native_capability(pt->thread().local));
|
||||
|
||||
pt->pager(platform_specific()->core_pager());
|
||||
|
||||
_context->utcb = pt->utcb();
|
||||
l4_utcb_tcr_u(pt->utcb())->user[UTCB_TCR_BADGE] = (unsigned long) pt->gate().local.idx();
|
||||
l4_utcb_tcr_u(pt->utcb())->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
|
||||
l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_BADGE] = (unsigned long) pt->gate().local.idx();
|
||||
l4_utcb_tcr_u(foc_utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this;
|
||||
|
||||
pt->start((void *)_thread_start, stack_top());
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ static inline void thread_yield() { Fiasco::l4_thread_yield(); }
|
||||
static inline bool thread_check_stopped_and_restart(Genode::Thread_base *thread_base)
|
||||
{
|
||||
Genode::Native_thread_id tid = thread_base ?
|
||||
thread_base->tid() :
|
||||
thread_base->tid().kcap :
|
||||
Fiasco::MAIN_THREAD_CAP;
|
||||
Genode::Native_thread_id irq = tid + Fiasco::THREAD_IRQ_CAP;
|
||||
Fiasco::l4_irq_trigger(irq);
|
||||
@ -62,7 +62,7 @@ static inline bool thread_check_stopped_and_restart(Genode::Thread_base *thread_
|
||||
static inline void thread_switch_to(Genode::Thread_base *thread_base)
|
||||
{
|
||||
Genode::Native_thread_id tid = thread_base ?
|
||||
thread_base->tid() :
|
||||
thread_base->tid().kcap :
|
||||
Fiasco::MAIN_THREAD_CAP;
|
||||
Fiasco::l4_thread_switch(tid);
|
||||
}
|
||||
@ -82,7 +82,7 @@ static void thread_stop_myself()
|
||||
|
||||
Genode::Thread_base *myself = Genode::Thread_base::myself();
|
||||
Genode::Native_thread_id tid = myself ?
|
||||
myself->tid() :
|
||||
myself->tid().kcap :
|
||||
Fiasco::MAIN_THREAD_CAP;
|
||||
Genode::Native_thread_id irq = tid + THREAD_IRQ_CAP;
|
||||
l4_irq_receive(irq, L4_IPC_NEVER);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <kernel/log.h>
|
||||
#include <base/native_capability.h>
|
||||
#include <base/ipc_msgbuf.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
namespace Genode
|
||||
{
|
||||
@ -80,17 +81,17 @@ struct Genode::Native_region
|
||||
struct Genode::Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration.
|
||||
* Stack area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
static constexpr addr_t stack_area_virtual_base() {
|
||||
return 0xe0000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
|
||||
|
||||
@ -105,8 +106,8 @@ class Genode::Native_utcb
|
||||
private:
|
||||
|
||||
Kernel::capid_t _caps[MAX_CAP_ARGS]; /* capability buffer */
|
||||
size_t _cap_cnt = 0; /* capability counter */
|
||||
size_t _size = 0; /* bytes to transfer */
|
||||
size_t _cap_cnt; /* capability counter */
|
||||
size_t _size; /* bytes to transfer */
|
||||
uint8_t _buf[get_page_size() - sizeof(_caps) -
|
||||
sizeof(_cap_cnt) - sizeof(_size)];
|
||||
|
||||
@ -190,7 +191,7 @@ namespace Genode
|
||||
|
||||
/**
|
||||
* The main thread's UTCB, used during bootstrap of the main thread before it
|
||||
* allocates its context area, needs to be outside the virtual memory area
|
||||
* allocates its stack area, needs to be outside the virtual memory area
|
||||
* controlled by the RM session, because it is needed before the main
|
||||
* thread can access its RM session.
|
||||
*/
|
||||
|
@ -25,7 +25,7 @@ SRC_CC += thread/thread.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/bootstrap.cc
|
||||
SRC_CC += thread/trace.cc
|
||||
SRC_CC += thread/context_allocator.cc
|
||||
SRC_CC += thread/stack_allocator.cc
|
||||
SRC_CC += kernel/interface.cc
|
||||
SRC_CC += sleep.cc
|
||||
SRC_CC += rm_session_client.cc
|
||||
|
@ -9,7 +9,7 @@ LIBS += base-common startup
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += cpu/cache.cc
|
||||
SRC_CC += env/env.cc
|
||||
SRC_CC += env/context_area.cc
|
||||
SRC_CC += env/stack_area.cc
|
||||
SRC_CC += env/reinitialize.cc
|
||||
SRC_CC += thread/start.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
|
@ -33,7 +33,7 @@ SRC_CC += pd_assign_pci.cc
|
||||
SRC_CC += platform.cc
|
||||
SRC_CC += platform_pd.cc
|
||||
SRC_CC += platform_thread.cc
|
||||
SRC_CC += context_area.cc
|
||||
SRC_CC += stack_area.cc
|
||||
SRC_CC += ram_session_component.cc
|
||||
SRC_CC += ram_session_support.cc
|
||||
SRC_CC += rm_session_component.cc
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* base-hw includes */
|
||||
#include <kernel/interface.h>
|
||||
|
||||
@ -57,9 +60,9 @@ void prepare_reinit_main_thread() { prepare_init_main_thread(); }
|
||||
** Thread_base **
|
||||
*****************/
|
||||
|
||||
Native_utcb * Thread_base::utcb()
|
||||
Native_utcb *Thread_base::utcb()
|
||||
{
|
||||
if (this) { return &_context->utcb; }
|
||||
if (this) { return &_stack->utcb(); }
|
||||
return utcb_main_thread();
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,12 @@
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack_allocator.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Genode { Rm_session * env_context_area_rm_session(); }
|
||||
namespace Genode { Rm_session * env_stack_area_rm_session(); }
|
||||
|
||||
namespace Hw {
|
||||
extern Ram_dataspace_capability _main_thread_utcb_ds;
|
||||
@ -39,18 +42,19 @@ void Thread_base::_init_platform_thread(size_t weight, Type type)
|
||||
/* create server object */
|
||||
char buf[48];
|
||||
name(buf, sizeof(buf));
|
||||
addr_t const utcb = (addr_t)&_context->utcb;
|
||||
addr_t const utcb = (addr_t)&_stack->utcb();
|
||||
_thread_cap = _cpu_session->create_thread(weight, buf, utcb);
|
||||
return;
|
||||
}
|
||||
/* if we got reinitialized we have to get rid of the old UTCB */
|
||||
size_t const utcb_size = sizeof(Native_utcb);
|
||||
addr_t const context_area = Native_config::context_area_virtual_base();
|
||||
addr_t const utcb_new = (addr_t)&_context->utcb - context_area;
|
||||
Rm_session * const rm = env_context_area_rm_session();
|
||||
size_t const utcb_size = sizeof(Native_utcb);
|
||||
addr_t const stack_area = Native_config::stack_area_virtual_base();
|
||||
addr_t const utcb_new = (addr_t)&_stack->utcb() - stack_area;
|
||||
Rm_session * const rm = env_stack_area_rm_session();
|
||||
|
||||
if (type == REINITIALIZED_MAIN) { rm->detach(utcb_new); }
|
||||
|
||||
/* remap initial main-thread UTCB according to context-area spec */
|
||||
/* remap initial main-thread UTCB according to stack-area spec */
|
||||
try { rm->attach_at(Hw::_main_thread_utcb_ds, utcb_new, utcb_size); }
|
||||
catch(...) {
|
||||
PERR("failed to re-map UTCB");
|
||||
@ -69,12 +73,12 @@ void Thread_base::_deinit_platform_thread()
|
||||
|
||||
_cpu_session->kill_thread(_thread_cap);
|
||||
|
||||
/* detach userland thread-context */
|
||||
size_t const size = sizeof(_context->utcb);
|
||||
addr_t utcb = Context_allocator::addr_to_base(_context) +
|
||||
Native_config::context_virtual_size() - size -
|
||||
Native_config::context_area_virtual_base();
|
||||
env_context_area_rm_session()->detach(utcb);
|
||||
/* detach userland stack */
|
||||
size_t const size = sizeof(_stack->utcb());
|
||||
addr_t utcb = Stack_allocator::addr_to_base(_stack) +
|
||||
Native_config::stack_virtual_size() - size -
|
||||
Native_config::stack_area_virtual_base();
|
||||
env_stack_area_rm_session()->detach(utcb);
|
||||
|
||||
if (_pager_cap.valid()) {
|
||||
env()->rm_session()->remove_client(_pager_cap);
|
||||
@ -91,20 +95,20 @@ void Thread_base::start()
|
||||
_pager_cap = env()->rm_session()->add_client(_thread_cap);
|
||||
_cpu_session->set_pager(_thread_cap, _pager_cap);
|
||||
|
||||
/* attach userland thread-context */
|
||||
/* attach userland stack */
|
||||
try {
|
||||
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 -
|
||||
Native_config::context_area_virtual_base();
|
||||
env_context_area_rm_session()->attach_at(ds, dst, size);
|
||||
size_t const size = sizeof(_stack->utcb());
|
||||
addr_t dst = Stack_allocator::addr_to_base(_stack) +
|
||||
Native_config::stack_virtual_size() - size -
|
||||
Native_config::stack_area_virtual_base();
|
||||
env_stack_area_rm_session()->attach_at(ds, dst, size);
|
||||
} catch (...) {
|
||||
PERR("failed to attach userland thread-context");
|
||||
PERR("failed to attach userland stack");
|
||||
sleep_forever();
|
||||
}
|
||||
/* start thread with its initial IP and aligned SP */
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _context->stack_top());
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _stack->top());
|
||||
}
|
||||
|
||||
|
||||
|
@ -95,7 +95,7 @@ namespace Genode {
|
||||
* \param quota CPU quota that shall be granted to the thread
|
||||
* \param label debugging label
|
||||
* \param virt_prio unscaled processor-scheduling priority
|
||||
* \param utcb core local pointer to userland thread-context
|
||||
* \param utcb core local pointer to userland stack
|
||||
*/
|
||||
Platform_thread(size_t const quota, const char * const label,
|
||||
unsigned const virt_prio, addr_t const utcb);
|
||||
|
@ -138,8 +138,8 @@ Platform::Platform()
|
||||
|
||||
/* preserve stack area in core's virtual address space */
|
||||
_core_mem_alloc.virt_alloc()->remove_range(
|
||||
Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size());
|
||||
Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size());
|
||||
|
||||
_init_io_port_alloc();
|
||||
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
|
||||
/* base-internal stack */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* core includes */
|
||||
#include <map_local.h>
|
||||
#include <kernel/kernel.h>
|
||||
@ -25,11 +28,10 @@
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
namespace Genode { Rm_session * env_context_area_rm_session(); }
|
||||
namespace Genode { Rm_session *env_stack_area_rm_session(); }
|
||||
|
||||
namespace Hw { extern Untyped_capability _main_thread_cap; }
|
||||
|
||||
namespace Hw {
|
||||
extern Untyped_capability _main_thread_cap;
|
||||
}
|
||||
|
||||
void Thread_base::start()
|
||||
{
|
||||
@ -56,13 +58,13 @@ void Thread_base::_init_platform_thread(size_t, Type type)
|
||||
{
|
||||
if (type == NORMAL) {
|
||||
_tid.platform_thread = new (platform()->core_mem_alloc())
|
||||
Platform_thread(_context->name, &_context->utcb);
|
||||
Platform_thread(_stack->name().string(), &_stack->utcb());
|
||||
return;
|
||||
}
|
||||
|
||||
/* remap initial main-thread UTCB according to context-area spec */
|
||||
/* remap initial main-thread UTCB according to stack-area spec */
|
||||
Genode::map_local((addr_t)Kernel::Core_thread::singleton().utcb(),
|
||||
(addr_t)&_context->utcb,
|
||||
(addr_t)&_stack->utcb(),
|
||||
max(sizeof(Native_utcb) / get_page_size(), (size_t)1));
|
||||
|
||||
/* adjust initial object state in case of a main thread */
|
||||
|
@ -26,7 +26,7 @@
|
||||
* Genode from POSIX.
|
||||
*/
|
||||
|
||||
extern Genode::addr_t _context_area_start;
|
||||
extern Genode::addr_t _stack_area_start;
|
||||
|
||||
namespace Genode {
|
||||
|
||||
@ -128,21 +128,21 @@ namespace Genode {
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration.
|
||||
* Stack area configuration
|
||||
*
|
||||
* Please update platform-specific files after changing these
|
||||
* functions, e.g., 'base-linux/src/ld/context_area.*.ld'.
|
||||
* functions, e.g., 'base-linux/src/ld/stack_area.*.ld'.
|
||||
*/
|
||||
static addr_t context_area_virtual_base() {
|
||||
return align_addr((addr_t)&_context_area_start, 20); }
|
||||
static addr_t stack_area_virtual_base() {
|
||||
return align_addr((addr_t)&_stack_area_start, 20); }
|
||||
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
|
||||
class Native_pd_args
|
||||
|
@ -19,7 +19,7 @@ SRC_CC += lock/lock.cc
|
||||
SRC_CC += env/rm_session_mmap.cc env/debug.cc
|
||||
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/trace.cc thread/thread_env.cc thread/context_allocator.cc
|
||||
SRC_CC += thread/trace.cc thread/thread_env.cc thread/stack_allocator.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
SRC_CC += sleep.cc
|
||||
SRC_CC += rm_session_client.cc
|
||||
|
@ -10,7 +10,7 @@
|
||||
LIBS += base-common syscall cxx
|
||||
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += env/env.cc env/platform_env.cc env/context_area.cc
|
||||
SRC_CC += env/env.cc env/platform_env.cc env/stack_area.cc
|
||||
SRC_CC += server/rpc_cap_alloc.cc
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/include $(BASE_DIR)/src/include
|
||||
|
@ -4,13 +4,13 @@
|
||||
|
||||
#
|
||||
# Startup code to be used when building a program and linker script that is
|
||||
# specific for Linux. We also reserve the thread-context area via a segment in
|
||||
# specific for Linux. We also reserve the stack area via a segment in
|
||||
# the program under Linux to prevent clashes with vdso.
|
||||
#
|
||||
ifneq ($(USE_HOST_LD_SCRIPT),yes)
|
||||
LD_TEXT_ADDR ?= 0x01000000
|
||||
LD_SCRIPT_STATIC = $(call select_from_repositories,src/ld/genode.ld) \
|
||||
$(call select_from_repositories,src/ld/context_area.nostdlib.ld)
|
||||
$(call select_from_repositories,src/ld/stack_area.nostdlib.ld)
|
||||
else
|
||||
LD_SCRIPT_STATIC ?=
|
||||
endif
|
||||
|
@ -10,7 +10,7 @@ endif
|
||||
#
|
||||
# We need to manually add the default linker script on the command line in case
|
||||
# of standard library use. Otherwise, we were not able to extend it by the
|
||||
# context area section.
|
||||
# stack area section.
|
||||
#
|
||||
ifeq ($(USE_HOST_LD_SCRIPT),yes)
|
||||
LD_SCRIPT_STATIC = ldscripts/armelf_linux_eabi.xc
|
||||
|
@ -6,7 +6,7 @@ SPECS += linux x86_32
|
||||
#
|
||||
# We need to manually add the default linker script on the command line in case
|
||||
# of standard library use. Otherwise, we were not able to extend it by the
|
||||
# context area section.
|
||||
# stack area section.
|
||||
#
|
||||
ifeq ($(USE_HOST_LD_SCRIPT),yes)
|
||||
LD_SCRIPT_DEFAULT = ldscripts/elf_i386.xc
|
||||
|
@ -6,7 +6,7 @@ SPECS += linux x86_64
|
||||
#
|
||||
# We need to manually add the default linker script on the command line in case
|
||||
# of standard library use. Otherwise, we were not able to extend it by the
|
||||
# context area section.
|
||||
# stack area section.
|
||||
#
|
||||
ifeq ($(USE_HOST_LD_SCRIPT),yes)
|
||||
LD_SCRIPT_DEFAULT = ldscripts/elf_x86_64.xc
|
||||
|
20
repos/base-linux/src/base/env/rm_session_mmap.cc
vendored
20
repos/base-linux/src/base/env/rm_session_mmap.cc
vendored
@ -8,7 +8,7 @@
|
||||
* dataspaces and 2) get the kernel to manage VM regions as we intent.
|
||||
*
|
||||
* The kernel sets up mappings for the binary on execve(), which are text and
|
||||
* data segments, the context area and special regions (stack, vdso, vsyscall).
|
||||
* data segments, the stack area and special regions (stack, vdso, vsyscall).
|
||||
* Later mappings are done by the Genode program itself, which knows nothing
|
||||
* about these initial mappings. Therefore, most mmap() operations are _soft_
|
||||
* to detect region conflicts with existing mappings or let the kernel find
|
||||
@ -17,10 +17,10 @@
|
||||
* but not populated dataspaces are "holes" in the Linux VM space represented
|
||||
* by PROT_NONE mappings (see _reserve_local()).
|
||||
*
|
||||
* The context area is a managed dataspace as on other platforms, which is
|
||||
* The stack area is a managed dataspace as on other platforms, which is
|
||||
* created and attached during program launch. The managed dataspace replaces
|
||||
* the inital reserved area, which is therefore flushed beforehand. Hybrid
|
||||
* programs have no context area.
|
||||
* programs have no stack area.
|
||||
*
|
||||
* Note, we do not support nesting of managed dataspaces.
|
||||
*/
|
||||
@ -40,7 +40,7 @@
|
||||
/* base-internal includes */
|
||||
#include <base/internal/local_capability.h>
|
||||
#include <base/internal/platform_env.h>
|
||||
#include <base/internal/context_area.h>
|
||||
#include <base/internal/stack_area.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
@ -58,13 +58,13 @@ addr_t Platform_env_base::Rm_session_mmap::_reserve_local(bool use_loc
|
||||
addr_t local_addr,
|
||||
Genode::size_t size)
|
||||
{
|
||||
/* special handling for context area */
|
||||
/* special handling for stack area */
|
||||
if (use_local_addr
|
||||
&& local_addr == Native_config::context_area_virtual_base()
|
||||
&& size == Native_config::context_area_virtual_size()) {
|
||||
&& local_addr == Native_config::stack_area_virtual_base()
|
||||
&& size == Native_config::stack_area_virtual_size()) {
|
||||
|
||||
/*
|
||||
* On the first request to reserve the context area, we flush the
|
||||
* On the first request to reserve the stack area, we flush the
|
||||
* initial mapping preserved in linker script and apply the actual
|
||||
* reservation. Subsequent requests are just ignored.
|
||||
*/
|
||||
@ -73,8 +73,8 @@ addr_t Platform_env_base::Rm_session_mmap::_reserve_local(bool use_loc
|
||||
{
|
||||
Context()
|
||||
{
|
||||
flush_context_area();
|
||||
reserve_context_area();
|
||||
flush_stack_area();
|
||||
reserve_stack_area();
|
||||
}
|
||||
} inst;
|
||||
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include <base/sleep.h>
|
||||
#include <linux_cpu_session/linux_cpu_session.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* Linux syscall bindings */
|
||||
#include <linux_syscalls.h>
|
||||
|
||||
@ -77,7 +80,7 @@ void Thread_base::_init_platform_thread(size_t weight, Type type)
|
||||
|
||||
/* for normal threads create an object at the CPU session */
|
||||
if (type == NORMAL) {
|
||||
_thread_cap = _cpu_session->create_thread(weight, _context->name);
|
||||
_thread_cap = _cpu_session->create_thread(weight, _stack->name().string());
|
||||
return;
|
||||
}
|
||||
/* adjust initial object state for main threads */
|
||||
|
@ -28,7 +28,6 @@
|
||||
/* base-internal includes */
|
||||
#include <base/internal/platform_env.h>
|
||||
|
||||
|
||||
namespace Genode {
|
||||
|
||||
/**
|
||||
|
@ -18,29 +18,29 @@
|
||||
#include <base/thread.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/context_area.h>
|
||||
#include <base/internal/stack_area.h>
|
||||
|
||||
|
||||
/**
|
||||
* Region-manager session for allocating thread contexts
|
||||
* Region-manager session for allocating stacks
|
||||
*
|
||||
* This class corresponds to the managed dataspace that is normally
|
||||
* used for organizing thread contexts with the thread context area.
|
||||
* It "emulates" the sub address space by adjusting the local address
|
||||
* argument to 'attach' with the offset of the thread context area.
|
||||
* This class corresponds to the managed dataspace that is normally used for
|
||||
* organizing stacks within the stack. It "emulates" the sub address space by
|
||||
* adjusting the local address argument to 'attach' with the offset of the
|
||||
* stack area.
|
||||
*/
|
||||
class Context_area_rm_session : public Genode::Rm_session
|
||||
class Stack_area_rm_session : public Genode::Rm_session
|
||||
{
|
||||
public:
|
||||
|
||||
Context_area_rm_session()
|
||||
Stack_area_rm_session()
|
||||
{
|
||||
flush_context_area();
|
||||
reserve_context_area();
|
||||
flush_stack_area();
|
||||
reserve_stack_area();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach backing store to thread-context area
|
||||
* Attach backing store to stack area
|
||||
*/
|
||||
Local_addr attach(Genode::Dataspace_capability ds_cap,
|
||||
Genode::size_t size, Genode::off_t offset,
|
||||
@ -49,9 +49,9 @@ class Context_area_rm_session : public Genode::Rm_session
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* convert context-area-relative to absolute virtual address */
|
||||
/* convert stack-area-relative to absolute virtual address */
|
||||
addr_t addr = local_addr;
|
||||
addr += Native_config::context_area_virtual_base();
|
||||
addr += Native_config::stack_area_virtual_base();
|
||||
|
||||
/* use anonymous mmap for allocating stack backing store */
|
||||
int flags = MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
@ -65,7 +65,7 @@ class Context_area_rm_session : public Genode::Rm_session
|
||||
}
|
||||
|
||||
void detach(Local_addr local_addr) {
|
||||
PWRN("context area detach from 0x%p - not implemented", (void *)local_addr); }
|
||||
PWRN("stack area detach from 0x%p - not implemented", (void *)local_addr); }
|
||||
|
||||
Genode::Pager_capability add_client(Genode::Thread_capability) {
|
||||
return Genode::Pager_capability(); }
|
||||
@ -81,7 +81,7 @@ class Context_area_rm_session : public Genode::Rm_session
|
||||
};
|
||||
|
||||
|
||||
class Context_area_ram_session : public Genode::Ram_session
|
||||
class Stack_area_ram_session : public Genode::Ram_session
|
||||
{
|
||||
public:
|
||||
|
||||
@ -102,19 +102,19 @@ class Context_area_ram_session : public Genode::Ram_session
|
||||
|
||||
|
||||
/**
|
||||
* Return single instance of the context-area RM and RAM session
|
||||
* Return single instance of the stack-area RM and RAM session
|
||||
*/
|
||||
namespace Genode {
|
||||
|
||||
Rm_session *env_context_area_rm_session()
|
||||
Rm_session *env_stack_area_rm_session()
|
||||
{
|
||||
static Context_area_rm_session inst;
|
||||
static Stack_area_rm_session inst;
|
||||
return &inst;
|
||||
}
|
||||
|
||||
Ram_session *env_context_area_ram_session()
|
||||
Ram_session *env_stack_area_ram_session()
|
||||
{
|
||||
static Context_area_ram_session inst;
|
||||
static Stack_area_ram_session inst;
|
||||
return &inst;
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ SRC_CC = main.cc \
|
||||
signal_source_component.cc \
|
||||
trace_session_component.cc \
|
||||
thread_linux.cc \
|
||||
context_area.cc \
|
||||
stack_area.cc \
|
||||
core_printf.cc \
|
||||
thread.cc myself.cc
|
||||
|
||||
|
@ -211,7 +211,7 @@ namespace Genode {
|
||||
* the common use case of managed dataspaces as mechanism
|
||||
* to reserve parts of the local address space from being
|
||||
* populated by the 'env()->rm_session()'. (i.e., for the
|
||||
* context area, or for the placement of consecutive
|
||||
* stack area, or for the placement of consecutive
|
||||
* shared-library segments)
|
||||
*/
|
||||
addr_t _base;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Linux-specific utilities for context area
|
||||
* \brief Linux-specific utilities for stack area
|
||||
* \author Christian Helmuth
|
||||
* \date 2013-09-26
|
||||
*/
|
||||
@ -11,8 +11,8 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE__BASE__INTERNAL__CONTEXT_AREA_H_
|
||||
#define _INCLUDE__BASE__INTERNAL__CONTEXT_AREA_H_
|
||||
#ifndef _INCLUDE__BASE__INTERNAL__STACK_AREA_H_
|
||||
#define _INCLUDE__BASE__INTERNAL__STACK_AREA_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
@ -24,12 +24,12 @@
|
||||
#include <sys/mman.h>
|
||||
|
||||
|
||||
static inline void flush_context_area()
|
||||
static inline void flush_stack_area()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
void * const base = (void *) Native_config::context_area_virtual_base();
|
||||
size_t const size = Native_config::context_area_virtual_size();
|
||||
void * const base = (void *) Native_config::stack_area_virtual_base();
|
||||
size_t const size = Native_config::stack_area_virtual_size();
|
||||
|
||||
int ret;
|
||||
if ((ret = lx_munmap(base, size)) < 0) {
|
||||
@ -39,14 +39,14 @@ static inline void flush_context_area()
|
||||
}
|
||||
|
||||
|
||||
static inline Genode::addr_t reserve_context_area()
|
||||
static inline Genode::addr_t reserve_stack_area()
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
int const flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||
int const prot = PROT_NONE;
|
||||
size_t const size = Native_config::context_area_virtual_size();
|
||||
void * const addr_in = (void *)Native_config::context_area_virtual_base();
|
||||
size_t const size = Native_config::stack_area_virtual_size();
|
||||
void * const addr_in = (void *)Native_config::stack_area_virtual_base();
|
||||
void * const addr_out = lx_mmap(addr_in, size, prot, flags, -1, 0);
|
||||
|
||||
/* reserve at local address failed - unmap incorrect mapping */
|
||||
@ -61,4 +61,4 @@ static inline Genode::addr_t reserve_context_area()
|
||||
return (addr_t) addr_out;
|
||||
}
|
||||
|
||||
#endif /* _INCLUDE__BASE__INTERNAL__CONTEXT_AREA_H_ */
|
||||
#endif /* _INCLUDE__BASE__INTERNAL__STACK_AREA_H_ */
|
@ -13,16 +13,16 @@
|
||||
|
||||
PHDRS
|
||||
{
|
||||
context_area PT_LOAD FLAGS(0);
|
||||
stack_area PT_LOAD FLAGS(0);
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40000000;
|
||||
_context_area_start = .;
|
||||
_stack_area_start = .;
|
||||
/*
|
||||
* Since Linux loads ldso page aligned, we align the context area after
|
||||
* Since Linux loads ldso page aligned, we align the stack area after
|
||||
* loading to a 1 MiB boundary, therefore we reserve one MiB more here.
|
||||
*/
|
||||
.context_area : { . += 0x10100000; } : context_area
|
||||
.stack_area : { . += 0x10100000; } : stack_area
|
||||
}
|
@ -14,6 +14,6 @@
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x40000000;
|
||||
_context_area_start = .;
|
||||
.context_area : { . += 0x10000000; }
|
||||
_stack_area_start = .;
|
||||
.stack_area : { . += 0x10000000; }
|
||||
}
|
@ -20,9 +20,9 @@
|
||||
extern "C" int raw_write_str(const char *str);
|
||||
|
||||
/**
|
||||
* Define context area
|
||||
* Define stack area
|
||||
*/
|
||||
Genode::addr_t _context_area_start;
|
||||
Genode::addr_t _stack_area_start;
|
||||
|
||||
|
||||
enum { verbose_atexit = false };
|
||||
@ -137,7 +137,7 @@ namespace Genode {
|
||||
struct Thread_meta_data
|
||||
{
|
||||
/**
|
||||
* Filled out by 'thread_start' function in the context of the new
|
||||
* Filled out by 'thread_start' function in the stack of the new
|
||||
* thread
|
||||
*/
|
||||
Thread_base * const thread_base;
|
||||
@ -419,7 +419,7 @@ Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
|
||||
PERR("pthread_create failed (returned %d, errno=%d)",
|
||||
ret, errno);
|
||||
destroy(env()->heap(), _tid.meta_data);
|
||||
throw Context_alloc_failed();
|
||||
throw Out_of_stack_space();
|
||||
}
|
||||
|
||||
_tid.meta_data->wait_for_construction();
|
||||
|
@ -241,17 +241,17 @@ namespace Genode {
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration.
|
||||
* Stack area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
static constexpr addr_t stack_area_virtual_base() {
|
||||
return 0xa0000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
|
||||
struct Native_pd_args { };
|
||||
|
@ -18,9 +18,9 @@ SRC_CC += elf/elf_binary.cc
|
||||
SRC_CC += lock/lock.cc
|
||||
SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc
|
||||
SRC_CC += thread/thread.cc thread/thread_context.cc thread/trace.cc
|
||||
SRC_CC += thread/thread.cc thread/stack.cc thread/trace.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/context_allocator.cc env/cap_map.cc
|
||||
SRC_CC += thread/stack_allocator.cc env/cap_map.cc
|
||||
SRC_CC += sleep.cc
|
||||
SRC_CC += rm_session_client.cc
|
||||
|
||||
|
@ -8,7 +8,7 @@ LIBS += base-common
|
||||
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += cpu/cache.cc
|
||||
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc
|
||||
SRC_CC += env/env.cc env/stack_area.cc env/reinitialize.cc
|
||||
SRC_CC += thread/thread_nova.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
SRC_CC += server/rpc_cap_alloc.cc
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include <base/rpc_server.h>
|
||||
#include <base/env.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/syscalls.h>
|
||||
#include <nova/util.h>
|
||||
@ -213,7 +216,7 @@ Rpc_entrypoint::Rpc_entrypoint(Pd_session *pd_session, size_t stack_size,
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
/* prepare portal receive window of new thread */
|
||||
if (!_rcv_buf.prepare_rcv_window((Nova::Utcb *)&_context->utcb))
|
||||
if (!_rcv_buf.prepare_rcv_window((Nova::Utcb *)&_stack->utcb()))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
if (start_on_construction)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Thread-context specific part of the thread library
|
||||
* \brief Stack-specific part of the thread library
|
||||
* \author Norman Feske
|
||||
* \author Alexander Boettcher
|
||||
* \author Martin Stein
|
||||
@ -21,6 +21,9 @@
|
||||
#include <base/env.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* base-nova includes */
|
||||
#include <base/cap_map.h>
|
||||
|
||||
@ -37,8 +40,8 @@ Native_utcb * main_thread_utcb()
|
||||
{
|
||||
using namespace Genode;
|
||||
return reinterpret_cast<Native_utcb *>(
|
||||
Native_config::context_area_virtual_base() +
|
||||
Native_config::context_virtual_size() - Nova::PAGE_SIZE_BYTE);
|
||||
Native_config::stack_area_virtual_base() +
|
||||
Native_config::stack_virtual_size() - Nova::PAGE_SIZE_BYTE);
|
||||
}
|
||||
|
||||
|
||||
@ -119,5 +122,5 @@ Native_utcb *Thread_base::utcb()
|
||||
*/
|
||||
if (this == 0) return main_thread_utcb();
|
||||
|
||||
return &_context->utcb;
|
||||
return &_stack->utcb();
|
||||
}
|
@ -18,10 +18,12 @@
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
|
||||
#include <base/rpc_client.h>
|
||||
#include <session/session.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/syscalls.h>
|
||||
#include <nova/util.h>
|
||||
@ -99,7 +101,7 @@ void Thread_base::_init_platform_thread(size_t weight, Type type)
|
||||
* afterwards.
|
||||
*/
|
||||
Rights rwx(true, true, true);
|
||||
addr_t utcb = reinterpret_cast<addr_t>(&_context->utcb);
|
||||
addr_t utcb = reinterpret_cast<addr_t>(&_stack->utcb());
|
||||
revoke(Mem_crd(utcb >> 12, 0, rwx));
|
||||
|
||||
_tid.exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2);
|
||||
@ -177,7 +179,7 @@ void Thread_base::start()
|
||||
try { _cpu_session->state(_thread_cap, state); }
|
||||
catch (...) { throw Cpu_session::Thread_creation_failed(); }
|
||||
|
||||
if (_cpu_session->start(_thread_cap, thread_ip, _context->stack_top()))
|
||||
if (_cpu_session->start(_thread_cap, thread_ip, _stack->top()))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
||||
/* request native EC thread cap */
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include <base/native_types.h>
|
||||
#include <base/thread.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* core includes */
|
||||
#include <pager.h>
|
||||
#include <address_space.h>
|
||||
@ -43,10 +46,10 @@ namespace Genode {
|
||||
VCPU = 0x2U,
|
||||
WORKER = 0x4U,
|
||||
};
|
||||
uint8_t _features;
|
||||
uint8_t _priority;
|
||||
uint8_t _features;
|
||||
uint8_t _priority;
|
||||
|
||||
char _name[Thread_base::Context::NAME_LEN];
|
||||
Stack::Name _name;
|
||||
|
||||
addr_t _sel_ec() const { return _id_base; }
|
||||
addr_t _sel_pt_oom() const { return _id_base + 1; }
|
||||
|
@ -126,13 +126,13 @@ static void page_fault_handler()
|
||||
pf_type & Ipc_pager::ERR_W ? "W" : "w",
|
||||
pf_type & Ipc_pager::ERR_P ? "P" : "p");
|
||||
|
||||
if ((Native_config::context_area_virtual_base() <= pf_sp) &&
|
||||
(pf_sp < Native_config::context_area_virtual_base() +
|
||||
Native_config::context_area_virtual_size()))
|
||||
if ((Native_config::stack_area_virtual_base() <= pf_sp) &&
|
||||
(pf_sp < Native_config::stack_area_virtual_base() +
|
||||
Native_config::stack_area_virtual_size()))
|
||||
{
|
||||
addr_t utcb_addr_f = pf_sp / Native_config::context_virtual_size();
|
||||
utcb_addr_f *= Native_config::context_virtual_size();
|
||||
utcb_addr_f += Native_config::context_virtual_size();
|
||||
addr_t utcb_addr_f = pf_sp / Native_config::stack_virtual_size();
|
||||
utcb_addr_f *= Native_config::stack_virtual_size();
|
||||
utcb_addr_f += Native_config::stack_virtual_size();
|
||||
utcb_addr_f -= 4096;
|
||||
|
||||
Nova::Utcb * utcb_fault = reinterpret_cast<Nova::Utcb *>(utcb_addr_f);
|
||||
@ -397,9 +397,9 @@ Platform::Platform() :
|
||||
/* preserve Bios Data Area (BDA) in core's virtual address space */
|
||||
region_alloc()->remove_range(BDA_VIRT_ADDR, 0x1000);
|
||||
|
||||
/* preserve context area in core's virtual address space */
|
||||
region_alloc()->remove_range(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size());
|
||||
/* preserve stack area in core's virtual address space */
|
||||
region_alloc()->remove_range(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size());
|
||||
|
||||
/* exclude utcb of core pager thread + empty guard pages before and after */
|
||||
region_alloc()->remove_range(CORE_PAGER_UTCB_ADDR - get_page_size(),
|
||||
@ -420,14 +420,14 @@ Platform::Platform() :
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < sizeof(check) / sizeof(check[0]); i++) {
|
||||
if (Native_config::context_area_virtual_base() <= check[i] &&
|
||||
check[i] < Native_config::context_area_virtual_base() +
|
||||
Native_config::context_area_virtual_size())
|
||||
if (Native_config::stack_area_virtual_base() <= check[i] &&
|
||||
check[i] < Native_config::stack_area_virtual_base() +
|
||||
Native_config::stack_area_virtual_size())
|
||||
{
|
||||
PERR("overlapping area - [%lx, %lx) vs %lx",
|
||||
Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_base() +
|
||||
Native_config::context_area_virtual_size(), check[i]);
|
||||
Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_base() +
|
||||
Native_config::stack_area_virtual_size(), check[i]);
|
||||
nova_die();
|
||||
}
|
||||
}
|
||||
|
@ -119,8 +119,8 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
_sel_exc_base = is_vcpu() ? _pager->exc_pt_vcpu() : _pager->exc_pt_sel_client();
|
||||
|
||||
if (!is_vcpu()) {
|
||||
pd_utcb = Native_config::context_area_virtual_base() +
|
||||
Native_config::context_virtual_size() - get_page_size();
|
||||
pd_utcb = Native_config::stack_area_virtual_base() +
|
||||
Native_config::stack_virtual_size() - get_page_size();
|
||||
|
||||
addr_t remap_src[] = { _pd->parent_pt_sel(), _pager->Object_pool<Pager_object>::Entry::cap().local_name() };
|
||||
addr_t remap_dst[] = { PT_SEL_PARENT, PT_SEL_MAIN_PAGER };
|
||||
@ -315,7 +315,7 @@ Native_capability Platform_thread::single_step(bool on)
|
||||
|
||||
unsigned long Platform_thread::pager_object_badge() const
|
||||
{
|
||||
return reinterpret_cast<unsigned long>(_name);
|
||||
return reinterpret_cast<unsigned long>(_name.string());
|
||||
}
|
||||
|
||||
|
||||
@ -353,17 +353,16 @@ Platform_thread::Platform_thread(const char *name, unsigned prio, int thread_id)
|
||||
_pd(0), _pager(0), _id_base(cap_map()->insert(2)),
|
||||
_sel_exc_base(Native_thread::INVALID_INDEX), _location(boot_cpu(), 0, 0, 0),
|
||||
_features(0),
|
||||
_priority(Cpu_session::scale_priority(Nova::Qpd::DEFAULT_PRIORITY, prio))
|
||||
_priority(Cpu_session::scale_priority(Nova::Qpd::DEFAULT_PRIORITY, prio)),
|
||||
_name(name)
|
||||
{
|
||||
strncpy(_name, name, sizeof(_name));
|
||||
|
||||
if (_priority == 0) {
|
||||
PWRN("priority of thread '%s' below minimum - boost to 1", _name);
|
||||
PWRN("priority of thread '%s' below minimum - boost to 1", _name.string());
|
||||
_priority = 1;
|
||||
}
|
||||
if (_priority > Nova::Qpd::DEFAULT_PRIORITY) {
|
||||
PWRN("priority of thread '%s' above maximum - limit to %u",
|
||||
_name, Nova::Qpd::DEFAULT_PRIORITY);
|
||||
_name.string(), Nova::Qpd::DEFAULT_PRIORITY);
|
||||
_priority = Nova::Qpd::DEFAULT_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ LIBS = base-common core
|
||||
|
||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
||||
SRC_CC = context_area.cc \
|
||||
SRC_CC = stack_area.cc \
|
||||
core_mem_alloc.cc \
|
||||
core_printf.cc \
|
||||
core_rm_session.cc \
|
||||
@ -61,6 +61,6 @@ vpath dataspace_component.cc $(GEN_CORE_DIR)
|
||||
vpath core_mem_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath dump_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath platform_services.cc $(GEN_CORE_DIR)/spec/x86
|
||||
vpath context_area.cc $(GEN_CORE_DIR)
|
||||
vpath stack_area.cc $(GEN_CORE_DIR)
|
||||
vpath core_printf.cc $(BASE_DIR)/src/base/console
|
||||
vpath %.cc $(REP_DIR)/src/core
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <base/thread.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* NOVA includes */
|
||||
#include <nova/syscalls.h>
|
||||
|
||||
@ -74,7 +77,7 @@ void Thread_base::_deinit_platform_thread()
|
||||
|
||||
/* revoke utcb */
|
||||
Nova::Rights rwx(true, true, true);
|
||||
addr_t utcb = reinterpret_cast<addr_t>(&_context->utcb);
|
||||
addr_t utcb = reinterpret_cast<addr_t>(&_stack->utcb());
|
||||
Nova::revoke(Nova::Mem_crd(utcb >> 12, 0, rwx));
|
||||
}
|
||||
|
||||
@ -87,9 +90,9 @@ void Thread_base::start()
|
||||
*/
|
||||
using namespace Nova;
|
||||
|
||||
addr_t sp = _context->stack_top();
|
||||
addr_t utcb = reinterpret_cast<addr_t>(&_context->utcb);
|
||||
Utcb * utcb_obj = reinterpret_cast<Utcb *>(&_context->utcb);
|
||||
addr_t sp = _stack->top();
|
||||
addr_t utcb = reinterpret_cast<addr_t>(&_stack->utcb());
|
||||
Utcb * utcb_obj = reinterpret_cast<Utcb *>(&_stack->utcb());
|
||||
addr_t pd_sel = Platform_pd::pd_core_sel();
|
||||
|
||||
/*
|
||||
|
@ -74,7 +74,7 @@ namespace Genode {
|
||||
/**
|
||||
* Empty UTCB type expected by the thread library, unused on OKL4
|
||||
*
|
||||
* On this kernel, UTCBs are not placed within the the context area. Each
|
||||
* On this kernel, UTCBs are not placed within the stack area. Each
|
||||
* thread can request its own UTCB pointer using the kernel interface.
|
||||
*/
|
||||
typedef struct { } Native_utcb;
|
||||
@ -93,17 +93,17 @@ namespace Genode {
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration.
|
||||
* Stack area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
static constexpr addr_t stack_area_virtual_base() {
|
||||
return 0x40000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
|
||||
struct Native_pd_args { };
|
||||
|
@ -21,7 +21,7 @@ SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/thread.cc thread/thread_bootstrap.cc thread/trace.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/context_allocator.cc
|
||||
SRC_CC += thread/stack_allocator.cc
|
||||
SRC_CC += sleep.cc
|
||||
SRC_CC += rm_session_client.cc
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += cpu/cache.cc
|
||||
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc
|
||||
SRC_CC += env/env.cc env/stack_area.cc env/reinitialize.cc
|
||||
SRC_CC += thread/thread_start.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
SRC_CC += server/rpc_cap_alloc.cc
|
||||
|
@ -271,9 +271,9 @@ Platform::Platform() :
|
||||
/* I/O port allocator (only meaningful for x86) */
|
||||
_io_port_alloc.add_range(0, 0x10000);
|
||||
|
||||
/* preserve context area in core's virtual address space */
|
||||
_core_mem_alloc.virt_alloc()->remove_range(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size());
|
||||
/* preserve stack area in core's virtual address space */
|
||||
_core_mem_alloc.virt_alloc()->remove_range(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size());
|
||||
|
||||
_vm_start = 0x1000;
|
||||
_vm_size = 0xb0000000 - 0x1000;
|
||||
|
@ -4,7 +4,7 @@ LIBS += boot_info base-common
|
||||
|
||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
||||
SRC_CC += context_area.cc \
|
||||
SRC_CC += stack_area.cc \
|
||||
core_mem_alloc.cc \
|
||||
core_printf.cc \
|
||||
core_rm_session.cc \
|
||||
@ -59,7 +59,7 @@ vpath dataspace_component.cc $(GEN_CORE_DIR)
|
||||
vpath core_mem_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath dump_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath context_area.cc $(GEN_CORE_DIR)
|
||||
vpath stack_area.cc $(GEN_CORE_DIR)
|
||||
vpath pager_ep.cc $(GEN_CORE_DIR)
|
||||
vpath pager_object.cc $(GEN_CORE_DIR)
|
||||
vpath %.cc $(REP_DIR)/src/core
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include <base/thread.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <core_env.h>
|
||||
@ -35,7 +38,7 @@ void Thread_base::start()
|
||||
{
|
||||
/* create and start platform thread */
|
||||
_tid.pt = new(platform_specific()->thread_slab())
|
||||
Platform_thread(0, _context->name);
|
||||
Platform_thread(0, _stack->name().string());
|
||||
|
||||
if (platform_specific()->core_pd()->bind_thread(_tid.pt))
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
|
@ -65,8 +65,8 @@ namespace Genode {
|
||||
/**
|
||||
* Empty UTCB type expected by the thread library
|
||||
*
|
||||
* On this kernel, UTCBs are not placed within the the context area. Each
|
||||
* thread can request its own UTCB pointer using the kernel interface.
|
||||
* On this kernel, UTCBs are not placed within the stack area. Each thread
|
||||
* can request its own UTCB pointer using the kernel interface.
|
||||
*/
|
||||
typedef struct { } Native_utcb;
|
||||
|
||||
@ -77,17 +77,17 @@ namespace Genode {
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration.
|
||||
* Stack area configuration
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
static constexpr addr_t stack_area_virtual_base() {
|
||||
return 0x40000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
|
||||
struct Native_pd_args { };
|
||||
|
@ -21,7 +21,7 @@ SRC_CC += signal/signal.cc signal/common.cc signal/platform.cc
|
||||
SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/thread.cc thread/trace.cc thread/thread_bootstrap.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/context_allocator.cc
|
||||
SRC_CC += thread/stack_allocator.cc
|
||||
SRC_CC += sleep.cc
|
||||
SRC_CC += rm_session_client.cc
|
||||
|
||||
|
@ -8,7 +8,7 @@ LIBS += base-common
|
||||
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += cpu/cache.cc
|
||||
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc
|
||||
SRC_CC += env/env.cc env/stack_area.cc env/reinitialize.cc
|
||||
SRC_CC += thread/thread_start.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
SRC_CC += server/rpc_cap_alloc.cc
|
||||
|
@ -434,8 +434,8 @@ void Platform::_setup_mem_alloc()
|
||||
|
||||
} else {
|
||||
region.start = addr; region.end = addr + size;
|
||||
if (region.intersects(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size()) ||
|
||||
if (region.intersects(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size()) ||
|
||||
intersects_kip_archdep(kip, addr, size)) {
|
||||
unmap_local(region.start, size >> get_page_size_log2());
|
||||
} else {
|
||||
@ -563,11 +563,11 @@ void Platform::_setup_basics()
|
||||
L4_MemoryDescLow(md), L4_MemoryDescHigh(md));
|
||||
}
|
||||
|
||||
/* configure core's virtual memory, exclude KIP, context area */
|
||||
/* configure core's virtual memory, exclude KIP, stack area */
|
||||
_region_alloc.add_range(_vm_start, _vm_size);
|
||||
_region_alloc.remove_range((addr_t)kip, kip_size);
|
||||
_region_alloc.remove_range(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size());
|
||||
_region_alloc.remove_range(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size());
|
||||
|
||||
/* remove KIP and MBI area from region and IO_MEM allocator */
|
||||
remove_region(Region((addr_t)kip, (addr_t)kip + kip_size), _region_alloc);
|
||||
|
@ -4,7 +4,7 @@ LIBS = base-common
|
||||
|
||||
GEN_CORE_DIR = $(BASE_DIR)/src/core
|
||||
|
||||
SRC_CC = context_area.cc \
|
||||
SRC_CC = stack_area.cc \
|
||||
core_printf.cc \
|
||||
core_rpc_cap_alloc.cc \
|
||||
cpu_session_component.cc \
|
||||
@ -58,7 +58,7 @@ vpath trace_session_component.cc $(GEN_CORE_DIR)
|
||||
vpath dataspace_component.cc $(GEN_CORE_DIR)
|
||||
vpath dump_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath core_rpc_cap_alloc.cc $(GEN_CORE_DIR)
|
||||
vpath context_area.cc $(GEN_CORE_DIR)
|
||||
vpath stack_area.cc $(GEN_CORE_DIR)
|
||||
vpath pager_ep.cc $(GEN_CORE_DIR)
|
||||
vpath pager_object.cc $(GEN_CORE_DIR)
|
||||
vpath core_printf.cc $(BASE_DIR)/src/base/console
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include <base/thread.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <core_env.h>
|
||||
@ -35,7 +38,7 @@ void Thread_base::start()
|
||||
{
|
||||
/* create and start platform thread */
|
||||
_tid.pt = new(platform()->core_mem_alloc())
|
||||
Platform_thread(0, _context->name);
|
||||
Platform_thread(0, _stack->name().string());
|
||||
|
||||
platform_specific()->core_pd()->bind_thread(_tid.pt);
|
||||
|
||||
|
@ -129,17 +129,17 @@ namespace Genode {
|
||||
struct Native_config
|
||||
{
|
||||
/**
|
||||
* Thread-context area configuration.
|
||||
* Stack-area configuration.
|
||||
*/
|
||||
static constexpr addr_t context_area_virtual_base() {
|
||||
static constexpr addr_t stack_area_virtual_base() {
|
||||
return 0x40000000UL; }
|
||||
static constexpr addr_t context_area_virtual_size() {
|
||||
static constexpr addr_t stack_area_virtual_size() {
|
||||
return 0x10000000UL; }
|
||||
|
||||
/**
|
||||
* Size of virtual address region holding the context of one thread
|
||||
* Size of virtual address region holding the stack of one thread
|
||||
*/
|
||||
static constexpr addr_t context_virtual_size() { return 0x00100000UL; }
|
||||
static constexpr addr_t stack_virtual_size() { return 0x00100000UL; }
|
||||
};
|
||||
|
||||
struct Native_pd_args { };
|
||||
|
@ -21,7 +21,7 @@ SRC_CC += server/server.cc server/common.cc
|
||||
SRC_CC += thread/thread.cc
|
||||
SRC_CC += thread/trace.cc
|
||||
SRC_CC += thread/myself.cc
|
||||
SRC_CC += thread/context_allocator.cc
|
||||
SRC_CC += thread/stack_allocator.cc
|
||||
SRC_CC += thread/thread_bootstrap.cc
|
||||
SRC_CC += env/capability.cc
|
||||
SRC_CC += sleep.cc
|
||||
|
@ -7,7 +7,7 @@
|
||||
LIBS += base-common syscall
|
||||
|
||||
SRC_CC += console/log_console.cc
|
||||
SRC_CC += env/env.cc env/context_area.cc env/reinitialize.cc
|
||||
SRC_CC += env/env.cc env/stack_area.cc env/reinitialize.cc
|
||||
SRC_CC += env/capability_space.cc
|
||||
SRC_CC += thread/thread_start.cc thread/thread_init.cc
|
||||
SRC_CC += irq/platform.cc
|
||||
|
@ -30,7 +30,7 @@ SRC_CC += \
|
||||
core_mem_alloc.cc \
|
||||
core_rpc_cap_alloc.cc \
|
||||
dump_alloc.cc \
|
||||
context_area.cc \
|
||||
stack_area.cc \
|
||||
capability_space.cc \
|
||||
pager.cc \
|
||||
pager_ep.cc
|
||||
|
@ -15,6 +15,9 @@
|
||||
#include <base/thread.h>
|
||||
#include <base/env.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
|
||||
/*****************************
|
||||
** Startup library support **
|
||||
@ -32,6 +35,6 @@ void prepare_reinit_main_thread() { prepare_init_main_thread(); }
|
||||
void Genode::Thread_base::_thread_bootstrap()
|
||||
{
|
||||
if (tid().ep_sel == 0) {
|
||||
tid().ep_sel = _context->utcb.ep_sel;
|
||||
tid().ep_sel = _stack->utcb().ep_sel;
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ class Genode::Platform_thread : public List<Platform_thread>::Element
|
||||
* Virtual address of the IPC buffer within the PDs address space
|
||||
*
|
||||
* The value is 0 for the PD's main thread. For all other threads,
|
||||
* the value is somewhere within the context area.
|
||||
* the value is somewhere within the stack area.
|
||||
*/
|
||||
addr_t const _utcb;
|
||||
|
||||
|
@ -155,9 +155,9 @@ void Platform::_init_allocators()
|
||||
core_virt_beg, core_virt_end, core_size);
|
||||
}
|
||||
|
||||
/* preserve context area in core's virtual address space */
|
||||
_core_mem_alloc.virt_alloc()->remove_range(Native_config::context_area_virtual_base(),
|
||||
Native_config::context_area_virtual_size());
|
||||
/* preserve stack area in core's virtual address space */
|
||||
_core_mem_alloc.virt_alloc()->remove_range(Native_config::stack_area_virtual_base(),
|
||||
Native_config::stack_area_virtual_size());
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,7 +65,7 @@ int Platform_pd::bind_thread(Platform_thread *thread)
|
||||
* 'Vm_space'. In contrast to mapping that are created as a result of
|
||||
* the RM-session's page-fault resolution, the IPC buffer's mapping
|
||||
* won't be recoverable once flushed. For this reason, it is important
|
||||
* to attach the UTCB as a dataspace to the context-area to make the RM
|
||||
* to attach the UTCB as a dataspace to the stack area to make the RM
|
||||
* session aware to the mapping. This code is missing.
|
||||
*/
|
||||
if (thread->_utcb) {
|
||||
|
@ -29,18 +29,17 @@ using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Region-manager session for allocating thread contexts
|
||||
* Region-manager session for allocating stacks
|
||||
*
|
||||
* This class corresponds to the managed dataspace that is normally
|
||||
* used for organizing thread contexts with the thread context area.
|
||||
* In contrast to the ordinary implementation, core's version does
|
||||
* not split between allocation of memory and virtual memory management.
|
||||
* Due to the missing availability of "real" dataspaces and capabilities
|
||||
* refering to it without having an entrypoint in place, the allocation
|
||||
* of a dataspace has no effect, but the attachment of the thereby "empty"
|
||||
* dataspace is doing both: allocation and attachment.
|
||||
* This class corresponds to the managed dataspace that is normally used for
|
||||
* organizing stacks with the stack area. In contrast to the ordinary
|
||||
* implementation, core's version does not split between allocation of memory
|
||||
* and virtual memory management. Due to the missing availability of "real"
|
||||
* dataspaces and capabilities refering to it without having an entrypoint in
|
||||
* place, the allocation of a dataspace has no effect, but the attachment of
|
||||
* the thereby "empty" dataspace is doing both: allocation and attachment.
|
||||
*/
|
||||
class Context_area_rm_session : public Rm_session
|
||||
class Stack_area_rm_session : public Rm_session
|
||||
{
|
||||
private:
|
||||
|
||||
@ -54,7 +53,7 @@ class Context_area_rm_session : public Rm_session
|
||||
public:
|
||||
|
||||
/**
|
||||
* Allocate and attach on-the-fly backing store to thread-context area
|
||||
* Allocate and attach on-the-fly backing store to the stack area
|
||||
*/
|
||||
Local_addr attach(Dataspace_capability ds_cap, /* ignored capability */
|
||||
size_t size, off_t offset,
|
||||
@ -72,12 +71,12 @@ class Context_area_rm_session : public Rm_session
|
||||
Dataspace_component *ds = new (&_ds_slab)
|
||||
Dataspace_component(size, 0, phys, CACHED, true, 0);
|
||||
if (!ds) {
|
||||
PERR("dataspace for core context does not exist");
|
||||
PERR("dataspace for core stack does not exist");
|
||||
return (addr_t)0;
|
||||
}
|
||||
|
||||
addr_t const core_local_addr =
|
||||
Native_config::context_area_virtual_base() + (addr_t)local_addr;
|
||||
Native_config::stack_area_virtual_base() + (addr_t)local_addr;
|
||||
|
||||
if (verbose)
|
||||
PDBG("core_local_addr = %lx, phys_addr = %lx, size = 0x%zx",
|
||||
@ -110,7 +109,7 @@ class Context_area_rm_session : public Rm_session
|
||||
};
|
||||
|
||||
|
||||
class Context_area_ram_session : public Ram_session
|
||||
class Stack_area_ram_session : public Ram_session
|
||||
{
|
||||
public:
|
||||
|
||||
@ -136,15 +135,15 @@ class Context_area_ram_session : public Ram_session
|
||||
*/
|
||||
namespace Genode {
|
||||
|
||||
Rm_session *env_context_area_rm_session()
|
||||
Rm_session *env_stack_area_rm_session()
|
||||
{
|
||||
static Context_area_rm_session inst;
|
||||
static Stack_area_rm_session inst;
|
||||
return &inst;
|
||||
}
|
||||
|
||||
Ram_session *env_context_area_ram_session()
|
||||
Ram_session *env_stack_area_ram_session()
|
||||
{
|
||||
static Context_area_ram_session inst;
|
||||
static Stack_area_ram_session inst;
|
||||
return &inst;
|
||||
}
|
||||
}
|
@ -16,6 +16,9 @@
|
||||
#include <base/printf.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
/* core includes */
|
||||
#include <platform.h>
|
||||
#include <platform_thread.h>
|
||||
@ -26,7 +29,7 @@ using namespace Genode;
|
||||
|
||||
void Thread_base::_init_platform_thread(size_t, Type type)
|
||||
{
|
||||
addr_t const utcb_virt_addr = (addr_t)&_context->utcb;
|
||||
addr_t const utcb_virt_addr = (addr_t)&_stack->utcb();
|
||||
|
||||
if (type == MAIN) {
|
||||
_tid.tcb_sel = seL4_CapInitThreadTCB;
|
||||
|
@ -107,14 +107,14 @@ struct Genode::Env
|
||||
/**
|
||||
* Reinitialize main-thread object
|
||||
*
|
||||
* \param context_area_rm new RM session of the context area
|
||||
* \param stack_area_rm new RM session of the context area
|
||||
*
|
||||
* This function is solely used for implementing fork semantics
|
||||
* as provided by the Noux environment.
|
||||
*
|
||||
* \noapi
|
||||
*/
|
||||
virtual void reinit_main_thread(Rm_session_capability &) = 0;
|
||||
virtual void reinit_main_thread(Rm_session_capability &stack_area_rm) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -2,50 +2,10 @@
|
||||
* \brief Thread interface
|
||||
* \author Norman Feske
|
||||
* \date 2006-04-28
|
||||
*
|
||||
* For storing thread-specific data (called thread context) such as the stack
|
||||
* and thread-local data, there is a dedicated portion of the virtual address
|
||||
* space. This portion is called thread-context area. Within the thread-context
|
||||
* area, each thread has a fixed-sized slot, a thread context. The layout of
|
||||
* each thread context looks as follows
|
||||
*
|
||||
* ; lower address
|
||||
* ; ...
|
||||
* ; ============================ <- aligned at the virtual context size
|
||||
* ;
|
||||
* ; empty
|
||||
* ;
|
||||
* ; ----------------------------
|
||||
* ;
|
||||
* ; stack
|
||||
* ; (top) <- initial stack pointer
|
||||
* ; ---------------------------- <- address of 'Context' object
|
||||
* ; additional context members
|
||||
* ; ----------------------------
|
||||
* ; UTCB
|
||||
* ; ============================ <- aligned at the virtual context size
|
||||
* ; ...
|
||||
* ; higher address
|
||||
*
|
||||
* On some platforms, a user-level thread-control block (UTCB) area contains
|
||||
* data shared between the user-level thread and the kernel. It is typically
|
||||
* used for transferring IPC message payload or for system-call arguments.
|
||||
* The additional context members are a reference to the corresponding
|
||||
* 'Thread_base' object and the name of the thread.
|
||||
*
|
||||
* The thread context is a virtual memory area, initially not backed by real
|
||||
* memory. When a new thread is created, an empty thread context gets assigned
|
||||
* to the new thread and populated with memory pages for the stack and the
|
||||
* additional context members. Note that this memory is allocated from the RAM
|
||||
* session of the process environment and not accounted for when using the
|
||||
* 'sizeof()' operand on a 'Thread_base' object.
|
||||
*
|
||||
* A thread may be associated with more than one stack. Additional secondary
|
||||
* stacks can be associated with a thread, and used for user level scheduling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2006-2013 Genode Labs GmbH
|
||||
* Copyright (C) 2006-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.
|
||||
@ -70,6 +30,7 @@ namespace Genode {
|
||||
|
||||
class Rm_session;
|
||||
class Thread_base;
|
||||
class Stack;
|
||||
template <unsigned> class Thread;
|
||||
}
|
||||
|
||||
@ -84,174 +45,24 @@ class Genode::Thread_base
|
||||
{
|
||||
public:
|
||||
|
||||
class Context_alloc_failed : public Exception { };
|
||||
class Stack_too_large : public Exception { };
|
||||
class Stack_alloc_failed : public Exception { };
|
||||
|
||||
/**
|
||||
* Thread context located within the thread-context area
|
||||
*
|
||||
* The end of a thread context is placed virtual size aligned.
|
||||
*/
|
||||
struct Context
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* Top of the stack is accessible via stack_top()
|
||||
*
|
||||
* Context provides the first word of the stack to prevent the
|
||||
* overlapping of stack top and the 'stack_base' member.
|
||||
*/
|
||||
addr_t _stack[1];
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Top of stack
|
||||
*
|
||||
* The alignment constrains are enforced by the CPU-specific ABI.
|
||||
*/
|
||||
addr_t stack_top() const { return Abi::stack_align((addr_t)_stack); }
|
||||
|
||||
/**
|
||||
* Ensure that the stack has a given size at the minimum
|
||||
*
|
||||
* \param size minimum stack size
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
*/
|
||||
void stack_size(size_t const size);
|
||||
|
||||
/**
|
||||
* Virtual address of the start of the stack
|
||||
*
|
||||
* This address is pointing to the begin of the dataspace used
|
||||
* for backing the thread context except for the UTCB (which is
|
||||
* managed by the kernel).
|
||||
*/
|
||||
addr_t stack_base;
|
||||
|
||||
/**
|
||||
* Pointer to corresponding 'Thread_base' object
|
||||
*/
|
||||
Thread_base *thread_base;
|
||||
|
||||
/**
|
||||
* Dataspace containing the backing store for the thread context
|
||||
*
|
||||
* We keep the dataspace capability to be able to release the
|
||||
* backing store on thread destruction.
|
||||
*/
|
||||
Ram_dataspace_capability ds_cap;
|
||||
|
||||
/**
|
||||
* Maximum length of thread name, including null-termination
|
||||
*/
|
||||
enum { NAME_LEN = 64 };
|
||||
|
||||
/**
|
||||
* Thread name, used for debugging
|
||||
*/
|
||||
char name[NAME_LEN];
|
||||
|
||||
/*
|
||||
* <- end of regular memory area
|
||||
*
|
||||
* The following part of the thread context is backed by
|
||||
* kernel-managed memory. No member variables are allowed
|
||||
* beyond this point.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Kernel-specific user-level thread control block
|
||||
*/
|
||||
Native_utcb utcb;
|
||||
};
|
||||
class Out_of_stack_space : public Exception { };
|
||||
class Stack_too_large : public Exception { };
|
||||
class Stack_alloc_failed : public Exception { };
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Manage the allocation of thread contexts
|
||||
*
|
||||
* There exists only one instance of this class per process.
|
||||
*/
|
||||
class Context_allocator
|
||||
{
|
||||
private:
|
||||
|
||||
static constexpr size_t MAX_THREADS =
|
||||
Native_config::context_area_virtual_size() /
|
||||
Native_config::context_virtual_size();
|
||||
|
||||
struct Context_bit_allocator : Bit_allocator<MAX_THREADS>
|
||||
{
|
||||
Context_bit_allocator()
|
||||
{
|
||||
/* the first index is used by main thread */
|
||||
_reserve(0, 1);
|
||||
}
|
||||
} _alloc;
|
||||
|
||||
Lock _threads_lock;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Allocate thread context for specified thread
|
||||
*
|
||||
* \param thread thread for which to allocate the new context
|
||||
* \param main_thread wether to alloc for the main thread
|
||||
*
|
||||
* \return virtual address of new thread context, or
|
||||
* 0 if the allocation failed
|
||||
*/
|
||||
Context *alloc(Thread_base *thread, bool main_thread);
|
||||
|
||||
/**
|
||||
* Release thread context
|
||||
*/
|
||||
void free(Context *thread);
|
||||
|
||||
/**
|
||||
* Return 'Context' object for a given base address
|
||||
*/
|
||||
static Context *base_to_context(addr_t base);
|
||||
|
||||
/**
|
||||
* Return base address of context containing the specified address
|
||||
*/
|
||||
static addr_t addr_to_base(void *addr);
|
||||
|
||||
/**
|
||||
* Return index in context area for a given base address
|
||||
*/
|
||||
static size_t base_to_idx(addr_t base);
|
||||
|
||||
/**
|
||||
* Return base address of context given index in context area
|
||||
*/
|
||||
static addr_t idx_to_base(size_t idx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return thread-context allocator
|
||||
*/
|
||||
static Context_allocator *_context_allocator();
|
||||
|
||||
/**
|
||||
* Allocate and locally attach a new thread context
|
||||
* Allocate and locally attach a new stack
|
||||
*
|
||||
* \param stack_size size of this threads stack
|
||||
* \param main_thread wether this is the main thread
|
||||
*/
|
||||
Context *_alloc_context(size_t stack_size, bool main_thread);
|
||||
Stack *_alloc_stack(size_t stack_size, char const *name, bool main_thread);
|
||||
|
||||
/**
|
||||
* Detach and release thread context of the thread
|
||||
* Detach and release stack of the thread
|
||||
*/
|
||||
void _free_context(Context *context);
|
||||
void _free_stack(Stack *stack);
|
||||
|
||||
/**
|
||||
* Platform-specific thread-startup code
|
||||
@ -297,9 +108,9 @@ class Genode::Thread_base
|
||||
Trace::Control *_trace_control;
|
||||
|
||||
/**
|
||||
* Pointer to primary thread context
|
||||
* Pointer to primary stack
|
||||
*/
|
||||
Context *_context;
|
||||
Stack *_stack;
|
||||
|
||||
/**
|
||||
* Physical thread ID
|
||||
@ -345,10 +156,10 @@ class Genode::Thread_base
|
||||
*
|
||||
* \noapi
|
||||
*
|
||||
* FIXME: With type = Forked_main_thread the whole
|
||||
* Context::_alloc_context call gets skipped but we should
|
||||
* at least set Context::ds_cap in a way that it references
|
||||
* the dataspace of the already attached stack.
|
||||
* FIXME: With type = Forked_main_thread the stack allocation
|
||||
* gets skipped but we should at least set Stack::ds_cap in a
|
||||
* way that it references the dataspace of the already attached
|
||||
* stack.
|
||||
*/
|
||||
Thread_base(size_t weight, const char *name, size_t stack_size,
|
||||
Type type);
|
||||
@ -362,12 +173,12 @@ class Genode::Thread_base
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
* \throw Context_alloc_failed
|
||||
* \throw Out_of_stack_space
|
||||
*
|
||||
* The stack for the new thread will be allocated from the RAM session
|
||||
* of the process environment. A small portion of the stack size is
|
||||
* internally used by the framework for storing thread-context
|
||||
* information such as the thread's name ('Context').
|
||||
* of the component environment. A small portion of the stack size is
|
||||
* internally used by the framework for storing thread-specific
|
||||
* information such as the thread's name.
|
||||
*/
|
||||
Thread_base(size_t weight, const char *name, size_t stack_size)
|
||||
: Thread_base(weight, name, stack_size, NORMAL) { }
|
||||
@ -389,7 +200,7 @@ class Genode::Thread_base
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
* \throw Context_alloc_failed
|
||||
* \throw Out_of_stack_space
|
||||
*/
|
||||
Thread_base(size_t weight, const char *name, size_t stack_size,
|
||||
Type type, Cpu_session *);
|
||||
@ -422,13 +233,12 @@ class Genode::Thread_base
|
||||
*
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
* \throw Context_alloc_failed
|
||||
* \throw Out_of_stack_space
|
||||
*
|
||||
* The stack for the new thread will be allocated from the RAM
|
||||
* session of the process environment. A small portion of the
|
||||
* session of the component environment. A small portion of the
|
||||
* stack size is internally used by the framework for storing
|
||||
* thread-context information such as the thread's name (see
|
||||
* 'struct Context').
|
||||
* thread-specific information such as the thread's name.
|
||||
*
|
||||
* \return pointer to the new stack's top
|
||||
*/
|
||||
@ -461,14 +271,14 @@ class Genode::Thread_base
|
||||
*
|
||||
* \return pointer just after first stack element
|
||||
*/
|
||||
void *stack_top() const { return (void *)_context->stack_top(); }
|
||||
void *stack_top() const;
|
||||
|
||||
/**
|
||||
* Return base of stack
|
||||
*
|
||||
* \return pointer to last stack element
|
||||
*/
|
||||
void *stack_base() { return (void*)_context->stack_base; }
|
||||
void *stack_base() const;
|
||||
|
||||
/**
|
||||
* Return 'Thread_base' object corresponding to the calling thread
|
||||
@ -482,10 +292,10 @@ class Genode::Thread_base
|
||||
*
|
||||
* \param size minimum stack size
|
||||
*
|
||||
* \throw Context::Stack_too_large
|
||||
* \throw Context::Stack_alloc_failed
|
||||
* \throw Stack_too_large
|
||||
* \throw Stack_alloc_failed
|
||||
*/
|
||||
void stack_size(size_t const size) { _context->stack_size(size); }
|
||||
void stack_size(size_t const size);
|
||||
|
||||
/**
|
||||
* Return user-level thread control block
|
||||
|
@ -22,7 +22,7 @@ namespace Abi {
|
||||
* On ARM we align the stack top to 16-byte. As a call (or branch) will not
|
||||
* change the stack pointer, we need no further stack adjustment.
|
||||
*/
|
||||
static Genode::addr_t stack_align(Genode::addr_t addr) {
|
||||
static inline Genode::addr_t stack_align(Genode::addr_t addr) {
|
||||
return (addr & ~0xf); }
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,7 @@ namespace Abi {
|
||||
* growth of the stack, we further adjust the stack-top address to comply
|
||||
* to the AMD64 ABI rule "stack top + adjustment is 16-byte aligned".
|
||||
*/
|
||||
static Genode::addr_t stack_align(Genode::addr_t addr) {
|
||||
inline Genode::addr_t stack_align(Genode::addr_t addr) {
|
||||
return (addr & ~0xf) - sizeof(Genode::addr_t); }
|
||||
|
||||
/**
|
||||
|
@ -13,7 +13,7 @@ LD_OPT += -Bsymbolic-functions --version-script=$(DIR)/symbol.map
|
||||
ifneq ($(filter linux, $(SPECS)),)
|
||||
|
||||
ENTRY_POINT = _start_initial_stack
|
||||
LD_OPT += -T$(call select_from_repositories,src/ld/context_area.nostdlib.ld) \
|
||||
LD_OPT += -T$(call select_from_repositories,src/ld/stack_area.nostdlib.ld) \
|
||||
|
||||
ifneq ($(filter x86_32, $(SPECS)),)
|
||||
LD_OPT += -T$(DIR)/linux-32.ld
|
||||
|
10
repos/base/src/base/env/reinitialize.cc
vendored
10
repos/base/src/base/env/reinitialize.cc
vendored
@ -28,7 +28,7 @@ namespace Genode
|
||||
{
|
||||
extern bool inhibit_tracing;
|
||||
|
||||
Rm_session * env_context_area_rm_session();
|
||||
Rm_session * env_stack_area_rm_session();
|
||||
}
|
||||
|
||||
|
||||
@ -83,12 +83,12 @@ void Genode::Platform_env::reinit(Native_capability::Dst dst,
|
||||
|
||||
void
|
||||
Genode::Platform_env::
|
||||
reinit_main_thread(Rm_session_capability & context_area_rm)
|
||||
reinit_main_thread(Rm_session_capability & stack_area_rm)
|
||||
{
|
||||
/* reinitialize context area RM session */
|
||||
Rm_session * const rms = env_context_area_rm_session();
|
||||
/* reinitialize stack area RM session */
|
||||
Rm_session * const rms = env_stack_area_rm_session();
|
||||
Rm_session_client * const rmc = dynamic_cast<Rm_session_client *>(rms);
|
||||
construct_at<Rm_session_client>(rmc, context_area_rm);
|
||||
construct_at<Rm_session_client>(rmc, stack_area_rm);
|
||||
|
||||
/* reinitialize main-thread object */
|
||||
::reinit_main_thread();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Process-local thread-context area
|
||||
* \brief Component-local stack area
|
||||
* \author Norman Feske
|
||||
* \date 2010-01-19
|
||||
*/
|
||||
@ -36,13 +36,13 @@ struct Expanding_rm_connection : Connection<Rm_session>, Expanding_rm_session_cl
|
||||
};
|
||||
|
||||
|
||||
struct Context_area_rm_session : Expanding_rm_connection
|
||||
struct Stack_area_rm_session : Expanding_rm_connection
|
||||
{
|
||||
Context_area_rm_session()
|
||||
: Expanding_rm_connection(0, Native_config::context_area_virtual_size())
|
||||
Stack_area_rm_session()
|
||||
: Expanding_rm_connection(0, Native_config::stack_area_virtual_size())
|
||||
{
|
||||
addr_t local_base = Native_config::context_area_virtual_base();
|
||||
size_t size = Native_config::context_area_virtual_size();
|
||||
addr_t local_base = Native_config::stack_area_virtual_base();
|
||||
size_t size = Native_config::stack_area_virtual_size();
|
||||
|
||||
env()->rm_session()->attach_at(dataspace(), local_base, size);
|
||||
}
|
||||
@ -51,13 +51,13 @@ struct Context_area_rm_session : Expanding_rm_connection
|
||||
|
||||
namespace Genode {
|
||||
|
||||
Rm_session *env_context_area_rm_session()
|
||||
Rm_session *env_stack_area_rm_session()
|
||||
{
|
||||
static Context_area_rm_session inst;
|
||||
static Stack_area_rm_session inst;
|
||||
return &inst;
|
||||
}
|
||||
|
||||
Ram_session *env_context_area_ram_session()
|
||||
Ram_session *env_stack_area_ram_session()
|
||||
{
|
||||
return env()->ram_session();
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* \brief Context-allocator implementation for the Genode Thread API
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2014-01-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Thread_base::Context *Thread_base::Context_allocator::base_to_context(addr_t base)
|
||||
{
|
||||
addr_t result = base + Native_config::context_virtual_size()
|
||||
- sizeof(Context);
|
||||
return reinterpret_cast<Context *>(result);
|
||||
}
|
||||
|
||||
|
||||
addr_t Thread_base::Context_allocator::addr_to_base(void *addr)
|
||||
{
|
||||
return ((addr_t)addr) & ~(Native_config::context_virtual_size() - 1);
|
||||
}
|
||||
|
||||
|
||||
size_t Thread_base::Context_allocator::base_to_idx(addr_t base)
|
||||
{
|
||||
return (base - Native_config::context_area_virtual_base()) /
|
||||
Native_config::context_virtual_size();
|
||||
}
|
||||
|
||||
|
||||
addr_t Thread_base::Context_allocator::idx_to_base(size_t idx)
|
||||
{
|
||||
return Native_config::context_area_virtual_base() +
|
||||
idx * Native_config::context_virtual_size();
|
||||
}
|
||||
|
||||
|
||||
Thread_base::Context *
|
||||
Thread_base::Context_allocator::alloc(Thread_base *thread_base, bool main_thread)
|
||||
{
|
||||
if (main_thread)
|
||||
/* the main-thread context is the first one */
|
||||
return base_to_context(Native_config::context_area_virtual_base());
|
||||
|
||||
try {
|
||||
Lock::Guard _lock_guard(_threads_lock);
|
||||
return base_to_context(idx_to_base(_alloc.alloc()));
|
||||
} catch(Bit_allocator<MAX_THREADS>::Out_of_indices) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::Context_allocator::free(Context *context)
|
||||
{
|
||||
addr_t const base = addr_to_base(context);
|
||||
|
||||
Lock::Guard _lock_guard(_threads_lock);
|
||||
_alloc.free(base_to_idx(base));
|
||||
}
|
||||
|
||||
|
||||
Thread_base::Context_allocator *Thread_base::_context_allocator()
|
||||
{
|
||||
static Context_allocator context_allocator_inst;
|
||||
return &context_allocator_inst;
|
||||
}
|
@ -11,24 +11,28 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack_allocator.h>
|
||||
|
||||
|
||||
Genode::Thread_base *Genode::Thread_base::myself()
|
||||
{
|
||||
int dummy = 0; /* used for determining the stack pointer */
|
||||
|
||||
/*
|
||||
* If the stack pointer is outside the thread-context area, we assume that
|
||||
* If the stack pointer is outside the stack area, we assume that
|
||||
* we are the main thread because this condition can never met by any other
|
||||
* thread.
|
||||
*/
|
||||
addr_t sp = (addr_t)(&dummy);
|
||||
if (sp < Native_config::context_area_virtual_base() ||
|
||||
sp >= Native_config::context_area_virtual_base() +
|
||||
Native_config::context_area_virtual_size())
|
||||
if (sp < Native_config::stack_area_virtual_base() ||
|
||||
sp >= Native_config::stack_area_virtual_base() +
|
||||
Native_config::stack_area_virtual_size())
|
||||
return 0;
|
||||
|
||||
addr_t base = Context_allocator::addr_to_base(&dummy);
|
||||
return Context_allocator::base_to_context(base)->thread_base;
|
||||
addr_t base = Stack_allocator::addr_to_base(&dummy);
|
||||
return &Stack_allocator::base_to_stack(base)->thread();
|
||||
}
|
||||
|
78
repos/base/src/base/thread/stack_allocator.cc
Normal file
78
repos/base/src/base/thread/stack_allocator.cc
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* \brief Stack-allocator implementation for the Genode Thread API
|
||||
* \author Norman Feske
|
||||
* \author Martin Stein
|
||||
* \date 2014-01-26
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2010-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.
|
||||
*/
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack_allocator.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Stack *Stack_allocator::base_to_stack(addr_t base)
|
||||
{
|
||||
addr_t result = base + Native_config::stack_virtual_size()
|
||||
- sizeof(Stack);
|
||||
return reinterpret_cast<Stack *>(result);
|
||||
}
|
||||
|
||||
|
||||
addr_t Stack_allocator::addr_to_base(void *addr)
|
||||
{
|
||||
return ((addr_t)addr) & ~(Native_config::stack_virtual_size() - 1);
|
||||
}
|
||||
|
||||
|
||||
size_t Stack_allocator::base_to_idx(addr_t base)
|
||||
{
|
||||
return (base - Native_config::stack_area_virtual_base()) /
|
||||
Native_config::stack_virtual_size();
|
||||
}
|
||||
|
||||
|
||||
addr_t Stack_allocator::idx_to_base(size_t idx)
|
||||
{
|
||||
return Native_config::stack_area_virtual_base() +
|
||||
idx * Native_config::stack_virtual_size();
|
||||
}
|
||||
|
||||
|
||||
Stack *
|
||||
Stack_allocator::alloc(Thread_base *thread_base, bool main_thread)
|
||||
{
|
||||
if (main_thread)
|
||||
/* the main-thread stack is the first one */
|
||||
return base_to_stack(Native_config::stack_area_virtual_base());
|
||||
|
||||
try {
|
||||
Lock::Guard _lock_guard(_threads_lock);
|
||||
return base_to_stack(idx_to_base(_alloc.alloc()));
|
||||
} catch(Bit_allocator<MAX_THREADS>::Out_of_indices) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Stack_allocator::free(Stack *stack)
|
||||
{
|
||||
addr_t const base = addr_to_base(stack);
|
||||
|
||||
Lock::Guard _lock_guard(_threads_lock);
|
||||
_alloc.free(base_to_idx(base));
|
||||
}
|
||||
|
||||
|
||||
Stack_allocator &Stack_allocator::stack_allocator()
|
||||
{
|
||||
static Stack_allocator inst;
|
||||
return inst;
|
||||
}
|
@ -11,93 +11,102 @@
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <util/construct_at.h>
|
||||
#include <util/string.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <base/thread.h>
|
||||
#include <base/env.h>
|
||||
#include <base/sleep.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <util/string.h>
|
||||
#include <util/misc_math.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack_allocator.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Return the managed dataspace holding the thread context area
|
||||
* Return the managed dataspace holding the stack area
|
||||
*
|
||||
* This function is provided by the process environment.
|
||||
*/
|
||||
namespace Genode {
|
||||
|
||||
Rm_session *env_context_area_rm_session();
|
||||
Ram_session *env_context_area_ram_session();
|
||||
Rm_session *env_stack_area_rm_session();
|
||||
Ram_session *env_stack_area_ram_session();
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::Context::stack_size(size_t const size)
|
||||
void Stack::size(size_t const size)
|
||||
{
|
||||
/* check if the stack needs to be enhanced */
|
||||
size_t const stack_size = (addr_t)_stack - stack_base;
|
||||
size_t const stack_size = (addr_t)_stack - _base;
|
||||
if (stack_size >= size) { return; }
|
||||
|
||||
/* check if the stack enhancement fits the context region */
|
||||
/* check if the stack enhancement fits the stack region */
|
||||
enum {
|
||||
CONTEXT_SIZE = Native_config::context_virtual_size(),
|
||||
UTCB_SIZE = sizeof(Native_utcb),
|
||||
PAGE_SIZE_LOG2 = 12,
|
||||
PAGE_SIZE = (1UL << PAGE_SIZE_LOG2),
|
||||
};
|
||||
addr_t const context_base = Context_allocator::addr_to_base(this);
|
||||
addr_t const stack_slot_base = Stack_allocator::addr_to_base(this);
|
||||
size_t const ds_size = align_addr(size - stack_size, PAGE_SIZE_LOG2);
|
||||
if (stack_base - ds_size < context_base) { throw Stack_too_large(); }
|
||||
if (_base - ds_size < stack_slot_base)
|
||||
throw Thread_base::Stack_too_large();
|
||||
|
||||
/* allocate and attach backing store for the stack enhancement */
|
||||
addr_t const ds_addr = stack_base - ds_size -
|
||||
Native_config::context_area_virtual_base();
|
||||
addr_t const ds_addr = _base - ds_size -
|
||||
Native_config::stack_area_virtual_base();
|
||||
try {
|
||||
Ram_session * const ram = env_context_area_ram_session();
|
||||
Ram_session * const ram = env_stack_area_ram_session();
|
||||
Ram_dataspace_capability const ds_cap = ram->alloc(ds_size);
|
||||
Rm_session * const rm = env_context_area_rm_session();
|
||||
Rm_session * const rm = env_stack_area_rm_session();
|
||||
void * const attach_addr = rm->attach_at(ds_cap, ds_addr, ds_size);
|
||||
if (ds_addr != (addr_t)attach_addr) { throw Stack_alloc_failed(); }
|
||||
}
|
||||
catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); }
|
||||
|
||||
/* update context information */
|
||||
stack_base -= ds_size;
|
||||
if (ds_addr != (addr_t)attach_addr)
|
||||
throw Thread_base::Out_of_stack_space();
|
||||
}
|
||||
catch (Ram_session::Alloc_failed) {
|
||||
throw Thread_base::Stack_alloc_failed();
|
||||
}
|
||||
|
||||
/* update stack information */
|
||||
_base -= ds_size;
|
||||
}
|
||||
|
||||
|
||||
Thread_base::Context *
|
||||
Thread_base::_alloc_context(size_t stack_size, bool main_thread)
|
||||
Stack *
|
||||
Thread_base::_alloc_stack(size_t stack_size, char const *name, bool main_thread)
|
||||
{
|
||||
/*
|
||||
* Synchronize context list when creating new threads from multiple threads
|
||||
* Synchronize stack list when creating new threads from multiple threads
|
||||
*
|
||||
* XXX: remove interim fix
|
||||
*/
|
||||
static Lock alloc_lock;
|
||||
Lock::Guard _lock_guard(alloc_lock);
|
||||
|
||||
/* allocate thread context */
|
||||
Context *context = _context_allocator()->alloc(this, main_thread);
|
||||
if (!context)
|
||||
throw Context_alloc_failed();
|
||||
/* allocate stack */
|
||||
Stack *stack = Stack_allocator::stack_allocator().alloc(this, main_thread);
|
||||
if (!stack)
|
||||
throw Out_of_stack_space();
|
||||
|
||||
/* determine size of dataspace to allocate for context members and stack */
|
||||
/* determine size of dataspace to allocate for the stack */
|
||||
enum { PAGE_SIZE_LOG2 = 12 };
|
||||
size_t ds_size = align_addr(stack_size, PAGE_SIZE_LOG2);
|
||||
|
||||
if (stack_size >= Native_config::context_virtual_size() -
|
||||
if (stack_size >= Native_config::stack_virtual_size() -
|
||||
sizeof(Native_utcb) - (1UL << PAGE_SIZE_LOG2))
|
||||
throw Stack_too_large();
|
||||
|
||||
/*
|
||||
* Calculate base address of the stack
|
||||
*
|
||||
* The stack is always located at the top of the context.
|
||||
* The stack pointer is always located at the top of the stack header.
|
||||
*/
|
||||
addr_t ds_addr = Context_allocator::addr_to_base(context) +
|
||||
Native_config::context_virtual_size() -
|
||||
addr_t ds_addr = Stack_allocator::addr_to_base(stack) +
|
||||
Native_config::stack_virtual_size() -
|
||||
ds_size;
|
||||
|
||||
/* add padding for UTCB if defined for the platform */
|
||||
@ -107,50 +116,46 @@ Thread_base::_alloc_context(size_t stack_size, bool main_thread)
|
||||
/* allocate and attach backing store for the stack */
|
||||
Ram_dataspace_capability ds_cap;
|
||||
try {
|
||||
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))
|
||||
ds_cap = env_stack_area_ram_session()->alloc(ds_size);
|
||||
addr_t attach_addr = ds_addr - Native_config::stack_area_virtual_base();
|
||||
if (attach_addr != (addr_t)env_stack_area_rm_session()->attach_at(ds_cap, attach_addr, ds_size))
|
||||
throw Stack_alloc_failed();
|
||||
}
|
||||
catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); }
|
||||
|
||||
/*
|
||||
* Now the thread context is backed by memory, so it is safe to access its
|
||||
* members.
|
||||
* Now the stack is backed by memory, so it is safe to access its members.
|
||||
*
|
||||
* We need to initialize the context object's memory with zeroes,
|
||||
* otherwise the ds_cap isn't invalid. That would cause trouble
|
||||
* when the assignment operator of Native_capability is used.
|
||||
* We need to initialize the stack object's memory with zeroes, otherwise
|
||||
* the ds_cap isn't invalid. That would cause trouble when the assignment
|
||||
* operator of Native_capability is used.
|
||||
*/
|
||||
memset(context, 0, sizeof(Context) - sizeof(Context::utcb));
|
||||
context->thread_base = this;
|
||||
context->stack_base = ds_addr;
|
||||
context->ds_cap = ds_cap;
|
||||
construct_at<Stack>(stack, name, *this, ds_addr, ds_cap);
|
||||
|
||||
Abi::init_stack(context->stack_top());
|
||||
return context;
|
||||
Abi::init_stack(stack->top());
|
||||
return stack;
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::_free_context(Context* context)
|
||||
void Thread_base::_free_stack(Stack *stack)
|
||||
{
|
||||
addr_t ds_addr = context->stack_base - Native_config::context_area_virtual_base();
|
||||
Ram_dataspace_capability ds_cap = context->ds_cap;
|
||||
addr_t ds_addr = stack->base() - Native_config::stack_area_virtual_base();
|
||||
Ram_dataspace_capability ds_cap = stack->ds_cap();
|
||||
|
||||
/* call de-constructor explicitly before memory gets detached */
|
||||
context->~Context();
|
||||
stack->~Stack();
|
||||
|
||||
Genode::env_context_area_rm_session()->detach((void *)ds_addr);
|
||||
Genode::env_context_area_ram_session()->free(ds_cap);
|
||||
Genode::env_stack_area_rm_session()->detach((void *)ds_addr);
|
||||
Genode::env_stack_area_ram_session()->free(ds_cap);
|
||||
|
||||
/* context area ready for reuse */
|
||||
_context_allocator()->free(context);
|
||||
/* stack ready for reuse */
|
||||
Stack_allocator::stack_allocator().free(stack);
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::name(char *dst, size_t dst_len)
|
||||
{
|
||||
snprintf(dst, min(dst_len, (size_t)Context::NAME_LEN), "%s", _context->name);
|
||||
snprintf(dst, dst_len, "%s", _stack->name().string());
|
||||
}
|
||||
|
||||
|
||||
@ -159,29 +164,36 @@ void Thread_base::join() { _join_lock.lock(); }
|
||||
|
||||
void* Thread_base::alloc_secondary_stack(char const *name, size_t stack_size)
|
||||
{
|
||||
Context *context = _alloc_context(stack_size, false);
|
||||
strncpy(context->name, name, sizeof(context->name));
|
||||
return (void *)context->stack_top();
|
||||
Stack *stack = _alloc_stack(stack_size, name, false);
|
||||
return (void *)stack->top();
|
||||
}
|
||||
|
||||
|
||||
void Thread_base::free_secondary_stack(void* stack_addr)
|
||||
{
|
||||
addr_t base = Context_allocator::addr_to_base(stack_addr);
|
||||
_free_context(Context_allocator::base_to_context(base));
|
||||
addr_t base = Stack_allocator::addr_to_base(stack_addr);
|
||||
_free_stack(Stack_allocator::base_to_stack(base));
|
||||
}
|
||||
|
||||
|
||||
void *Thread_base::stack_top() const { return (void *)_stack->top(); }
|
||||
|
||||
|
||||
void *Thread_base::stack_base() const { return (void*)_stack->base(); }
|
||||
|
||||
|
||||
void Thread_base::stack_size(size_t const size) { _stack->size(size); }
|
||||
|
||||
|
||||
Thread_base::Thread_base(size_t weight, const char *name, size_t stack_size,
|
||||
Type type, Cpu_session *cpu_session)
|
||||
:
|
||||
_cpu_session(cpu_session),
|
||||
_trace_control(nullptr),
|
||||
_context(type == REINITIALIZED_MAIN ?
|
||||
_context : _alloc_context(stack_size, type == MAIN)),
|
||||
_stack(type == REINITIALIZED_MAIN ?
|
||||
_stack : _alloc_stack(stack_size, name, type == MAIN)),
|
||||
_join_lock(Lock::LOCKED)
|
||||
{
|
||||
strncpy(_context->name, name, sizeof(_context->name));
|
||||
_init_platform_thread(weight, type);
|
||||
|
||||
if (_cpu_session) {
|
||||
@ -201,12 +213,12 @@ Thread_base::~Thread_base()
|
||||
{
|
||||
if (Thread_base::myself() == this) {
|
||||
PERR("thread '%s' tried to self de-struct - sleeping forever.",
|
||||
_context->name);
|
||||
_stack->name().string());
|
||||
sleep_forever();
|
||||
}
|
||||
|
||||
_deinit_platform_thread();
|
||||
_free_context(_context);
|
||||
_free_stack(_stack);
|
||||
|
||||
/*
|
||||
* We have to detach the trace control dataspace last because
|
||||
|
@ -17,6 +17,9 @@
|
||||
#include <base/sleep.h>
|
||||
#include <base/env.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
@ -55,7 +58,7 @@ void Thread_base::start()
|
||||
char buf[48];
|
||||
name(buf, sizeof(buf));
|
||||
enum { WEIGHT = Cpu_session::DEFAULT_WEIGHT };
|
||||
addr_t const utcb = (addr_t)&_context->utcb;
|
||||
addr_t const utcb = (addr_t)&_stack->utcb();
|
||||
_thread_cap = _cpu_session->create_thread(WEIGHT, buf, utcb);
|
||||
if (!_thread_cap.valid())
|
||||
throw Cpu_session::Thread_creation_failed();
|
||||
@ -72,7 +75,7 @@ void Thread_base::start()
|
||||
_cpu_session->set_pager(_thread_cap, pager_cap);
|
||||
|
||||
/* register initial IP and SP at core */
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _context->stack_top());
|
||||
_cpu_session->start(_thread_cap, (addr_t)_thread_start, _stack->top());
|
||||
}
|
||||
|
||||
|
||||
|
26
repos/base/src/base/thread/thread_utcb.cc
Normal file
26
repos/base/src/base/thread/thread_utcb.cc
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* \brief Fiasco-specific implementation of the thread API
|
||||
* \author Norman Feske
|
||||
* \date 2016-01-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/thread.h>
|
||||
|
||||
/* base-internal includes */
|
||||
#include <base/internal/stack.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
Native_utcb *Thread_base::utcb()
|
||||
{
|
||||
return &_stack->utcb();
|
||||
}
|
@ -28,18 +28,18 @@ using namespace Genode;
|
||||
|
||||
|
||||
/**
|
||||
* Region-manager session for allocating thread contexts
|
||||
* Region-manager session for allocating stacks
|
||||
*
|
||||
* This class corresponds to the managed dataspace that is normally
|
||||
* used for organizing thread contexts with the thread context area.
|
||||
* used for organizing stacks within the stack area.
|
||||
* In contrast to the ordinary implementation, core's version does
|
||||
* not split between allocation of memory and virtual memory management.
|
||||
* Due to the missing availability of "real" dataspaces and capabilities
|
||||
* refering to it without having an entrypoint in place, the allocation
|
||||
* referring to it without having an entrypoint in place, the allocation
|
||||
* of a dataspace has no effect, but the attachment of the thereby "empty"
|
||||
* dataspace is doing both: allocation and attachment.
|
||||
*/
|
||||
class Context_area_rm_session : public Rm_session
|
||||
class Stack_area_rm_session : public Rm_session
|
||||
{
|
||||
private:
|
||||
|
||||
@ -53,7 +53,7 @@ class Context_area_rm_session : public Rm_session
|
||||
public:
|
||||
|
||||
/**
|
||||
* Allocate and attach on-the-fly backing store to thread-context area
|
||||
* Allocate and attach on-the-fly backing store to stack area
|
||||
*/
|
||||
Local_addr attach(Dataspace_capability ds_cap, /* ignored capability */
|
||||
size_t size, off_t offset,
|
||||
@ -66,7 +66,7 @@ class Context_area_rm_session : public Rm_session
|
||||
Range_allocator *ra = platform_specific()->ram_alloc();
|
||||
if (ra->alloc_aligned(size, &phys_base,
|
||||
get_page_size_log2()).is_error()) {
|
||||
PERR("could not allocate backing store for new context");
|
||||
PERR("could not allocate backing store for new stack");
|
||||
return (addr_t)0;
|
||||
}
|
||||
|
||||
@ -76,11 +76,11 @@ class Context_area_rm_session : public Rm_session
|
||||
Dataspace_component *ds = new (&_ds_slab)
|
||||
Dataspace_component(size, 0, (addr_t)phys_base, CACHED, true, 0);
|
||||
if (!ds) {
|
||||
PERR("dataspace for core context does not exist");
|
||||
PERR("dataspace for core stack does not exist");
|
||||
return (addr_t)0;
|
||||
}
|
||||
|
||||
addr_t core_local_addr = Native_config::context_area_virtual_base() +
|
||||
addr_t core_local_addr = Native_config::stack_area_virtual_base() +
|
||||
(addr_t)local_addr;
|
||||
|
||||
if (verbose)
|
||||
@ -103,15 +103,14 @@ class Context_area_rm_session : public Rm_session
|
||||
{
|
||||
using Genode::addr_t;
|
||||
|
||||
if ((addr_t)local_addr >= Native_config::context_area_virtual_size())
|
||||
if ((addr_t)local_addr >= Native_config::stack_area_virtual_size())
|
||||
return;
|
||||
|
||||
addr_t const detach = Native_config::context_area_virtual_base() +
|
||||
addr_t const detach = Native_config::stack_area_virtual_base() +
|
||||
(addr_t)local_addr;
|
||||
addr_t const thread_context = Native_config::context_virtual_size();
|
||||
addr_t const pages = ((detach & ~(thread_context - 1))
|
||||
+ thread_context
|
||||
- detach) >> get_page_size_log2();
|
||||
addr_t const stack = Native_config::stack_virtual_size();
|
||||
addr_t const pages = ((detach & ~(stack - 1)) + stack - detach)
|
||||
>> get_page_size_log2();
|
||||
|
||||
unmap_local(detach, pages);
|
||||
}
|
||||
@ -129,7 +128,7 @@ class Context_area_rm_session : public Rm_session
|
||||
};
|
||||
|
||||
|
||||
class Context_area_ram_session : public Ram_session
|
||||
class Stack_area_ram_session : public Ram_session
|
||||
{
|
||||
public:
|
||||
|
||||
@ -154,15 +153,15 @@ class Context_area_ram_session : public Ram_session
|
||||
*/
|
||||
namespace Genode {
|
||||
|
||||
Rm_session *env_context_area_rm_session()
|
||||
Rm_session *env_stack_area_rm_session()
|
||||
{
|
||||
static Context_area_rm_session inst;
|
||||
static Stack_area_rm_session inst;
|
||||
return &inst;
|
||||
}
|
||||
|
||||
Ram_session *env_context_area_ram_session()
|
||||
Ram_session *env_stack_area_ram_session()
|
||||
{
|
||||
static Context_area_ram_session inst;
|
||||
static Stack_area_ram_session inst;
|
||||
return &inst;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user