diff --git a/base-nova/src/base/server/server.cc b/base-nova/src/base/server/server.cc index 3140598433..a6d3c0b185 100644 --- a/base-nova/src/base/server/server.cc +++ b/base-nova/src/base/server/server.cc @@ -38,7 +38,7 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj) Untyped_capability ec_cap, ep_cap; /* _ec_sel is invalid until thread gets started */ - if (tid().ec_sel != ~0UL) + if (tid().ec_sel != Native_thread::INVALID_INDEX) ec_cap = Native_capability(tid().ec_sel); else ec_cap = _thread_cap; @@ -56,8 +56,11 @@ Untyped_capability Rpc_entrypoint::_manage(Rpc_object_base *obj) void Rpc_entrypoint::_dissolve(Rpc_object_base *obj) { - /* Avoid any incoming IPC early, keep local cap solely */ - Nova::revoke(Nova::Obj_crd(obj->cap().local_name(), 0), false); + /* de-announce object from cap_session */ + _cap_session->free(obj->cap()); + + /* avoid any incoming IPC */ + Nova::revoke(Nova::Obj_crd(obj->cap().local_name(), 0), true); /* make sure nobody is able to find this object */ remove_locked(obj); @@ -74,14 +77,9 @@ void Rpc_entrypoint::_dissolve(Rpc_object_base *obj) /* wait until nobody is inside dispatch */ obj->acquire(); - /* De-announce object from cap_session */ - _cap_session->free(obj->cap()); - - /* Revoke also local cap finally */ - Nova::revoke(Nova::Obj_crd(obj->cap().local_name(), 0), true); - /* free cap selector */ - cap_selector_allocator()->free(obj->cap().local_name(), 0); + /* XXX we need cap ref counting to avoid reuse bug which triggers */ + //cap_selector_allocator()->free(obj->cap().local_name(), 0); } void Rpc_entrypoint::_activation_entry() @@ -158,24 +156,27 @@ void Rpc_entrypoint::entry() } -void Rpc_entrypoint::_leave_server_object(Rpc_object_base *obj) +void Rpc_entrypoint::_leave_server_object(Rpc_object_base *) { - { - Lock::Guard lock_guard(_curr_obj_lock); + using namespace Nova; - if (obj == _curr_obj) - cancel_blocking(); - } - - Nova::Utcb *utcb = reinterpret_cast( - Thread_base::myself()->utcb()); + Utcb *utcb = reinterpret_cast(Thread_base::myself()->utcb()); /* don't call ourself */ - if (utcb != reinterpret_cast(&_context->utcb)) { - utcb->msg[0] = 0xdead; - utcb->set_msg_word(1); - if (uint8_t res = Nova::call(obj->cap().local_name())) - PERR("could not clean up entry point - %u", res); - } + if (utcb == reinterpret_cast(this->utcb())) + return; + + /* + * Required outside of core. E.g. launchpad needs it to forcefully kill + * a client which blocks on a session opening request where the service + * is not up yet. + */ + cancel_blocking(); + + utcb->msg[0] = 0xdead; + utcb->set_msg_word(1); + if (uint8_t res = call(_cap.local_name())) + PERR("%8p - could not clean up entry point of thread 0x%p - res %u", + utcb, this->utcb(), res); } @@ -211,7 +212,7 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, * setup in the early bootstrap phase of core. In core the thread * is created 'manually'. */ - if (_tid.ec_sel == ~0UL) { + if (_tid.ec_sel == Native_thread::INVALID_INDEX) { /* create new pager object and assign it to the new thread */ _pager_cap = env()->rm_session()->add_client(_thread_cap); if (!_pager_cap.valid()) @@ -257,6 +258,13 @@ Rpc_entrypoint::Rpc_entrypoint(Cap_session *cap_session, size_t stack_size, */ Thread_base::start(); + /* create cleanup portal */ + _cap = _cap_session->alloc(Native_capability(_tid.ec_sel), + (addr_t)_activation_entry); + if (!_cap.valid()) + throw Cpu_session::Thread_creation_failed(); + + /* prepare portal receive window of new thread */ _rcv_buf.rcv_prepare_pt_sel_window((Nova::Utcb *)&_context->utcb); if (start_on_construction) @@ -275,4 +283,13 @@ Rpc_entrypoint::~Rpc_entrypoint() while (Rpc_object_base *obj = Pool::first()) _dissolve(obj); } + + if (!_cap.valid()) + return; + + /* de-announce object from cap_session */ + _cap_session->free(_cap); + + Nova::revoke(Nova::Obj_crd(_cap.local_name(), 0), true); + cap_selector_allocator()->free(_cap.local_name(), 0); }