From e8f82a1da38c04df7032ff42d351fe00f4b01250 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Thu, 30 Apr 2015 15:28:25 +0200 Subject: [PATCH] nova: delay UTCB revocation on thread destruction On NOVA, a Genode thread currently cannot destroy itself by destroying its own 'Thread' object, because in 'Thread_base::_deinit_platform_thread()' it cannot call 'Cpu_session::kill_thread()' anymore after it has revoked its own UTCB. As solution, the revocation of the UTCB can be delayed until its location in the context area is needed by a new thread. Fixes #1505 --- repos/base-nova/src/base/thread/thread_nova.cc | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/repos/base-nova/src/base/thread/thread_nova.cc b/repos/base-nova/src/base/thread/thread_nova.cc index 6896546064..1952375cfa 100644 --- a/repos/base-nova/src/base/thread/thread_nova.cc +++ b/repos/base-nova/src/base/thread/thread_nova.cc @@ -89,6 +89,19 @@ void Thread_base::_init_platform_thread(size_t weight, Type type) return; } + /* + * Revoke possible left-over UTCB of a previously destroyed thread + * which used this context location. + * + * This cannot be done in '_deinit_platform_thread()', because a + * self-destructing thread needs its UTCB to call + * 'Cpu_session::kill_thread()' and is not able to revoke the UTCB + * afterwards. + */ + Rights rwx(true, true, true); + addr_t utcb = reinterpret_cast(&_context->utcb); + revoke(Mem_crd(utcb >> 12, 0, rwx)); + _tid.exc_pt_sel = cap_map()->insert(NUM_INITIAL_PT_LOG2); if (_tid.exc_pt_sel == Native_thread::INVALID_INDEX) throw Cpu_session::Thread_creation_failed(); @@ -124,11 +137,6 @@ void Thread_base::_deinit_platform_thread() revoke(Obj_crd(_tid.exc_pt_sel, NUM_INITIAL_PT_LOG2)); cap_map()->remove(_tid.exc_pt_sel, NUM_INITIAL_PT_LOG2, false); - /* revoke utcb */ - Rights rwx(true, true, true); - addr_t utcb = reinterpret_cast(&_context->utcb); - revoke(Mem_crd(utcb >> 12, 0, rwx)); - /* de-announce thread */ if (_thread_cap.valid()) _cpu_session->kill_thread(_thread_cap);