genode/repos/base-hw/src/lib/base/thread_start.cc
Martin Stein fbe9d26c47 trace: initialize trace control in Thread::start
Previously, the trace control of a thread was initialized in its
constructor (which is generic for all components). This has the
disadvantage that the CPU-session-pointer member of the thread might not
be valid at this point. And it cannot be replaced by using the
"deprecated_env" CPU session neither as constructing the deprecated
environment in causes troubles in Core. But as the trace control
shouldn't be needed in Core anyway, the initialization can be moved to
the Thread::start implementation of non-core components. This code
already takes care of the CPU session pointer.

Fixes #2901
2018-08-02 14:36:35 +02:00

108 lines
2.9 KiB
C++

/**
* \brief Implementations for the start of a thread
* \author Martin Stein
* \author Stefan Kalkowski
* \date 2012-02-12
*/
/*
* Copyright (C) 2012-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 <base/thread.h>
#include <base/log.h>
#include <base/sleep.h>
#include <base/env.h>
#include <cpu_thread/client.h>
/* base-internal includes */
#include <base/internal/stack_allocator.h>
#include <base/internal/native_utcb.h>
#include <base/internal/globals.h>
using namespace Genode;
namespace Hw {
extern Ram_dataspace_capability _main_thread_utcb_ds;
extern Untyped_capability _main_thread_cap;
}
/************
** Thread **
************/
void Thread::_init_platform_thread(size_t weight, Type type)
{
_init_cpu_session_and_trace_control();
if (type == NORMAL) {
/* create server object */
addr_t const utcb = (addr_t)&_stack->utcb();
_thread_cap = _cpu_session->create_thread(env_deprecated()->pd_session_cap(),
name(), _affinity,
Weight(weight), utcb);
return;
}
/* if we got reinitialized we have to get rid of the old UTCB */
size_t const utcb_size = sizeof(Native_utcb);
addr_t const stack_area = stack_area_virtual_base();
addr_t const utcb_new = (addr_t)&_stack->utcb() - stack_area;
Region_map * const rm = env_stack_area_region_map;
if (type == REINITIALIZED_MAIN) { rm->detach(utcb_new); }
/* remap initial main-thread UTCB according to stack-area spec */
try { rm->attach_at(Hw::_main_thread_utcb_ds, utcb_new, utcb_size); }
catch(...) {
error("failed to re-map UTCB");
while (1) ;
}
/* adjust initial object state in case of a main thread */
native_thread().cap = Hw::_main_thread_cap;
_thread_cap = main_thread_cap();
}
void Thread::_deinit_platform_thread()
{
if (!_cpu_session)
_cpu_session = env_deprecated()->cpu_session();
_cpu_session->kill_thread(_thread_cap);
/* detach userland stack */
size_t const size = sizeof(_stack->utcb());
addr_t utcb = Stack_allocator::addr_to_base(_stack) +
stack_virtual_size() - size - stack_area_virtual_base();
env_stack_area_region_map->detach(utcb);
}
void Thread::start()
{
/* attach userland stack */
try {
Dataspace_capability ds = Cpu_thread_client(_thread_cap).utcb();
size_t const size = sizeof(_stack->utcb());
addr_t dst = Stack_allocator::addr_to_base(_stack) +
stack_virtual_size() - size - stack_area_virtual_base();
env_stack_area_region_map->attach_at(ds, dst, size);
} catch (...) {
error("failed to attach userland stack");
sleep_forever();
}
/* start thread with its initial IP and aligned SP */
Cpu_thread_client(_thread_cap).start((addr_t)_thread_start, _stack->top());
}
void Thread::cancel_blocking()
{
Cpu_thread_client(_thread_cap).cancel_blocking();
}