diff --git a/base-hw/include/kernel/syscalls.h b/base-hw/include/kernel/syscalls.h index 2274672b4..3604ed908 100644 --- a/base-hw/include/kernel/syscalls.h +++ b/base-hw/include/kernel/syscalls.h @@ -35,6 +35,7 @@ namespace Kernel /* execution control */ NEW_THREAD = 1, + DELETE_THREAD = 24, START_THREAD = 2, PAUSE_THREAD = 3, RESUME_THREAD = 4, @@ -134,12 +135,23 @@ namespace Kernel * \retval >0 ID of the new thread * \retval 0 if no new thread was created * - * Restricted to core threads. Regaining of the supplied memory is not - * supported by now. + * Restricted to core threads. Regaining of the supplied memory can be done + * through 'delete_thread'. */ inline int new_thread(void * const dst, Genode::Platform_thread * const pt) { return syscall(NEW_THREAD, (Syscall_arg)dst, (Syscall_arg)pt); } + /** + * Delete an existing thread + * + * \param id kernel name of the targeted thread + * + * Restricted to core threads. After calling this, the memory that was + * granted beforehand by 'new_thread' to kernel for managing this thread + * is freed again. + */ + inline void delete_thread(unsigned thread_id) { + syscall(DELETE_THREAD, (Syscall_arg)thread_id); } /** * Start thread with a given context and let it participate in CPU scheduling diff --git a/base-hw/src/base/thread_support.cc b/base-hw/src/base/thread_support.cc index d91df4106..4b8df4e21 100644 --- a/base-hw/src/base/thread_support.cc +++ b/base-hw/src/base/thread_support.cc @@ -50,7 +50,17 @@ void Thread_base::_init_platform_thread() { } void Thread_base::_deinit_platform_thread() -{ env()->cpu_session()->kill_thread(_thread_cap); } +{ + /* detach UTCB */ + size_t const size = sizeof(_context->utcb); + addr_t utcb = Context_allocator::addr_to_base(_context) + + Native_config::context_virtual_size() - size - + Native_config::context_area_virtual_base(); + env_context_area_rm_session()->detach(utcb); + + /* destroy object at the CPU session */ + env()->cpu_session()->kill_thread(_thread_cap); +} void Thread_base::start() diff --git a/base-hw/src/core/include/platform_thread.h b/base-hw/src/core/include/platform_thread.h index e8dfa3360..8f0242ed3 100644 --- a/base-hw/src/core/include/platform_thread.h +++ b/base-hw/src/core/include/platform_thread.h @@ -31,8 +31,6 @@ namespace Genode { class Rm_client; class Platform_thread; - size_t kernel_thread_size(); - /** * Userland interface for the management of kernel thread-objects */ @@ -51,12 +49,18 @@ namespace Genode { Software_tlb * _software_tlb; Ram_dataspace_capability _utcb; char _name[NAME_MAX_LEN]; + void * _kernel_thread; /** * Common construction part */ void _init(); + /* + * Check if this thread will attach its UTCB by itself + */ + bool _attaches_utcb_by_itself(); + public: /** @@ -73,6 +77,11 @@ namespace Genode { Platform_thread(const char * name, unsigned int priority, addr_t utcb); + /** + * Destructor + */ + ~Platform_thread(); + /** * Join PD identified by 'pd_id' * @@ -124,15 +133,6 @@ namespace Genode { return -1; }; - /** - * Destructor - */ - ~Platform_thread() - { - kernel_log() << __PRETTY_FUNCTION__ << ": Not implemented\n"; - while (1) ; - } - /** * Return unique identification of this thread as faulter */ diff --git a/base-hw/src/core/kernel.cc b/base-hw/src/core/kernel.cc index 7babbc34a..50e24a75d 100644 --- a/base-hw/src/core/kernel.cc +++ b/base-hw/src/core/kernel.cc @@ -697,8 +697,17 @@ namespace Kernel * Ensures that we have a unique ID and * can be found through the static object pool. */ - Object() : Pool::Entry(_id_alloc()->alloc()) - { pool()->insert(static_cast(this)); } + Object() : Pool::Entry(_id_alloc()->alloc()) { + pool()->insert(static_cast(this)); } + + /** + * Destructor + */ + ~Object() + { + pool()->remove(static_cast(this)); + _id_alloc()->free(Pool::Entry::id()); + } }; /** @@ -1539,6 +1548,23 @@ namespace Kernel user->user_arg_0((Syscall_ret)t->id()); } + /** + * Do specific syscall for 'user', for details see 'syscall.h' + */ + void do_delete_thread(Thread * const user) + { + /* check permissions */ + assert(user->pd_id() == core_id()); + + /* get targeted thread */ + unsigned thread_id = (unsigned)user->user_arg_1(); + Thread * const thread = Thread::pool()->object(thread_id); + assert(thread); + + /* destroy thread */ + thread->~Thread(); + } + /** * Do specific syscall for 'user', for details see 'syscall.h' @@ -1901,6 +1927,7 @@ namespace Kernel /* 21 */ do_new_signal_context, /* 22 */ do_await_signal, /* 23 */ do_submit_signal, + /* 24 */ do_delete_thread, }; enum { MAX_SYSCALL = sizeof(handle_sysc)/sizeof(handle_sysc[0]) - 1 }; diff --git a/base-hw/src/core/platform_thread.cc b/base-hw/src/core/platform_thread.cc index efc90c3ab..d1333de96 100644 --- a/base-hw/src/core/platform_thread.cc +++ b/base-hw/src/core/platform_thread.cc @@ -21,6 +21,44 @@ using namespace Genode; namespace Kernel { unsigned core_id(); } +bool Platform_thread::_attaches_utcb_by_itself() +{ + /* + * If this is a main thread outside of core it'll not manage its + * virtual context area by itself, as it is done for other threads + * through a sub RM-session. + */ + return _pd_id == Kernel::core_id() || !_main_thread; +} + + +Platform_thread::~Platform_thread() +{ + /* detach UTCB if main thread outside core */ + if (!_attaches_utcb_by_itself()) { + assert(_rm_client); + Rm_session_component * const rm = _rm_client->member_rm_session(); + rm->detach(_virt_utcb); + } + /* free UTCB */ + if (_pd_id == Kernel::core_id()) { + Range_allocator * const ram = platform()->ram_alloc(); + ram->free((void *)_phys_utcb, sizeof(Native_utcb)); + } else { + Ram_session_component * const ram = + dynamic_cast(core_env()->ram_session()); + assert(ram); + ram->free(_utcb); + } + /* destroy object at the kernel */ + Kernel::delete_thread(_id); + + /* free kernel object space */ + Range_allocator * ram = platform()->ram_alloc(); + ram->free(&_kernel_thread, Kernel::thread_size()); +} + + Platform_thread::Platform_thread(const char * name, Thread_base * const thread_base, unsigned long const stack_size, @@ -85,10 +123,9 @@ int Platform_thread::join_pd(unsigned long const pd_id, void Platform_thread::_init() { /* create kernel object */ - void * kernel_thread; Range_allocator * ram = platform()->ram_alloc(); - assert(ram->alloc(Kernel::thread_size(), &kernel_thread)); - _id = Kernel::new_thread(kernel_thread, this); + assert(ram->alloc(Kernel::thread_size(), &_kernel_thread)); + _id = Kernel::new_thread(_kernel_thread, this); assert(_id); } @@ -98,13 +135,8 @@ int Platform_thread::start(void * ip, void * sp, unsigned int cpu_no) /* check thread attributes */ assert(_pd_id); - /* - * If this is a main thread outside of core it'll not manage its - * virtual context area by itself, as it is done for other threads - * through a sub RM-session. Therefore we attach the UTCB to its - * address space before it gets started. - */ - if (_pd_id != Kernel::core_id() && _main_thread) + /* attach UTCB if the thread can't do this by itself */ + if (!_attaches_utcb_by_itself()) { /* * Declare page aligned virtual UTCB outside the context area. diff --git a/os/run/signal.run b/os/run/signal.run index ddb5f43e2..4fee2d3a8 100644 --- a/os/run/signal.run +++ b/os/run/signal.run @@ -13,6 +13,7 @@ install_config { + diff --git a/os/src/drivers/timer/nova/timer_session_component.h b/os/src/drivers/timer/nova/timer_session_component.h index be809f060..6cffa22b3 100644 --- a/os/src/drivers/timer/nova/timer_session_component.h +++ b/os/src/drivers/timer/nova/timer_session_component.h @@ -149,10 +149,7 @@ namespace Timer { _session_cap(_entrypoint.manage(this)), _barrier(Genode::Cancelable_lock::LOCKED), _wake_up_alarm(&_barrier) - { - PDBG("created new session component, _session_cap.valid=%d", - _session_cap.valid()); - } + { } /** * Destructor