From 33334b4f4bab4d62b284eb8348587871ed24adca Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Tue, 26 Jun 2012 11:49:55 +0200 Subject: [PATCH] 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. --- base-nova/src/base/pager/pager.cc | 10 +++++----- base-nova/src/base/server/server.cc | 9 ++++++++- base-nova/src/core/thread_start.cc | 9 +++++++-- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/base-nova/src/base/pager/pager.cc b/base-nova/src/base/pager/pager.cc index 24291a965c..9114f93c71 100644 --- a/base-nova/src/base/pager/pager.cc +++ b/base-nova/src/base/pager/pager.cc @@ -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); diff --git a/base-nova/src/base/server/server.cc b/base-nova/src/base/server/server.cc index 1bfbad7d8f..6f5d9ccd5c 100644 --- a/base-nova/src/base/server/server.cc +++ b/base-nova/src/base/server/server.cc @@ -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(Thread_base::myself()->utcb()); /* don't call ourself */ if (utcb != reinterpret_cast(&_context->utcb)) { - utcb->mtd = 0; + utcb->set_msg_word(0); if (Nova::call(obj->cap().dst() + 1)) PERR("could not clean up entry point"); } diff --git a/base-nova/src/core/thread_start.cc b/base-nova/src/core/thread_start.cc index 90cdfbfac4..4589ee6557 100644 --- a/base-nova/src/core/thread_start.cc +++ b/base-nova/src/core/thread_start.cc @@ -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); +}