diff --git a/base-hw/src/core/include/util.h b/base-hw/src/core/include/util.h index 2c6b47ee8..5bc5baddf 100644 --- a/base-hw/src/core/include/util.h +++ b/base-hw/src/core/include/util.h @@ -22,6 +22,15 @@ namespace Genode { enum { MIN_PAGE_SIZE_LOG2 = 12 }; + /** + * Identification that core threads use to get access to their metadata + */ + typedef addr_t Core_thread_id; + + /** + * Allows core threads to get their core-thread ID via their stack pointer + */ + enum { CORE_STACK_ALIGNM_LOG2 = 15 }; /** * Get the the minimal supported page-size log 2 diff --git a/base-hw/src/core/kernel/configuration.h b/base-hw/src/core/kernel/configuration.h index 5ede42918..cd0cc4c84 100644 --- a/base-hw/src/core/kernel/configuration.h +++ b/base-hw/src/core/kernel/configuration.h @@ -17,7 +17,7 @@ namespace Kernel { enum { - DEFAULT_STACK_SIZE = 1024 * 1024, + DEFAULT_STACK_SIZE = 16 * 1024, USER_LAP_TIME_MS = 100, MAX_PDS = 256, MAX_THREADS = 256, diff --git a/base-hw/src/core/kernel/kernel.cc b/base-hw/src/core/kernel/kernel.cc index b54cfec8d..67fc25b8e 100644 --- a/base-hw/src/core/kernel/kernel.cc +++ b/base-hw/src/core/kernel/kernel.cc @@ -50,8 +50,9 @@ namespace Kernel Pic * pic() { return unsynchronized_singleton(); } /* import Genode types */ - typedef Genode::umword_t umword_t; - typedef Genode::Core_tlb Core_tlb; + typedef Genode::umword_t umword_t; + typedef Genode::Core_tlb Core_tlb; + typedef Genode::Core_thread_id Core_thread_id; void init_platform(); } @@ -216,12 +217,23 @@ extern "C" void kernel() /* create the core main thread */ { - static Native_utcb utcb; - static char stack[DEFAULT_STACK_SIZE] - __attribute__((aligned(Cpu::DATA_ACCESS_ALIGNM))); - enum { STACK_SIZE = sizeof(stack)/sizeof(stack[0]) + 1 }; + /* get stack memory that fullfills the constraints for core stacks */ + enum { + STACK_ALIGNM = 1 << Genode::CORE_STACK_ALIGNM_LOG2, + STACK_SIZE = DEFAULT_STACK_SIZE, + }; + if (STACK_SIZE > STACK_ALIGNM - sizeof(Core_thread_id)) { + PERR("stack size does not fit stack alignment of core"); + } + static char s[STACK_SIZE] __attribute__((aligned(STACK_ALIGNM))); + + /* provide thread ident at the aligned base of the stack */ + *(Core_thread_id *)s = 0; + + /* start thread with stack pointer at the top of stack */ + void * const sp = (void *)((addr_t)s + STACK_SIZE); void * const ip = (void *)CORE_MAIN; - void * const sp = (void *)&stack[STACK_SIZE - 1]; + static Native_utcb utcb; _main_utcb = &utcb; static Thread t((Platform_thread *)0); t.init(ip, sp, 0, core_id(), &utcb, &utcb, 1, 1); diff --git a/base-hw/src/core/thread.cc b/base-hw/src/core/thread.cc index 46808ffea..d2b6ff4bc 100644 --- a/base-hw/src/core/thread.cc +++ b/base-hw/src/core/thread.cc @@ -37,20 +37,24 @@ Native_utcb * Thread_base::utcb() } -/** - * Returns 0 if this is the main thread or the thread base pointer otherwise - */ Thread_base * Thread_base::myself() { - Platform_thread * const t = Kernel::get_thread(0); - if (t) { return t->thread_base(); } + /* get thread ident from the aligned base of the stack */ + int dummy = 0; + addr_t sp = (addr_t)(&dummy); + enum { SP_MASK = ~((1 << CORE_STACK_ALIGNM_LOG2) - 1) }; + Core_thread_id id = *(Core_thread_id *)((addr_t)sp & SP_MASK); + + /* if the ident is zero this is the main thread */ + Platform_thread * const pt = (Platform_thread *)id; + if (pt) { return pt->thread_base(); } return 0; } void Thread_base::_thread_start() { - /* this is never called by a main thread */ + /* this is never called by the main thread */ Thread_base::myself()->_thread_bootstrap(); Thread_base::myself()->entry(); } @@ -73,12 +77,30 @@ Thread_base::~Thread_base() void Thread_base::start() { - size_t const stack_size = _tid.pt->stack_size()/sizeof(umword_t) + 1; - void * const stack_base = new (platform()->core_mem_alloc()) - umword_t [stack_size]; - void * sp = (void *)((addr_t)stack_base + _tid.pt->stack_size()); + /* allocate stack memory that fullfills the constraints for core stacks */ + size_t const size = _tid.pt->stack_size(); + if (size > (1 << CORE_STACK_ALIGNM_LOG2) - sizeof(Core_thread_id)) { + PERR("stack size does not fit stack alignment of core"); + return; + } + void * base; + Platform * const p = static_cast(platform()); + Range_allocator * const alloc = p->core_mem_alloc(); + if (alloc->alloc_aligned(size, &base, CORE_STACK_ALIGNM_LOG2).is_error()) { + PERR("failed to allocate stack memory"); + return; + } + /* provide thread ident at the aligned base of the stack */ + *(Core_thread_id *)base = (Core_thread_id)_tid.pt; + + /* start thread with stack pointer at the top of stack */ + void * sp = (void *)((addr_t)base + size); void * ip = (void *)&_thread_start; - if (_tid.pt->start(ip, sp)) PERR("Couldn't start thread"); + if (_tid.pt->start(ip, sp)) { + PERR("failed to start thread"); + alloc->free(base, size); + return; + } }