Rework the internal lock interface

With this patch, the 'futex' syscall gets used for blocking and unblocking
of threads in the Linux-specific lock implementation.

The 'Native_thread_id' type, which was previously used in the
lock-internal 'Applicant' class to identify a thread to be woken up,
was not suitable anymore for implementing this change. With this patch,
the 'Thread_base*' type gets used instead, which also has the positive
effect of making the public 'cancelable_lock.h' header file
platform-independent.

Fixes #646.
This commit is contained in:
Christian Prochaska
2013-02-25 21:18:26 +01:00
committed by Norman Feske
parent 7fef0ba931
commit a99193ad90
36 changed files with 496 additions and 330 deletions

View File

@ -150,11 +150,11 @@ void Ipc_pager::reply_and_wait_for_fault()
int ret = l4_map((void *)_reply_mapping.from_phys(),
(void *)_reply_mapping.to_virt(),
_reply_mapping.num_pages(), flags, _last.tid);
_reply_mapping.num_pages(), flags, _last);
/* wake up faulter if mapping succeeded */
if (ret < 0)
PERR("l4_map returned %d, putting thread %d to sleep", ret, _last.tid);
PERR("l4_map returned %d, putting thread %d to sleep", ret, _last);
else
acknowledge_wakeup();
@ -166,7 +166,7 @@ void Ipc_pager::reply_and_wait_for_fault()
void Ipc_pager::acknowledge_wakeup()
{
enum { SUCCESS = 0 };
l4_set_sender(_last.tid);
l4_set_sender(_last);
l4_ipc_return(SUCCESS);
}

View File

@ -22,7 +22,8 @@
#include <codezero/syscalls.h>
static Codezero::l4_mutex main_running_lock = { -1 };
extern Genode::Native_thread_id main_thread_tid;
extern Codezero::l4_mutex main_thread_running_lock;
static inline void thread_yield()
@ -31,58 +32,30 @@ static inline void thread_yield()
}
static inline bool thread_id_valid(Genode::Native_thread_id tid)
static inline bool thread_check_stopped_and_restart(Genode::Thread_base *thread_base)
{
return tid.tid != Codezero::NILTHREAD;
}
static inline bool thread_check_stopped_and_restart(Genode::Native_thread_id tid)
{
if (!thread_id_valid(tid))
return false;
Codezero::l4_mutex_unlock(tid.running_lock);
Codezero::l4_mutex *running_lock = thread_base ?
thread_base->utcb()->running_lock() :
&main_thread_running_lock;
Codezero::l4_mutex_unlock(running_lock);
return true;
}
static inline Genode::Native_thread_id thread_get_my_native_id()
static inline void thread_switch_to(Genode::Thread_base *thread_base)
{
using namespace Genode;
Codezero::l4_mutex *running_lock = 0;
/* obtain pointer to running lock of calling thread */
if (Thread_base::myself())
running_lock = Thread_base::myself()->utcb()->running_lock();
else {
running_lock = &main_running_lock;
if (running_lock->lock == -1) {
Codezero::l4_mutex_init(running_lock);
Codezero::l4_mutex_lock(running_lock); /* block on first mutex lock */
}
}
return Genode::Native_thread_id(Codezero::thread_myself(), running_lock);
}
static inline Genode::Native_thread_id thread_invalid_id()
{
return Genode::Native_thread_id(Codezero::NILTHREAD, 0);
}
static inline void thread_switch_to(Genode::Native_thread_id tid)
{
if (thread_id_valid(tid))
Codezero::l4_thread_switch(tid.tid);
Genode::Native_thread_id tid = thread_base ?
thread_base->tid().l4id :
main_thread_tid;
Codezero::l4_thread_switch(tid);
}
static inline void thread_stop_myself()
{
Genode::Native_thread_id myself = thread_get_my_native_id();
Codezero::l4_mutex_lock(myself.running_lock);
Genode::Thread_base *myself = Genode::Thread_base::myself();
Codezero::l4_mutex *running_lock = myself ?
myself->utcb()->running_lock() :
&main_thread_running_lock;
Codezero::l4_mutex_lock(running_lock);
}

View File

@ -0,0 +1,25 @@
/*
* \brief Thread bootstrap code
* \author Christian Prochaska
* \date 2013-02-15
*/
/*
* Copyright (C) 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.
*/
/* Genode includes */
#include <base/thread.h>
/* Codezero includes */
#include <codezero/syscalls.h>
void Genode::Thread_base::_thread_bootstrap()
{
Codezero::l4_mutex_init(utcb()->running_lock());
Codezero::l4_mutex_lock(utcb()->running_lock()); /* block on first mutex lock */
}

View File

@ -39,11 +39,7 @@ void Thread_base::_thread_start()
** Thread base **
*****************/
void Thread_base::_init_platform_thread()
{
Codezero::l4_mutex_init(utcb()->running_lock());
Codezero::l4_mutex_lock(utcb()->running_lock()); /* block on first mutex lock */
}
void Thread_base::_init_platform_thread() { }
void Thread_base::_deinit_platform_thread()

View File

@ -42,7 +42,7 @@ int Platform_thread::start(void *ip, void *sp, unsigned int cpu_no)
memset(&exregs, 0, sizeof(exregs));
exregs_set_stack(&exregs, (unsigned long)sp);
exregs_set_pc (&exregs, (unsigned long)ip);
exregs_set_pager(&exregs, pager.tid);
exregs_set_pager(&exregs, pager);
exregs_set_utcb (&exregs, _utcb);
int ret = l4_exchange_registers(&exregs, _tid);

View File

@ -105,12 +105,14 @@ void Thread_base::start()
_tid.pt = new(platform()->core_mem_alloc()) Platform_thread(_context->name);
_tid.l4id = create_thread(1, &_context->stack[-4], (void *)&_thread_start);
if (_tid.l4id.tid < 0)
PERR("create_thread returned %d", _tid.l4id.tid);
if (_tid.l4id < 0)
PERR("create_thread returned %d", _tid.l4id);
if (verbose_thread_start)
printf("core started local thread \"%s\" with ID %d\n",
_context->name, _tid.l4id.tid);
_context->name, _tid.l4id);
}

View File

@ -59,9 +59,19 @@ extern "C" int printf(const char *format, ...)
** Startup-code helpers **
**************************/
Genode::Native_thread_id main_thread_tid;
Codezero::l4_mutex main_thread_running_lock;
static void main_thread_bootstrap()
{
Codezero::__l4_init();
main_thread_tid = Codezero::thread_myself();
Codezero::l4_mutex_init(&main_thread_running_lock);
Codezero::l4_mutex_lock(&main_thread_running_lock); /* block on first mutex lock */
}
#endif /* _PLATFORM___MAIN_HELPER_H_ */