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);
}
/**