diff --git a/base-foc/src/base/env/cap_map.cc b/base-foc/src/base/env/cap_map.cc index db31ab1075..93c6600737 100644 --- a/base-foc/src/base/env/cap_map.cc +++ b/base-foc/src/base/env/cap_map.cc @@ -39,6 +39,10 @@ Genode::addr_t Genode::Cap_index::kcap() { return cap_idx_alloc()->idx_to_kcap(this); } +/**************************** + ** Capability_map class ** + ****************************/ + Genode::Cap_index* Genode::Capability_map::find(int id) { using namespace Genode; @@ -52,10 +56,6 @@ Genode::Cap_index* Genode::Capability_map::find(int id) } -/**************************** - ** Capability_map class ** - ****************************/ - Genode::Cap_index* Genode::Capability_map::insert(int id) { using namespace Genode; @@ -63,8 +63,10 @@ Genode::Cap_index* Genode::Capability_map::insert(int id) Lock_guard guard(_lock); Cap_index *i = cap_idx_alloc()->alloc(1); - i->id(id); - _tree.insert(i); + if (i) { + i->id(id); + _tree.insert(i); + } return i; } @@ -76,8 +78,10 @@ Genode::Cap_index* Genode::Capability_map::insert(int id, addr_t kcap) Lock_guard guard(_lock); Cap_index *i = cap_idx_alloc()->alloc(kcap, 1); - i->id(id); - _tree.insert(i); + if (i) { + i->id(id); + _tree.insert(i); + } return i; } diff --git a/base-foc/src/base/thread/thread_start.cc b/base-foc/src/base/thread/thread_start.cc index f1109a7c29..1dfa0cae5c 100644 --- a/base-foc/src/base/thread/thread_start.cc +++ b/base-foc/src/base/thread/thread_start.cc @@ -57,9 +57,24 @@ void Thread_base::start() _tid = state.kcap; _context->utcb = state.utcb; - l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_BADGE] = state.id; - l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this; - cap_map()->insert(state.id, state.kcap); + /** + * If we've a dead capability in our database, which is already + * revoked, its id might be reused. + */ + Cap_index *i = cap_map()->find(state.id); + if (i) { + l4_msgtag_t tag = l4_task_cap_valid(L4_BASE_TASK_CAP, i->kcap()); + if (!tag.label()) + cap_map()->remove(i); + } + + try { + l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_BADGE] = state.id; + l4_utcb_tcr_u(state.utcb)->user[UTCB_TCR_THREAD_OBJ] = (addr_t)this; + cap_map()->insert(state.id, state.kcap); + } catch(Cap_index_allocator::Region_conflict) { + PERR("could not insert id %lx", state.id); + } /* register initial IP and SP at core */ addr_t thread_sp = (addr_t)&_context->stack[-4];