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:
Stefan Kalkowski 2012-08-29 17:07:38 +02:00 committed by Norman Feske
parent a5ea6765d1
commit 28614ce518
9 changed files with 52 additions and 69 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -97,7 +97,7 @@ namespace Genode {
** Fiasco-specific Accessors **
*******************************/
Core_cap_index* native_task() { return _task.local; }
Native_capability native_task() { return _task.local; }
};
}

View File

@ -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(); }
/*******************************

View File

@ -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

View File

@ -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");
}

View File

@ -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(),
&params);
}
@ -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()

View File

@ -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);