Fix: Avoid deadlock during cleanup of entrypoint

Invoke cancel_blocking before calling the
cleanup portal of the rpc_entrypoint. If a rpc_entrypoint
is blocked in a semaphore the cleanup call gets
stuck forever.
This commit is contained in:
Alexander Boettcher 2012-06-26 11:49:55 +02:00 committed by Norman Feske
parent f328f3786b
commit 33334b4f4b
3 changed files with 20 additions and 8 deletions

View File

@ -162,12 +162,12 @@ Pager_object::~Pager_object()
revoke(Obj_crd(_pt_sel, 0), true);
/* Make sure nobody is in the handler anymore by doing an IPC to a
* local cap pointing to same serving thread. When the call returns
* we know that nobody is handled by this object anymore, because
* all remotely available portals had been revoked beforehand.
*/
* local cap pointing to same serving thread. When the call returns
* we know that nobody is handled by this object anymore, because
* all remotely available portals had been revoked beforehand.
*/
Utcb *utcb = (Utcb *)Thread_base::myself()->utcb();
utcb->mtd = 0;
utcb->set_msg_word(0);
if (uint8_t res = call(_pt_cleanup))
PERR("failure - cleanup call failed res=%d", res);

View File

@ -173,10 +173,17 @@ void Rpc_entrypoint::entry()
void Rpc_entrypoint::_leave_server_object(Rpc_object_base *obj)
{
{
Lock::Guard lock_guard(_curr_obj_lock);
if (obj == _curr_obj)
cancel_blocking();
}
Nova::Utcb *utcb = reinterpret_cast<Nova::Utcb *>(Thread_base::myself()->utcb());
/* don't call ourself */
if (utcb != reinterpret_cast<Nova::Utcb *>(&_context->utcb)) {
utcb->mtd = 0;
utcb->set_msg_word(0);
if (Nova::call(obj->cap().dst() + 1))
PERR("could not clean up entry point");
}

View File

@ -41,9 +41,9 @@ void Thread_base::_init_platform_thread()
_tid.pd_sel = cap_selector_allocator()->pd_sel();
/* create running semaphore required for locking */
int res = Nova::create_sm(_tid.rs_sel, _tid.pd_sel, 0);
uint8_t res = Nova::create_sm(_tid.rs_sel, _tid.pd_sel, 0);
if (res)
PERR("create_sm returned %d", res);
PERR("create_sm returned %u", res);
}
@ -61,3 +61,8 @@ void Thread_base::start()
* On NOVA, core never starts regular threads.
*/
}
void Thread_base::cancel_blocking()
{
Nova::sm_ctrl(_tid.rs_sel, Nova::SEMAPHORE_UP);
}