From 5447c406e5c59b8720811117f0c1b93a53736db9 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Fri, 24 Jan 2014 12:06:21 +0100 Subject: [PATCH] thread: rearrange thread context management Use a bit allocator for the allocation management of thread contexts, instead of holding allocation information within the Thread_base objects, which lead to race conditions in the past. Moreover, extend the Thread_base class interface with the ability to to add additional stacks to a thread, and associate the context they're located in with the corresponding Thread_base object. Additional stacks can be used to do user-level scheduling with stack switching, without breaking Genode's API. Fixes #1024 Fixes #1036 --- base-codezero/include/base/native_types.h | 8 +- base-fiasco/include/base/native_types.h | 8 +- base-foc/include/arm/base/native_config.h | 38 +++++++ base-foc/include/base/native_types.h | 16 +-- base-foc/include/x86/base/native_config.h | 38 +++++++ base-foc/lib/mk/arm/base.mk | 3 - base-foc/lib/mk/{base.inc => base.mk} | 0 base-foc/lib/mk/exynos5/base.mk | 3 - base-foc/lib/mk/x86/base.mk | 3 - .../thread/arndale/thread_context_area.cc | 19 ---- base-foc/src/base/thread/thread.cc | 99 ++++++++++--------- .../src/base/thread/thread_context_area.cc | 11 --- base-foc/src/core/arndale/target.mk | 3 - base-foc/src/core/target.inc | 1 - base-host/include/base/native_types.h | 8 +- base-hw/include/base/native_types.h | 8 +- base-hw/src/core/thread.cc | 3 - base-linux/include/base/native_types.h | 8 +- base-linux/src/platform/lx_hybrid.cc | 2 - base-nova/include/base/native_types.h | 8 +- base-okl4/include/base/native_types.h | 8 +- base-pistachio/include/base/native_types.h | 8 +- base/include/base/thread.h | 60 ++++++++--- base/src/base/thread/thread.cc | 66 +++++++------ dde_linux/src/lib/usb/include/routine.h | 9 +- 25 files changed, 259 insertions(+), 179 deletions(-) create mode 100644 base-foc/include/arm/base/native_config.h create mode 100644 base-foc/include/x86/base/native_config.h delete mode 100644 base-foc/lib/mk/arm/base.mk rename base-foc/lib/mk/{base.inc => base.mk} (100%) delete mode 100644 base-foc/lib/mk/exynos5/base.mk delete mode 100644 base-foc/lib/mk/x86/base.mk delete mode 100644 base-foc/src/base/thread/arndale/thread_context_area.cc delete mode 100644 base-foc/src/base/thread/thread_context_area.cc diff --git a/base-codezero/include/base/native_types.h b/base-codezero/include/base/native_types.h index 5bb4346c7..81c91a976 100644 --- a/base-codezero/include/base/native_types.h +++ b/base-codezero/include/base/native_types.h @@ -95,13 +95,15 @@ namespace Genode { /** * Thread-context area configuration. */ - static addr_t context_area_virtual_base() { return 0x40000000UL; } - static addr_t context_area_virtual_size() { return 0x10000000UL; } + static constexpr addr_t context_area_virtual_base() { + return 0x40000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } /** * Size of virtual address region holding the context of one thread */ - static addr_t context_virtual_size() { return 0x00100000UL; } + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } }; struct Native_pd_args { }; diff --git a/base-fiasco/include/base/native_types.h b/base-fiasco/include/base/native_types.h index 7efc64626..0946fd58e 100644 --- a/base-fiasco/include/base/native_types.h +++ b/base-fiasco/include/base/native_types.h @@ -78,13 +78,15 @@ namespace Genode { /** * Thread-context area configuration. */ - static addr_t context_area_virtual_base() { return 0x40000000UL; } - static addr_t context_area_virtual_size() { return 0x10000000UL; } + static constexpr addr_t context_area_virtual_base() { + return 0x40000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } /** * Size of virtual address region holding the context of one thread */ - static addr_t context_virtual_size() { return 0x00100000UL; } + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } }; struct Native_pd_args { }; diff --git a/base-foc/include/arm/base/native_config.h b/base-foc/include/arm/base/native_config.h new file mode 100644 index 000000000..97bcf113a --- /dev/null +++ b/base-foc/include/arm/base/native_config.h @@ -0,0 +1,38 @@ +/* + * \brief Platform-specific context area definitions + * \author Stefan Kalkowski + * \date 2014-01-24 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__BASE__NATIVE_CONFIG_H_ +#define _INCLUDE__BASE__NATIVE_CONFIG_H_ + +#include + +namespace Genode { + + struct Native_config + { + /** + * Thread-context area configuration + */ + static constexpr addr_t context_area_virtual_base() { + return 0x20000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } + + /** + * Size of virtual address region holding the context of one thread + */ + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } + }; +} + +#endif /* _INCLUDE__BASE__NATIVE_CONFIG_H_ */ diff --git a/base-foc/include/base/native_types.h b/base-foc/include/base/native_types.h index bfc56f8ac..323a9c9e8 100644 --- a/base-foc/include/base/native_types.h +++ b/base-foc/include/base/native_types.h @@ -1,8 +1,8 @@ #ifndef _INCLUDE__BASE__NATIVE_TYPES_H_ #define _INCLUDE__BASE__NATIVE_TYPES_H_ +#include #include -#include namespace Fiasco { #include @@ -178,20 +178,6 @@ namespace Genode { typedef int Native_connection_state; - struct Native_config - { - /** - * Thread-context area configuration - */ - static addr_t context_area_virtual_base(); - static addr_t context_area_virtual_size() { return 0x10000000UL; } - - /** - * Size of virtual address region holding the context of one thread - */ - static addr_t context_virtual_size() { return 0x00100000UL; } - }; - struct Native_pd_args { }; } diff --git a/base-foc/include/x86/base/native_config.h b/base-foc/include/x86/base/native_config.h new file mode 100644 index 000000000..6fbf3c7ab --- /dev/null +++ b/base-foc/include/x86/base/native_config.h @@ -0,0 +1,38 @@ +/* + * \brief Platform-specific context area definitions + * \author Stefan Kalkowski + * \date 2014-01-24 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__BASE__NATIVE_CONFIG_H_ +#define _INCLUDE__BASE__NATIVE_CONFIG_H_ + +#include + +namespace Genode { + + struct Native_config + { + /** + * Thread-context area configuration + */ + static constexpr addr_t context_area_virtual_base() { + return 0x40000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } + + /** + * Size of virtual address region holding the context of one thread + */ + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } + }; +} + +#endif /* _INCLUDE__BASE__NATIVE_CONFIG_H_ */ diff --git a/base-foc/lib/mk/arm/base.mk b/base-foc/lib/mk/arm/base.mk deleted file mode 100644 index 5d2889686..000000000 --- a/base-foc/lib/mk/arm/base.mk +++ /dev/null @@ -1,3 +0,0 @@ -include $(REP_DIR)/lib/mk/base.inc - -SRC_CC += thread/thread_context_area.cc diff --git a/base-foc/lib/mk/base.inc b/base-foc/lib/mk/base.mk similarity index 100% rename from base-foc/lib/mk/base.inc rename to base-foc/lib/mk/base.mk diff --git a/base-foc/lib/mk/exynos5/base.mk b/base-foc/lib/mk/exynos5/base.mk deleted file mode 100644 index 5de464872..000000000 --- a/base-foc/lib/mk/exynos5/base.mk +++ /dev/null @@ -1,3 +0,0 @@ -include $(REP_DIR)/lib/mk/base.inc - -SRC_CC += thread/arndale/thread_context_area.cc diff --git a/base-foc/lib/mk/x86/base.mk b/base-foc/lib/mk/x86/base.mk deleted file mode 100644 index 5d2889686..000000000 --- a/base-foc/lib/mk/x86/base.mk +++ /dev/null @@ -1,3 +0,0 @@ -include $(REP_DIR)/lib/mk/base.inc - -SRC_CC += thread/thread_context_area.cc diff --git a/base-foc/src/base/thread/arndale/thread_context_area.cc b/base-foc/src/base/thread/arndale/thread_context_area.cc deleted file mode 100644 index 9764793d7..000000000 --- a/base-foc/src/base/thread/arndale/thread_context_area.cc +++ /dev/null @@ -1,19 +0,0 @@ -/* - * \brief Arndale specific definition of the context area location - * \author Sebastian Sumpf - * \date 2013-02-12 - * - * We need to place the context area within core outside the physical memory. - * Sigma0 maps physical to core-local memory always 1:1 when using - * SIGMA0_REQ_FPAGE_ANY. Those mappings would interfere with the context area. - * - * Because the UTCB area of a task resides at the end of the context area and - * its address gets calculated by core, the context area in other tasks needs - * to be at the same address as in core. - */ - -#include - -using namespace Genode; - -addr_t Native_config::context_area_virtual_base() { return 0x20000000UL; } diff --git a/base-foc/src/base/thread/thread.cc b/base-foc/src/base/thread/thread.cc index 6f8dcef83..e9ceace89 100644 --- a/base-foc/src/base/thread/thread.cc +++ b/base-foc/src/base/thread/thread.cc @@ -17,10 +17,6 @@ #include #include -namespace Fiasco { -#include -} - using namespace Genode; @@ -41,7 +37,8 @@ namespace Genode { Thread_base::Context *Thread_base::Context_allocator::base_to_context(addr_t base) { - addr_t result = base + Native_config::context_virtual_size() - sizeof(Context); + addr_t result = base + Native_config::context_virtual_size() + - sizeof(Context); return reinterpret_cast(result); } @@ -52,14 +49,17 @@ addr_t Thread_base::Context_allocator::addr_to_base(void *addr) } -bool Thread_base::Context_allocator::_is_in_use(addr_t base) +size_t Thread_base::Context_allocator::base_to_idx(addr_t base) { - List_element *le = _threads.first(); - for (; le; le = le->next()) - if (base_to_context(base) == le->object()->_context) - return true; + return (base - Native_config::context_area_virtual_base()) / + Native_config::context_virtual_size(); +} - return false; + +addr_t Thread_base::Context_allocator::idx_to_base(size_t idx) +{ + return Native_config::context_area_virtual_base() + + idx * Native_config::context_virtual_size(); } @@ -67,30 +67,19 @@ Thread_base::Context *Thread_base::Context_allocator::alloc(Thread_base *thread_ { Lock::Guard _lock_guard(_threads_lock); - /* - * Find slot in context area for the new context - */ - addr_t base = Native_config::context_area_virtual_base(); - for (; _is_in_use(base); base += Native_config::context_virtual_size()) { - - /* check upper bound of context area */ - if (base >= Native_config::context_area_virtual_base() + Native_config::context_area_virtual_size()) - return 0; + try { + return base_to_context(idx_to_base(_alloc.alloc())); + } catch(Bit_allocator::Out_of_indices) { + return 0; } - - _threads.insert(&thread_base->_list_element); - - return base_to_context(base); } -void Thread_base::Context_allocator::free(Thread_base *thread_base) +void Thread_base::Context_allocator::free(Context *context) { Lock::Guard _lock_guard(_threads_lock); - _threads.remove(&thread_base->_list_element); - - thread_base->_context->~Context(); + _alloc.free(base_to_idx(addr_to_base(context))); } @@ -124,7 +113,8 @@ Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) enum { PAGE_SIZE_LOG2 = 12 }; size_t ds_size = align_addr(stack_size, PAGE_SIZE_LOG2); - if (stack_size >= Native_config::context_virtual_size() - sizeof(Native_utcb) - (1 << PAGE_SIZE_LOG2)) + if (stack_size >= Native_config::context_virtual_size() - + sizeof(Native_utcb) - (1UL << PAGE_SIZE_LOG2)) throw Stack_too_large(); /* @@ -132,8 +122,9 @@ Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) * * The stack is always located at the top of the context. */ - addr_t ds_addr = Context_allocator::addr_to_base(context) + Native_config::context_virtual_size() - - ds_size; + addr_t ds_addr = Context_allocator::addr_to_base(context) + + Native_config::context_virtual_size() - + ds_size; /* add padding for UTCB if defined for the platform */ if (sizeof(Native_utcb) >= (1 << PAGE_SIZE_LOG2)) @@ -144,41 +135,47 @@ Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) try { ds_cap = env_context_area_ram_session()->alloc(ds_size); addr_t attach_addr = ds_addr - Native_config::context_area_virtual_base(); - env_context_area_rm_session()->attach_at(ds_cap, attach_addr, ds_size); - - } catch (Ram_session::Alloc_failed) { - throw Stack_alloc_failed(); + if (attach_addr != (addr_t)env_context_area_rm_session()->attach_at(ds_cap, attach_addr, ds_size)) + throw Stack_alloc_failed(); } + catch (Ram_session::Alloc_failed) { throw Stack_alloc_failed(); } /* * Now the thread context is backed by memory, so it is safe to access its * members. * - * We need to initalize the context object's memory with zeroes, + * We need to initialize the context object's memory with zeroes, * otherwise the ds_cap isn't invalid. That would cause trouble * when the assignment operator of Native_capability is used. */ - memset(context, 0, sizeof(Context)); + memset(context, 0, sizeof(Context) - sizeof(Context::utcb)); context->thread_base = this; context->stack_base = ds_addr; context->ds_cap = ds_cap; + return context; } -void Thread_base::_free_context() +void Thread_base::_free_context(Context* context) { - addr_t ds_addr = _context->stack_base - Native_config::context_area_virtual_base(); - Ram_dataspace_capability ds_cap = _context->ds_cap; - _context_allocator()->free(this); + addr_t ds_addr = context->stack_base - Native_config::context_area_virtual_base(); + Ram_dataspace_capability ds_cap = context->ds_cap; + + /* call de-constructor explicitly before memory gets detached */ + context->~Context(); + Genode::env_context_area_rm_session()->detach((void *)ds_addr); Genode::env_context_area_ram_session()->free(ds_cap); + + /* context area ready for reuse */ + _context_allocator()->free(context); } void Thread_base::name(char *dst, size_t dst_len) { - snprintf(dst, min(dst_len, (size_t)Context::NAME_LEN), _context->name); + snprintf(dst, min(dst_len, (size_t)Context::NAME_LEN), "%s", _context->name); } @@ -196,9 +193,23 @@ void Thread_base::join() } +void* Thread_base::alloc_secondary_stack(char const *name, size_t stack_size) +{ + Context *context = _alloc_context(stack_size); + strncpy(context->name, name, sizeof(context->name)); + return (void *)context->stack_top(); +} + + +void Thread_base::free_secondary_stack(void* stack_addr) +{ + addr_t base = Context_allocator::addr_to_base(stack_addr); + _free_context(Context_allocator::base_to_context(base)); +} + + Thread_base::Thread_base(const char *name, size_t stack_size) : - _list_element(this), _context(_alloc_context(stack_size)), _join_lock(Lock::LOCKED) { @@ -210,5 +221,5 @@ Thread_base::Thread_base(const char *name, size_t stack_size) Thread_base::~Thread_base() { _deinit_platform_thread(); - _free_context(); + _free_context(_context); } diff --git a/base-foc/src/base/thread/thread_context_area.cc b/base-foc/src/base/thread/thread_context_area.cc deleted file mode 100644 index 2597172ab..000000000 --- a/base-foc/src/base/thread/thread_context_area.cc +++ /dev/null @@ -1,11 +0,0 @@ -/* - * \brief Generic definitions for the location of the thread-context area - * \author Sebastian Sumpf - * \date 2013-02-12 - */ - -#include - -using namespace Genode; - -addr_t Native_config::context_area_virtual_base() { return 0x40000000UL; } diff --git a/base-foc/src/core/arndale/target.mk b/base-foc/src/core/arndale/target.mk index 4290ec929..6a182a0b0 100644 --- a/base-foc/src/core/arndale/target.mk +++ b/base-foc/src/core/arndale/target.mk @@ -1,6 +1,3 @@ -# override default location of thread context area within core -vpath thread_context_area.cc $(REP_DIR)/src/base/thread/arndale - include $(PRG_DIR)/../target.inc LD_TEXT_ADDR = 0x80100000 diff --git a/base-foc/src/core/target.inc b/base-foc/src/core/target.inc index dacf93940..3c6e3078d 100644 --- a/base-foc/src/core/target.inc +++ b/base-foc/src/core/target.inc @@ -33,7 +33,6 @@ SRC_CC = cap_session_component.cc \ signal_source_component.cc \ trace_session_component.cc \ thread_start.cc \ - thread_context_area.cc \ core_printf.cc INC_DIR += $(REP_DIR)/src/core/include \ diff --git a/base-host/include/base/native_types.h b/base-host/include/base/native_types.h index 4e752f887..d1e50c7dd 100644 --- a/base-host/include/base/native_types.h +++ b/base-host/include/base/native_types.h @@ -37,13 +37,15 @@ namespace Genode { /** * Thread-context area configuration. */ - static addr_t context_area_virtual_base() { return 0x40000000UL; } - static addr_t context_area_virtual_size() { return 0x10000000UL; } + static constexpr addr_t context_area_virtual_base() { + return 0x40000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } /** * Size of virtual address region holding the context of one thread */ - static addr_t context_virtual_size() { return 0x00100000UL; } + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } }; struct Native_pd_args { }; diff --git a/base-hw/include/base/native_types.h b/base-hw/include/base/native_types.h index c6b4ee489..3db5f418f 100644 --- a/base-hw/include/base/native_types.h +++ b/base-hw/include/base/native_types.h @@ -106,13 +106,15 @@ namespace Genode /** * Thread-context area configuration. */ - static addr_t context_area_virtual_base() { return 0x40000000UL; } - static addr_t context_area_virtual_size() { return 0x10000000UL; } + static constexpr addr_t context_area_virtual_base() { + return 0x40000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } /** * Size of virtual address region holding the context of one thread */ - static addr_t context_virtual_size() { return 0x00100000UL; } + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } }; struct Native_pd_args { }; diff --git a/base-hw/src/core/thread.cc b/base-hw/src/core/thread.cc index 8c985a44b..85dab8540 100644 --- a/base-hw/src/core/thread.cc +++ b/base-hw/src/core/thread.cc @@ -31,7 +31,6 @@ Native_utcb * Thread_base::utcb() { if (this) { return _tid.platform_thread->utcb_virt(); } return _main_thread_utcb; - } @@ -55,8 +54,6 @@ void Thread_base::_thread_start() Thread_base::Thread_base(const char * const label, size_t const stack_size) -: - _list_element(this) { _tid.platform_thread = new (platform()->core_mem_alloc()) Platform_thread(stack_size, Kernel::core_id(), label); diff --git a/base-linux/include/base/native_types.h b/base-linux/include/base/native_types.h index 6d4333b14..3f99ab4fd 100644 --- a/base-linux/include/base/native_types.h +++ b/base-linux/include/base/native_types.h @@ -131,13 +131,15 @@ namespace Genode { * Please update platform-specific files after changing these * values, e.g., 'base-linux/src/platform/context_area.*.ld'. */ - static addr_t context_area_virtual_base() { return 0x40000000UL; } - static addr_t context_area_virtual_size() { return 0x10000000UL; } + static constexpr addr_t context_area_virtual_base() { + return 0x40000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } /** * Size of virtual address region holding the context of one thread */ - static addr_t context_virtual_size() { return 0x00100000UL; } + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } }; class Native_pd_args diff --git a/base-linux/src/platform/lx_hybrid.cc b/base-linux/src/platform/lx_hybrid.cc index 4fb5cf476..cf70b1144 100644 --- a/base-linux/src/platform/lx_hybrid.cc +++ b/base-linux/src/platform/lx_hybrid.cc @@ -402,8 +402,6 @@ void Thread_base::join() Thread_base::Thread_base(const char *name, size_t stack_size) -: - _list_element(this) { _tid.meta_data = new (env()->heap()) Thread_meta_data_created(this); diff --git a/base-nova/include/base/native_types.h b/base-nova/include/base/native_types.h index 8b13cef86..e01447dfd 100644 --- a/base-nova/include/base/native_types.h +++ b/base-nova/include/base/native_types.h @@ -257,13 +257,15 @@ namespace Genode { /** * Thread-context area configuration. */ - static addr_t context_area_virtual_base() { return 0xa0000000UL; } - static addr_t context_area_virtual_size() { return 0x10000000UL; } + static constexpr addr_t context_area_virtual_base() { + return 0xa0000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } /** * Size of virtual address region holding the context of one thread */ - static addr_t context_virtual_size() { return 0x00100000UL; } + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } }; struct Native_pd_args { }; diff --git a/base-okl4/include/base/native_types.h b/base-okl4/include/base/native_types.h index cb75eb681..9e953b633 100644 --- a/base-okl4/include/base/native_types.h +++ b/base-okl4/include/base/native_types.h @@ -95,13 +95,15 @@ namespace Genode { /** * Thread-context area configuration. */ - static addr_t context_area_virtual_base() { return 0x40000000UL; } - static addr_t context_area_virtual_size() { return 0x10000000UL; } + static constexpr addr_t context_area_virtual_base() { + return 0x40000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } /** * Size of virtual address region holding the context of one thread */ - static addr_t context_virtual_size() { return 0x00100000UL; } + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } }; struct Native_pd_args { }; diff --git a/base-pistachio/include/base/native_types.h b/base-pistachio/include/base/native_types.h index 0df6b187c..7803408a5 100644 --- a/base-pistachio/include/base/native_types.h +++ b/base-pistachio/include/base/native_types.h @@ -79,13 +79,15 @@ namespace Genode { /** * Thread-context area configuration. */ - static addr_t context_area_virtual_base() { return 0x40000000UL; } - static addr_t context_area_virtual_size() { return 0x10000000UL; } + static constexpr addr_t context_area_virtual_base() { + return 0x40000000UL; } + static constexpr addr_t context_area_virtual_size() { + return 0x10000000UL; } /** * Size of virtual address region holding the context of one thread */ - static addr_t context_virtual_size() { return 0x00100000UL; } + static constexpr addr_t context_virtual_size() { return 0x00100000UL; } }; struct Native_pd_args { }; diff --git a/base/include/base/thread.h b/base/include/base/thread.h index be2ed7ea0..3dd4f3839 100644 --- a/base/include/base/thread.h +++ b/base/include/base/thread.h @@ -39,6 +39,9 @@ * additional context members. Note that this memory is allocated from the RAM * session of the process environment and not accounted for when using the * 'sizeof()' operand on a 'Thread_base' object. + * + * A thread may be associated with more than one stack. Additional secondary + * stacks can be associated with a thread, and used for user level scheduling. */ /* @@ -57,7 +60,7 @@ #include #include #include -#include +#include #include /* for 'Ram_dataspace_capability' type */ #include /* for 'Thread_capability' type */ @@ -80,15 +83,6 @@ namespace Genode { class Stack_too_large : public Exception { }; class Stack_alloc_failed : public Exception { }; - private: - - /** - * List-element helper to enable inserting threads in a list - */ - List_element _list_element; - - public: - /** * Thread context located within the thread-context area * @@ -169,8 +163,12 @@ namespace Genode { { private: - List > _threads; - Lock _threads_lock; + static constexpr size_t MAX_THREADS = + Native_config::context_area_virtual_size() / + Native_config::context_virtual_size(); + + Bit_allocator _alloc; + Lock _threads_lock; /** * Detect if a context already exists at the specified address @@ -191,7 +189,7 @@ namespace Genode { /** * Release thread context */ - void free(Thread_base *thread); + void free(Context *thread); /** * Return 'Context' object for a given base address @@ -202,6 +200,16 @@ namespace Genode { * Return base address of context containing the specified address */ static addr_t addr_to_base(void *addr); + + /** + * Return index in context area for a given base address + */ + static size_t base_to_idx(addr_t base); + + /** + * Return base address of context given index in context area + */ + static addr_t idx_to_base(size_t idx); }; /** @@ -217,7 +225,7 @@ namespace Genode { /** * Detach and release thread context of the thread */ - void _free_context(); + void _free_context(Context *context); /** * Platform-specific thread-startup code @@ -258,7 +266,7 @@ namespace Genode { Genode::Pager_capability _pager_cap; /** - * Pointer to corresponding thread context + * Pointer to primary thread context */ Context *_context; @@ -326,6 +334,28 @@ namespace Genode { */ void name(char *dst, size_t dst_len); + /** + * Add an additional stack to the thread + * + * \throw Stack_too_large + * \throw Stack_alloc_failed + * \throw Context_alloc_failed + * + * The stack for the new thread will be allocated from the RAM + * session of the process environment. A small portion of the + * stack size is internally used by the framework for storing + * thread-context information such as the thread's name (see + * 'struct Context'). + * + * \return pointer to the new stack's top + */ + void* alloc_secondary_stack(char const *name, size_t stack_size); + + /** + * Remove a secondary stack from the thread + */ + void free_secondary_stack(void* stack_addr); + /** * Request capability of thread */ diff --git a/base/src/base/thread/thread.cc b/base/src/base/thread/thread.cc index 48388b23c..868b339d2 100644 --- a/base/src/base/thread/thread.cc +++ b/base/src/base/thread/thread.cc @@ -49,14 +49,17 @@ addr_t Thread_base::Context_allocator::addr_to_base(void *addr) } -bool Thread_base::Context_allocator::_is_in_use(addr_t base) +size_t Thread_base::Context_allocator::base_to_idx(addr_t base) { - List_element *le = _threads.first(); - for (; le; le = le->next()) - if (base_to_context(base) == le->object()->_context) - return true; + return (base - Native_config::context_area_virtual_base()) / + Native_config::context_virtual_size(); +} - return false; + +addr_t Thread_base::Context_allocator::idx_to_base(size_t idx) +{ + return Native_config::context_area_virtual_base() + + idx * Native_config::context_virtual_size(); } @@ -64,29 +67,19 @@ Thread_base::Context *Thread_base::Context_allocator::alloc(Thread_base *thread_ { Lock::Guard _lock_guard(_threads_lock); - /* - * Find slot in context area for the new context - */ - addr_t base = Native_config::context_area_virtual_base(); - for (; _is_in_use(base); base += Native_config::context_virtual_size()) { - - /* check upper bound of context area */ - if (base >= Native_config::context_area_virtual_base() + - Native_config::context_area_virtual_size()) - return 0; + try { + return base_to_context(idx_to_base(_alloc.alloc())); + } catch(Bit_allocator::Out_of_indices) { + return 0; } - - _threads.insert(&thread_base->_list_element); - - return base_to_context(base); } -void Thread_base::Context_allocator::free(Thread_base *thread_base) +void Thread_base::Context_allocator::free(Context *context) { Lock::Guard _lock_guard(_threads_lock); - _threads.remove(&thread_base->_list_element); + _alloc.free(base_to_idx(addr_to_base(context))); } @@ -159,23 +152,24 @@ Thread_base::Context *Thread_base::_alloc_context(size_t stack_size) context->thread_base = this; context->stack_base = ds_addr; context->ds_cap = ds_cap; + return context; } -void Thread_base::_free_context() +void Thread_base::_free_context(Context* context) { - addr_t ds_addr = _context->stack_base - Native_config::context_area_virtual_base(); - Ram_dataspace_capability ds_cap = _context->ds_cap; + addr_t ds_addr = context->stack_base - Native_config::context_area_virtual_base(); + Ram_dataspace_capability ds_cap = context->ds_cap; /* call de-constructor explicitly before memory gets detached */ - _context->~Context(); + context->~Context(); Genode::env_context_area_rm_session()->detach((void *)ds_addr); Genode::env_context_area_ram_session()->free(ds_cap); /* context area ready for reuse */ - _context_allocator()->free(this); + _context_allocator()->free(context); } @@ -211,9 +205,23 @@ void Thread_base::join() } +void* Thread_base::alloc_secondary_stack(char const *name, size_t stack_size) +{ + Context *context = _alloc_context(stack_size); + strncpy(context->name, name, sizeof(context->name)); + return (void *)context->stack_top(); +} + + +void Thread_base::free_secondary_stack(void* stack_addr) +{ + addr_t base = Context_allocator::addr_to_base(stack_addr); + _free_context(Context_allocator::base_to_context(base)); +} + + Thread_base::Thread_base(const char *name, size_t stack_size) : - _list_element(this), _context(_alloc_context(stack_size)), _join_lock(Lock::LOCKED) { @@ -225,5 +233,5 @@ Thread_base::Thread_base(const char *name, size_t stack_size) Thread_base::~Thread_base() { _deinit_platform_thread(); - _free_context(); + _free_context(_context); } diff --git a/dde_linux/src/lib/usb/include/routine.h b/dde_linux/src/lib/usb/include/routine.h index 994783879..bd566d67d 100644 --- a/dde_linux/src/lib/usb/include/routine.h +++ b/dde_linux/src/lib/usb/include/routine.h @@ -64,15 +64,16 @@ class Routine : public Genode::List::Element /* will never return */ if (!_started) { _started = true; - _stack = (char *)dde_kit_simple_malloc(STACK_SIZE); + Genode::Thread_base *th = Genode::Thread_base::myself(); + _stack = (char *) th->alloc_secondary_stack(_name, STACK_SIZE); if (verbose) - PDBG("Start func %s (%p) sp: %p", _name, _func, (_stack + STACK_SIZE)); + PDBG("Start func %s (%p) sp: %p", _name, _func, _stack); /* XXX move to platform code */ /* switch stack and call '_func(_arg)' */ - platform_execute((void *)(_stack + STACK_SIZE), (void *)_func, _arg); + platform_execute((void *)(_stack), (void *)_func, _arg); } /* restore old state */ @@ -122,7 +123,7 @@ class Routine : public Genode::List::Element ~Routine() { if (_stack) - dde_kit_simple_free(_stack); + Genode::Thread_base::myself()->free_secondary_stack(_stack); } /**