2011-12-22 16:19:25 +01:00
|
|
|
/*
|
|
|
|
* \brief Fiasco thread facility
|
|
|
|
* \author Christian Helmuth
|
|
|
|
* \date 2006-04-11
|
|
|
|
*
|
|
|
|
* This provides a thread object and uses l4_inter_task_ex_regs() for L4 thread
|
|
|
|
* manipulation.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2012-01-03 15:35:05 +01:00
|
|
|
* Copyright (C) 2006-2012 Genode Labs GmbH
|
2011-12-22 16:19:25 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Genode includes */
|
|
|
|
#include <base/printf.h>
|
|
|
|
#include <util/string.h>
|
|
|
|
|
|
|
|
/* core includes */
|
|
|
|
#include <platform_thread.h>
|
|
|
|
|
|
|
|
/* Fiasco includes */
|
|
|
|
namespace Fiasco {
|
|
|
|
#include <l4/sys/types.h>
|
|
|
|
#include <l4/sys/syscalls.h>
|
|
|
|
#include <l4/sys/utcb.h>
|
|
|
|
#include <l4/sys/kdebug.h>
|
|
|
|
}
|
|
|
|
|
|
|
|
using namespace Genode;
|
|
|
|
using namespace Fiasco;
|
|
|
|
|
|
|
|
|
|
|
|
int Platform_thread::start(void *ip, void *sp)
|
|
|
|
{
|
|
|
|
l4_umword_t dummy, old_eflags;
|
|
|
|
l4_threadid_t thread = _l4_thread_id;
|
|
|
|
l4_threadid_t pager = _pager ? _pager->cap().tid() : L4_INVALID_ID;
|
|
|
|
l4_threadid_t preempter = L4_INVALID_ID;
|
|
|
|
l4_threadid_t cap_handler = L4_INVALID_ID;
|
|
|
|
|
|
|
|
l4_inter_task_ex_regs(thread, (l4_umword_t)ip, (l4_umword_t)sp,
|
|
|
|
&preempter, &pager, &cap_handler,
|
|
|
|
&old_eflags, &dummy, &dummy,
|
|
|
|
0, l4_utcb_get());
|
|
|
|
if (old_eflags == ~0UL)
|
|
|
|
PWRN("old eflags == ~0 on ex_regs %x.%x", (int)thread.id.task, (int)thread.id.lthread);
|
|
|
|
|
|
|
|
fiasco_register_thread_name(thread, _name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_thread::pause()
|
|
|
|
{
|
|
|
|
PDBG("not implemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_thread::resume()
|
|
|
|
{
|
|
|
|
PDBG("not implemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_thread::bind(int thread_id, l4_threadid_t l4_thread_id, Platform_pd *pd)
|
|
|
|
{
|
|
|
|
_thread_id = thread_id;
|
|
|
|
_l4_thread_id = l4_thread_id;
|
|
|
|
_platform_pd = pd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_thread::unbind()
|
|
|
|
{
|
|
|
|
l4_umword_t dummy, old_eflags;
|
|
|
|
l4_threadid_t thread = _l4_thread_id;
|
|
|
|
l4_threadid_t pager = thread;
|
|
|
|
l4_threadid_t preempter = L4_INVALID_ID;
|
|
|
|
l4_threadid_t cap_handler = L4_INVALID_ID;
|
|
|
|
|
|
|
|
fiasco_register_thread_name(thread, "<dead>");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Fiasco thread is halted by setting itself as pager and forcing
|
|
|
|
* pagefault at 0, where Genode never maps a page. The bottom line is the
|
|
|
|
* thread blocks in IPC to itself.
|
|
|
|
*/
|
|
|
|
l4_inter_task_ex_regs(thread, 0, 0,
|
|
|
|
&preempter, &pager, &cap_handler,
|
|
|
|
&old_eflags, &dummy, &dummy,
|
|
|
|
0, l4_utcb_get());
|
|
|
|
if (old_eflags == ~0UL)
|
|
|
|
PWRN("old eflags == ~0 on ex_regs %x.%x", (int)thread.id.task, (int)thread.id.lthread);
|
|
|
|
|
|
|
|
_thread_id = THREAD_INVALID;
|
|
|
|
_l4_thread_id = L4_INVALID_ID;
|
|
|
|
_platform_pd = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Platform_thread::state(Thread_state *state_dst)
|
|
|
|
{
|
|
|
|
l4_umword_t old_eflags, ip, sp;
|
|
|
|
l4_threadid_t thread = _l4_thread_id;
|
|
|
|
l4_threadid_t pager = L4_INVALID_ID;
|
|
|
|
l4_threadid_t preempter = L4_INVALID_ID;
|
|
|
|
l4_threadid_t cap_handler = L4_INVALID_ID;
|
|
|
|
|
|
|
|
l4_inter_task_ex_regs(thread, ~0UL, ~0UL,
|
|
|
|
&preempter, &pager, &cap_handler,
|
|
|
|
&old_eflags, &ip, &sp,
|
|
|
|
L4_THREAD_EX_REGS_NO_CANCEL, l4_utcb_get());
|
|
|
|
if (old_eflags == ~0UL)
|
|
|
|
PWRN("old eflags == ~0 on ex_regs %x.%x", (int)thread.id.task, (int)thread.id.lthread);
|
|
|
|
|
|
|
|
/* fill thread state structure */
|
|
|
|
state_dst->ip = ip;
|
|
|
|
state_dst->sp = sp;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Platform_thread::cancel_blocking()
|
|
|
|
{
|
|
|
|
l4_umword_t dummy;
|
|
|
|
l4_threadid_t invalid = L4_INVALID_ID;
|
|
|
|
|
|
|
|
l4_inter_task_ex_regs(_l4_thread_id, ~0UL, ~0UL,
|
|
|
|
&invalid, &invalid, &invalid,
|
|
|
|
&dummy, &dummy, &dummy, 0, l4_utcb_get());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Platform_thread::Platform_thread(const char *name, unsigned, int thread_id)
|
|
|
|
: _thread_id(thread_id), _l4_thread_id(L4_INVALID_ID), _pager(0)
|
|
|
|
{
|
|
|
|
strncpy(_name, name, sizeof(_name));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Platform_thread::~Platform_thread()
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* We inform our protection domain about thread destruction, which will end up in
|
|
|
|
* Thread::unbind()
|
|
|
|
*/
|
|
|
|
if (_platform_pd)
|
|
|
|
_platform_pd->unbind_thread(this);
|
|
|
|
}
|