mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
Fiasco.OC: fix capability ref-counter issue in core
The Cap_mapping abstraction in core shouldn't use a Cap_index directly, but use Native_capability instead, as it can break reference-counting, as long as the same Cap_index gets used in a Cap_mapping and a Native_capability. This commit finally fixes #208.
This commit is contained in:
parent
a5ea6765d1
commit
28614ce518
@ -60,11 +60,11 @@ void Cap_mapping::map(Native_thread_id task)
|
||||
{
|
||||
using namespace Fiasco;
|
||||
|
||||
if (!local || !Fiasco::Capability::valid(remote))
|
||||
if (!local.valid() || !Fiasco::Capability::valid(remote))
|
||||
return;
|
||||
|
||||
l4_msgtag_t tag = l4_task_map(task, L4_BASE_TASK_CAP,
|
||||
l4_obj_fpage(local->kcap(), 0, L4_FPAGE_RWX),
|
||||
l4_obj_fpage(local.dst(), 0, L4_FPAGE_RWX),
|
||||
((l4_cap_idx_t)remote) | L4_ITEM_MAP);
|
||||
if (l4_msgtag_has_error(tag))
|
||||
PERR("mapping cap failed");
|
||||
@ -72,27 +72,11 @@ void Cap_mapping::map(Native_thread_id task)
|
||||
|
||||
|
||||
Cap_mapping::Cap_mapping(bool alloc, Native_thread_id r)
|
||||
: local(alloc ? _get_cap() : 0), remote(r)
|
||||
{
|
||||
if (local)
|
||||
local->inc();
|
||||
}
|
||||
: local(alloc ? _get_cap() : 0), remote(r) { }
|
||||
|
||||
|
||||
Cap_mapping::Cap_mapping(Core_cap_index* i, Native_thread_id r)
|
||||
: local(i), remote(r)
|
||||
{
|
||||
if (local)
|
||||
local->inc();
|
||||
}
|
||||
|
||||
|
||||
Cap_mapping::~Cap_mapping()
|
||||
{
|
||||
if (local) {
|
||||
cap_map()->remove(local);
|
||||
}
|
||||
}
|
||||
Cap_mapping::Cap_mapping(Native_capability cap, Native_thread_id r)
|
||||
: local(cap), remote(r) { }
|
||||
|
||||
|
||||
/*****************************
|
||||
@ -115,7 +99,6 @@ Native_capability Cap_session_component::alloc(Cap_session_component *session,
|
||||
Core_cap_index* ref = static_cast<Core_cap_index*>(ep.idx());
|
||||
|
||||
ASSERT(ref && ref->pt(), "No valid platform_thread");
|
||||
ASSERT(ref->pt()->thread().local, "No valid platform_thread cap set");
|
||||
|
||||
/*
|
||||
* Allocate new id, and ipc-gate and set id as gate-label
|
||||
@ -131,7 +114,7 @@ Native_capability Cap_session_component::alloc(Cap_session_component *session,
|
||||
|
||||
l4_msgtag_t tag = l4_factory_create_gate(L4_BASE_FACTORY_CAP,
|
||||
idx->kcap(),
|
||||
ref->pt()->thread().local->kcap(), id);
|
||||
ref->pt()->thread().local.dst(), id);
|
||||
if (l4_msgtag_has_error(tag)) {
|
||||
PERR("l4_factory_create_gate failed!");
|
||||
cap_map()->remove(idx);
|
||||
|
@ -45,7 +45,7 @@ void Genode::Cpu_session_component::enable_vcpu(Genode::Thread_capability thread
|
||||
Cpu_thread_component *thread = _lookup_thread(thread_cap);
|
||||
if (!thread) return;
|
||||
|
||||
Native_thread tid = thread->platform_thread()->thread().local->kcap();
|
||||
Native_thread tid = thread->platform_thread()->thread().local.dst();
|
||||
|
||||
l4_msgtag_t tag = l4_thread_vcpu_control(tid, vcpu_state);
|
||||
if (l4_msgtag_has_error(tag))
|
||||
@ -63,7 +63,7 @@ Genode::Cpu_session_component::native_cap(Genode::Thread_capability cap)
|
||||
Cpu_thread_component *thread = _lookup_thread(cap);
|
||||
if (!thread) return Native_capability();
|
||||
|
||||
return Native_capability(thread->platform_thread()->thread().local);
|
||||
return thread->platform_thread()->thread().local;
|
||||
}
|
||||
|
||||
|
||||
@ -106,7 +106,7 @@ void Genode::Cpu_session_component::single_step(Genode::Thread_capability thread
|
||||
Cpu_thread_component *thread = _lookup_thread(thread_cap);
|
||||
if (!thread) return;
|
||||
|
||||
Native_thread tid = thread->platform_thread()->thread().local->kcap();
|
||||
Native_thread tid = thread->platform_thread()->thread().local.dst();
|
||||
|
||||
enum { THREAD_SINGLE_STEP = 0x40000 };
|
||||
int flags = enable ? THREAD_SINGLE_STEP : 0;
|
||||
|
@ -40,14 +40,13 @@ namespace Genode {
|
||||
|
||||
public:
|
||||
|
||||
Core_cap_index* local; /* reference to cap that is mapped */
|
||||
Native_thread_id remote; /* index in cap-space of the other pd */
|
||||
Native_capability local; /* reference to cap that is mapped */
|
||||
Native_thread_id remote; /* index in cap-space of the other pd */
|
||||
|
||||
Cap_mapping(bool alloc=false,
|
||||
Native_thread_id r = Fiasco::L4_INVALID_CAP);
|
||||
Cap_mapping(Core_cap_index* i,
|
||||
Cap_mapping(Native_capability cap,
|
||||
Native_thread_id r = Fiasco::L4_INVALID_CAP);
|
||||
~Cap_mapping();
|
||||
|
||||
/**
|
||||
* Map the cap in local to corresponding task.
|
||||
|
@ -97,7 +97,7 @@ namespace Genode {
|
||||
** Fiasco-specific Accessors **
|
||||
*******************************/
|
||||
|
||||
Core_cap_index* native_task() { return _task.local; }
|
||||
Native_capability native_task() { return _task.local; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ namespace Genode {
|
||||
* Return identification of thread when faulting
|
||||
*/
|
||||
unsigned long pager_object_badge() {
|
||||
return (unsigned long) _thread.local->kcap(); }
|
||||
return (unsigned long) _thread.local.dst(); }
|
||||
|
||||
|
||||
/*******************************
|
||||
|
@ -126,7 +126,7 @@ Platform::Sigma0::Sigma0(Cap_index* i) : Pager_object(0)
|
||||
* We use the Pager_object here in a slightly different manner,
|
||||
* just to tunnel the pager cap to the Platform_thread::start method.
|
||||
*/
|
||||
cap(Native_capability(i));
|
||||
cap(i);
|
||||
}
|
||||
|
||||
|
||||
@ -145,8 +145,8 @@ Platform::Core_pager::Core_pager(Platform_pd *core_pd, Sigma0 *sigma0)
|
||||
using namespace Fiasco;
|
||||
|
||||
l4_thread_control_start();
|
||||
l4_thread_control_pager(thread().local->kcap());
|
||||
l4_thread_control_exc_handler(thread().local->kcap());
|
||||
l4_thread_control_pager(thread().local.dst());
|
||||
l4_thread_control_exc_handler(thread().local.dst());
|
||||
l4_msgtag_t tag = l4_thread_control_commit(L4_BASE_THREAD_CAP);
|
||||
if (l4_msgtag_has_error(tag))
|
||||
PWRN("l4_thread_control_commit failed!");
|
||||
@ -475,8 +475,7 @@ Platform::Platform() :
|
||||
reinterpret_cast<Core_cap_index*>(cap_map()->insert(_cap_id_alloc.alloc()));
|
||||
|
||||
/* setup pd object for core pd */
|
||||
_core_pd = new(core_mem_alloc())
|
||||
Platform_pd(reinterpret_cast<Core_cap_index*>(pdi));
|
||||
_core_pd = new(core_mem_alloc()) Platform_pd(pdi);
|
||||
|
||||
/*
|
||||
* We setup the thread object for thread0 in core pd using a special
|
||||
|
@ -60,8 +60,8 @@ int Platform_pd::bind_thread(Platform_thread *thread)
|
||||
|
||||
/* if it's no core-thread we have to map parent and pager gate cap */
|
||||
if (!thread->core_thread()) {
|
||||
_task.map(_task.local->kcap());
|
||||
_parent.map(_task.local->kcap());
|
||||
_task.map(_task.local.dst());
|
||||
_parent.map(_task.local.dst());
|
||||
}
|
||||
|
||||
/* inform thread about binding */
|
||||
@ -90,14 +90,14 @@ void Platform_pd::unbind_thread(Platform_thread *thread)
|
||||
int Platform_pd::assign_parent(Native_capability parent)
|
||||
{
|
||||
if (!parent.valid()) return -1;
|
||||
_parent.local = reinterpret_cast<Core_cap_index*>(parent.idx());
|
||||
_parent.local = parent;
|
||||
_parent.remote = PARENT_CAP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Platform_pd::Platform_pd(Core_cap_index* i)
|
||||
: _task(i, TASK_CAP)
|
||||
: _task(Native_capability(i), TASK_CAP)
|
||||
{
|
||||
for (unsigned i = 0; i < THREAD_MAX; i++)
|
||||
_threads[i] = (Platform_thread*) 0;
|
||||
@ -113,7 +113,7 @@ Platform_pd::Platform_pd()
|
||||
l4_fpage_t utcb_area = l4_fpage(UTCB_AREA_START,
|
||||
log2<unsigned>(UTCB_AREA_SIZE), 0);
|
||||
l4_msgtag_t tag = l4_factory_create_task(L4_BASE_FACTORY_CAP,
|
||||
_task.local->kcap(), utcb_area);
|
||||
_task.local.dst(), utcb_area);
|
||||
if (l4_msgtag_has_error(tag))
|
||||
PERR("pd creation failed");
|
||||
}
|
||||
|
@ -40,22 +40,22 @@ int Platform_thread::start(void *ip, void *sp)
|
||||
{
|
||||
/* map the pager cap */
|
||||
if (_platform_pd)
|
||||
_pager.map(_platform_pd->native_task()->kcap());
|
||||
_pager.map(_platform_pd->native_task().dst());
|
||||
|
||||
/* reserve utcb area and associate thread with this task */
|
||||
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()->kcap());
|
||||
l4_msgtag_t tag = l4_thread_control_commit(_thread.local->kcap());
|
||||
l4_thread_control_bind(_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!",
|
||||
(unsigned long) _thread.local->kcap());
|
||||
(unsigned long) _thread.local.dst());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* set ip and sp and run the thread */
|
||||
tag = l4_thread_ex_regs(_thread.local->kcap(), (l4_addr_t) ip,
|
||||
tag = l4_thread_ex_regs(_thread.local.dst(), (l4_addr_t) ip,
|
||||
(l4_addr_t) sp, 0);
|
||||
if (l4_msgtag_has_error(tag)) {
|
||||
PWRN("l4_thread_ex_regs failed!");
|
||||
@ -91,7 +91,7 @@ void Platform_thread::pause()
|
||||
* The pager thread, which also acts as exception handler, will
|
||||
* leave the thread in exception state until, it gets woken again
|
||||
*/
|
||||
l4_thread_ex_regs_ret(_thread.local->kcap(), &_pager_obj->state.ip,
|
||||
l4_thread_ex_regs_ret(_thread.local.dst(), &_pager_obj->state.ip,
|
||||
&_pager_obj->state.sp, &flags);
|
||||
bool in_syscall = flags == 0;
|
||||
_pager_obj->state.lock.unlock();
|
||||
@ -106,7 +106,7 @@ void Platform_thread::pause()
|
||||
* the requested thread, and stored its thread state
|
||||
*/
|
||||
while (exc == _pager_obj->state.exceptions && !_pager_obj->state.in_exception)
|
||||
l4_thread_switch(_thread.local->kcap());
|
||||
l4_thread_switch(_thread.local.dst());
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,8 +132,8 @@ void Platform_thread::resume()
|
||||
void Platform_thread::bind(Platform_pd *pd)
|
||||
{
|
||||
_platform_pd = pd;
|
||||
_gate.map(pd->native_task()->kcap());
|
||||
_irq.map(pd->native_task()->kcap());
|
||||
_gate.map(pd->native_task().dst());
|
||||
_irq.map(pd->native_task().dst());
|
||||
}
|
||||
|
||||
|
||||
@ -143,12 +143,12 @@ void Platform_thread::unbind()
|
||||
l4_thread_control_start();
|
||||
l4_thread_control_pager(_gate.remote);
|
||||
l4_thread_control_exc_handler(_gate.remote);
|
||||
if (l4_msgtag_has_error(l4_thread_control_commit(_thread.local->kcap())))
|
||||
if (l4_msgtag_has_error(l4_thread_control_commit(_thread.local.dst())))
|
||||
PWRN("l4_thread_control_commit for %lx failed!",
|
||||
(unsigned long) _thread.local->kcap());
|
||||
(unsigned long) _thread.local.dst());
|
||||
|
||||
/* now force it into a pagefault */
|
||||
l4_thread_ex_regs(_thread.local->kcap(), 0, 0, L4_THREAD_EX_REGS_CANCEL);
|
||||
l4_thread_ex_regs(_thread.local.dst(), 0, 0, L4_THREAD_EX_REGS_CANCEL);
|
||||
|
||||
_platform_pd = (Platform_pd*) 0;
|
||||
}
|
||||
@ -157,7 +157,7 @@ void Platform_thread::unbind()
|
||||
void Platform_thread::pager(Pager_object *pager_obj)
|
||||
{
|
||||
_pager_obj = pager_obj;
|
||||
_pager.local = reinterpret_cast<Core_cap_index*>(pager_obj->cap().idx());
|
||||
_pager.local = pager_obj->cap();
|
||||
}
|
||||
|
||||
|
||||
@ -167,7 +167,7 @@ int Platform_thread::state(Thread_state *state_dst)
|
||||
*state_dst = _pager_obj->state;
|
||||
|
||||
state_dst->kcap = _gate.remote;
|
||||
state_dst->id = _gate.local->id();
|
||||
state_dst->id = _gate.local.local_name();
|
||||
state_dst->utcb = _utcb;
|
||||
|
||||
return 0;
|
||||
@ -176,19 +176,19 @@ int Platform_thread::state(Thread_state *state_dst)
|
||||
|
||||
void Platform_thread::cancel_blocking()
|
||||
{
|
||||
l4_irq_trigger(_irq.local->kcap());
|
||||
l4_irq_trigger(_irq.local.dst());
|
||||
}
|
||||
|
||||
|
||||
void Platform_thread::_create_thread()
|
||||
{
|
||||
l4_msgtag_t tag = l4_factory_create_thread(L4_BASE_FACTORY_CAP,
|
||||
_thread.local->kcap());
|
||||
_thread.local.dst());
|
||||
if (l4_msgtag_has_error(tag))
|
||||
PERR("cannot create more thread kernel-objects!");
|
||||
|
||||
/* create initial gate for thread */
|
||||
_gate.local = static_cast<Core_cap_index*>(Cap_session_component::alloc(0, _thread.local).idx());
|
||||
_gate.local = Cap_session_component::alloc(0, _thread.local);
|
||||
}
|
||||
|
||||
|
||||
@ -196,23 +196,23 @@ void Platform_thread::_finalize_construction(const char *name, unsigned prio)
|
||||
{
|
||||
/* create irq for new thread */
|
||||
l4_msgtag_t tag = l4_factory_create_irq(L4_BASE_FACTORY_CAP,
|
||||
_irq.local->kcap());
|
||||
_irq.local.dst());
|
||||
if (l4_msgtag_has_error(tag))
|
||||
PWRN("creating thread's irq failed");
|
||||
|
||||
/* attach thread to irq */
|
||||
tag = l4_irq_attach(_irq.local->kcap(), 0, _thread.local->kcap());
|
||||
tag = l4_irq_attach(_irq.local.dst(), 0, _thread.local.dst());
|
||||
if (l4_msgtag_has_error(tag))
|
||||
PWRN("attaching thread's irq failed");
|
||||
|
||||
/* set human readable name in kernel debugger */
|
||||
strncpy(_name, name, sizeof(_name));
|
||||
Fiasco::l4_debugger_set_object_name(_thread.local->kcap(), name);
|
||||
Fiasco::l4_debugger_set_object_name(_thread.local.dst(), name);
|
||||
|
||||
/* set priority of thread */
|
||||
prio = Cpu_session::scale_priority(DEFAULT_PRIORITY, prio);
|
||||
l4_sched_param_t params = l4_sched_param(prio);
|
||||
l4_scheduler_run_thread(L4_BASE_SCHEDULER_CAP, _thread.local->kcap(),
|
||||
l4_scheduler_run_thread(L4_BASE_SCHEDULER_CAP, _thread.local.dst(),
|
||||
¶ms);
|
||||
}
|
||||
|
||||
@ -226,7 +226,7 @@ Platform_thread::Platform_thread(const char *name,
|
||||
_platform_pd(0),
|
||||
_pager_obj(0)
|
||||
{
|
||||
_thread.local->pt(this);
|
||||
((Core_cap_index*)_thread.local.idx())->pt(this);
|
||||
_create_thread();
|
||||
_finalize_construction(name, prio);
|
||||
}
|
||||
@ -235,13 +235,13 @@ Platform_thread::Platform_thread(const char *name,
|
||||
Platform_thread::Platform_thread(Core_cap_index* thread,
|
||||
Core_cap_index* irq, const char *name)
|
||||
: _core_thread(true),
|
||||
_thread(thread, L4_BASE_THREAD_CAP),
|
||||
_irq(irq),
|
||||
_thread(Native_capability(thread), L4_BASE_THREAD_CAP),
|
||||
_irq(Native_capability(irq)),
|
||||
_utcb(0),
|
||||
_platform_pd(0),
|
||||
_pager_obj(0)
|
||||
{
|
||||
_thread.local->pt(this);
|
||||
reinterpret_cast<Core_cap_index*>(_thread.local.idx())->pt(this);
|
||||
_finalize_construction(name, 0);
|
||||
}
|
||||
|
||||
@ -254,7 +254,7 @@ Platform_thread::Platform_thread(const char *name)
|
||||
_platform_pd(0),
|
||||
_pager_obj(0)
|
||||
{
|
||||
_thread.local->pt(this);
|
||||
((Core_cap_index*)_thread.local.idx())->pt(this);
|
||||
_create_thread();
|
||||
_finalize_construction(name, 0);
|
||||
}
|
||||
@ -262,6 +262,8 @@ Platform_thread::Platform_thread(const char *name)
|
||||
|
||||
Platform_thread::~Platform_thread()
|
||||
{
|
||||
_gate.local.idx()->dec();
|
||||
|
||||
/*
|
||||
* We inform our protection domain about thread destruction, which will end up in
|
||||
* Thread::unbind()
|
||||
|
@ -50,7 +50,7 @@ void Thread_base::start()
|
||||
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;
|
||||
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;
|
||||
|
||||
pt->start((void *)_thread_start, _context->stack);
|
||||
|
Loading…
x
Reference in New Issue
Block a user