192 lines
4.3 KiB
C++
Executable File
192 lines
4.3 KiB
C++
Executable File
/*
|
|
* \brief Thread facility
|
|
* \author Norman Feske
|
|
* \author Martin Stein
|
|
* \date 2009-10-02
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2009-2013 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.
|
|
*/
|
|
|
|
#include <base/printf.h>
|
|
#include <base/ipc_pager.h>
|
|
#include <platform_thread.h>
|
|
#include <platform_pd.h>
|
|
#include <kernel/syscalls.h>
|
|
#include "include/platform.h"
|
|
#include <cpu_session/cpu_session.h>
|
|
|
|
static bool const verbose = 0;
|
|
|
|
using namespace Genode;
|
|
|
|
|
|
Tid_allocator* Genode::tid_allocator()
|
|
{
|
|
static Tid_allocator _tida(User::MIN_THREAD_ID+1, User::MAX_THREAD_ID);
|
|
return &_tida;
|
|
}
|
|
|
|
|
|
Pid_allocator* Genode::pid_allocator()
|
|
{
|
|
static Pid_allocator _pida(User::MIN_PROTECTION_ID, User::MAX_PROTECTION_ID);
|
|
return &_pida;
|
|
}
|
|
|
|
|
|
namespace Genode
|
|
{
|
|
static Kernel::Utcb * phys_utcb[User::MAX_THREAD_ID];
|
|
}
|
|
|
|
|
|
int Genode::physical_utcb(Native_thread_id const &tid, Kernel::Utcb * const &utcb)
|
|
{
|
|
if (tid < sizeof(phys_utcb)/sizeof(phys_utcb[0])) {
|
|
Genode::phys_utcb[tid] = utcb;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
Kernel::Utcb* Genode::physical_utcb(Native_thread_id tid)
|
|
{
|
|
|
|
if (tid >= sizeof(phys_utcb)/sizeof(phys_utcb[0])) {
|
|
PERR("Native thread ID out of range");
|
|
return 0;
|
|
}
|
|
|
|
if(!phys_utcb[tid]) {
|
|
if (platform_specific()->
|
|
core_mem_alloc()->
|
|
alloc_aligned(sizeof(Kernel::Utcb),
|
|
(void**)&phys_utcb[tid],
|
|
Kernel::Utcb::ALIGNMENT_LOG2).is_error())
|
|
{
|
|
PERR("Allocate memory for a new UTCB failed");
|
|
return 0;
|
|
}
|
|
if(verbose) {
|
|
PDBG("UTCB %i: [%p|%p]", tid, phys_utcb[tid],
|
|
(void*)((addr_t)phys_utcb[tid] + sizeof(Kernel::Utcb)));
|
|
}
|
|
}
|
|
return phys_utcb[tid];
|
|
}
|
|
|
|
|
|
void Platform_thread::affinity(unsigned int cpu_no) { PERR("not implemented"); }
|
|
|
|
|
|
void Platform_thread::cancel_blocking() { PERR("not implemented"); }
|
|
|
|
|
|
void Platform_thread::state(Thread_state s)
|
|
{
|
|
PDBG("Not implemented");
|
|
throw Cpu_session::State_access_failed();
|
|
}
|
|
|
|
|
|
Thread_state Platform_thread::state()
|
|
{
|
|
PDBG("Not implemented");
|
|
throw Cpu_session::State_access_failed();
|
|
}
|
|
|
|
|
|
int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no)
|
|
{
|
|
Native_thread_id pager_tid = _pager ? _pager->cap().dst() : 0;
|
|
Kernel::Utcb* putcb = physical_utcb(_tid);
|
|
|
|
/* Hand over arguments for the thread's bootstrap */
|
|
*((Native_thread_id*)&putcb->byte[0]) = _tid;
|
|
if (verbose) {
|
|
PDBG("Start Thread, tid=%i, pid=%i, pager=%i", _tid, _pid, pager_tid);
|
|
PDBG("vip=0x%p, vsp=%p, vutcb=0x%p", ip, sp, _utcb);
|
|
}
|
|
int const error = Kernel::thread_create(_tid, _pid, pager_tid,
|
|
putcb, (addr_t)ip, (addr_t)sp, 0);
|
|
if (error) {
|
|
PERR("Kernel::thread_create failed, error=%di", error);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
void Platform_thread::pause()
|
|
{
|
|
PDBG("not implemented");
|
|
}
|
|
|
|
|
|
void Platform_thread::resume()
|
|
{
|
|
PDBG("not implemented");
|
|
}
|
|
|
|
|
|
Platform_thread::Platform_thread(const char *name, unsigned, int thread_id,
|
|
uint32_t params)
|
|
: _tid(0), _utcb(0), _params(params)
|
|
{
|
|
if (!_tid) {
|
|
if (!(_tid = tid_allocator()->allocate(this))) {
|
|
PERR("TID allocation failed");
|
|
return;
|
|
}
|
|
}
|
|
else if (!tid_allocator()->allocate(this, (Native_thread_id)thread_id)) {
|
|
PERR("TID allocation failed");
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
Platform_thread::~Platform_thread() {
|
|
_pd->unbind_thread(this);
|
|
if(Kernel::thread_kill(_tid)){
|
|
PERR("Kernel::thread_kill(%i) failed", (unsigned)_tid);
|
|
}
|
|
tid_allocator()->free(_tid);
|
|
}
|
|
|
|
|
|
bool Ipc_pager::resolved()
|
|
{
|
|
typedef Platform_pd::Context_part Context_part;
|
|
typedef Mapping::Physical_page Physical_page;
|
|
|
|
addr_t va = (addr_t)_request.virtual_page.address();
|
|
Native_thread_id context_owner = 0;
|
|
Context_part context_part = Platform_pd::NO_CONTEXT_PART;
|
|
unsigned stack_offset = 0;
|
|
|
|
Platform_pd* pd =
|
|
pid_allocator()->holder(_request.virtual_page.protection_id());
|
|
|
|
if (!pd) { return false; }
|
|
if (!pd->metadata_if_context_address(va, &context_owner, &context_part,
|
|
&stack_offset))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (context_part != Platform_pd::UTCB_AREA) { return false; }
|
|
|
|
Native_utcb * const putcb = physical_utcb(context_owner);
|
|
set_reply_mapping(Genode::Mapping(va, (addr_t)putcb, false,
|
|
Native_utcb::size_log2(), true));
|
|
|
|
return true;
|
|
}
|