/* * \brief Setup the thread environment of a programs first thread * \author Christian Helmuth * \author Christian Prochaska * \author Martin Stein * \date 2013-12-04 */ /* * Copyright (C) 2013-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ /* Genode includes */ #include #include #include #include /* base-internal includes */ #include using namespace Genode; addr_t init_main_thread_result; extern void init_exception_handling(); namespace Genode { extern Region_map * env_stack_area_region_map; } void prepare_init_main_thread(); enum { MAIN_THREAD_STACK_SIZE = 1024*sizeof(Genode::addr_t) }; /** * Satisfy crt0.s in static programs, LDSO overrides this symbol */ extern "C" void init_rtld() __attribute__((weak)); void init_rtld() { } /** * Lower bound of the stack, solely used for sanity checking */ extern unsigned char __initial_stack_base[]; /** * The first thread in a program */ class Main_thread : public Thread_deprecated { public: /** * Constructor * * \param reinit wether this is called for reinitialization */ Main_thread(bool reinit) : Thread_deprecated("main", reinit ? REINITIALIZED_MAIN : MAIN) { } /********************** ** Thread interface ** **********************/ void entry() override { } }; Main_thread * main_thread() { static Main_thread s(false); return &s; } /** * Create a thread object for the main thread * * \return stack pointer of the new environment via init_main_thread_result * * This function must be called only once per program and before the _main * function. It can be called as soon as a temporary environment provides * some stack space and inter-process communication. At this stage, global * static objects are not registered for implicit destruction at program exit. */ extern "C" void init_main_thread() { /* do platform specific preparation */ prepare_init_main_thread(); /* * Explicitly setup program environment at this point to ensure that its * destructor won't be registered for the atexit routine. */ (void*)env_deprecated(); init_log(*env_deprecated()->parent()); init_exit(*env_deprecated()->parent()); /* create a thread object for the main thread */ main_thread(); /** * The new stack pointer enables the caller to switch from its current * environment to the those that the thread object provides. */ addr_t const sp = reinterpret_cast(main_thread()->stack_top()); init_main_thread_result = sp; /* * Sanity check for the usage of the initial stack * * Because the initial stack is located in the BSS, it is zero-initialized. * We check that the stack still contains zeros at its lower boundary after * executing all the initialization code. */ enum { STACK_PAD = 256U }; for (unsigned i = 0; i < STACK_PAD; i++) { if (__initial_stack_base[i] == 0) continue; error("initial stack overflow detected"); for (;;); } } /** * Reinitialize main-thread object according to a reinitialized environment */ void reinit_main_thread() { construct_at(main_thread(), true); }