mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-23 15:32:25 +00:00
parent
d6f89b285d
commit
a891b3832c
@ -112,7 +112,7 @@ namespace Libc {
|
||||
/**
|
||||
* Pthread/semaphore support
|
||||
*/
|
||||
void init_pthread_support(Suspend &, Resume &, Timer_accessor &);
|
||||
void init_pthread_support(Monitor &, Timer_accessor &);
|
||||
void init_pthread_support(Genode::Cpu_session &, Xml_node);
|
||||
void init_semaphore_support(Timer_accessor &);
|
||||
|
||||
|
@ -165,17 +165,7 @@ struct Libc::Pthread : Noncopyable, Thread::Tls::Base
|
||||
|
||||
bool _exiting = false;
|
||||
|
||||
/*
|
||||
* The join blockade is needed because 'Libc::resume_all()' uses a
|
||||
* 'Signal_transmitter' which holds a reference to a signal context
|
||||
* capability, which needs to be released before the thread can be
|
||||
* destroyed.
|
||||
*
|
||||
* Also, we cannot use 'Thread::join()', because it only
|
||||
* returns when the thread entry function returns, which does not
|
||||
* happen with 'pthread_cancel()'.
|
||||
*/
|
||||
Genode::Blockade _join_blockade;
|
||||
Genode::Mutex _mutex { };
|
||||
|
||||
/* return value for 'pthread_join()' */
|
||||
void *_retval = PTHREAD_CANCELED;
|
||||
@ -189,10 +179,12 @@ struct Libc::Pthread : Noncopyable, Thread::Tls::Base
|
||||
class Cleanup_handler : public List<Cleanup_handler>::Element
|
||||
{
|
||||
private:
|
||||
|
||||
void (*_routine)(void*);
|
||||
void *_arg;
|
||||
|
||||
public:
|
||||
|
||||
Cleanup_handler(void (*routine)(void*), void *arg)
|
||||
: _routine(routine), _arg(arg) { }
|
||||
|
||||
|
@ -453,7 +453,7 @@ Libc::Kernel::Kernel(Genode::Env &env, Genode::Allocator &heap)
|
||||
atexit(close_file_descriptors_on_exit);
|
||||
|
||||
init_semaphore_support(_timer_accessor);
|
||||
init_pthread_support(*this, *this, _timer_accessor);
|
||||
init_pthread_support(*this, _timer_accessor);
|
||||
init_pthread_support(env.cpu(), _pthread_config());
|
||||
|
||||
_env.ep().register_io_progress_handler(*this);
|
||||
|
@ -32,8 +32,7 @@
|
||||
#include <internal/init.h>
|
||||
#include <internal/kernel.h>
|
||||
#include <internal/pthread.h>
|
||||
#include <internal/resume.h>
|
||||
#include <internal/suspend.h>
|
||||
#include <internal/monitor.h>
|
||||
#include <internal/time.h>
|
||||
#include <internal/timer.h>
|
||||
|
||||
@ -42,21 +41,28 @@ using namespace Libc;
|
||||
|
||||
|
||||
static Thread *_main_thread_ptr;
|
||||
static Resume *_resume_ptr;
|
||||
static Suspend *_suspend_ptr;
|
||||
static Monitor *_monitor_ptr;
|
||||
static Timer_accessor *_timer_accessor_ptr;
|
||||
|
||||
|
||||
void Libc::init_pthread_support(Suspend &suspend, Resume &resume,
|
||||
Timer_accessor &timer_accessor)
|
||||
void Libc::init_pthread_support(Monitor &monitor, Timer_accessor &timer_accessor)
|
||||
{
|
||||
_main_thread_ptr = Thread::myself();
|
||||
_suspend_ptr = &suspend;
|
||||
_resume_ptr = &resume;
|
||||
_monitor_ptr = &monitor;
|
||||
_timer_accessor_ptr = &timer_accessor;
|
||||
}
|
||||
|
||||
|
||||
static Libc::Monitor & monitor()
|
||||
{
|
||||
struct Missing_call_of_init_pthread_support : Genode::Exception { };
|
||||
if (!_monitor_ptr)
|
||||
throw Missing_call_of_init_pthread_support();
|
||||
return *_monitor_ptr;
|
||||
}
|
||||
|
||||
namespace { using Fn = Libc::Monitor::Function_result; }
|
||||
|
||||
/*************
|
||||
** Pthread **
|
||||
*************/
|
||||
@ -74,47 +80,26 @@ void Libc::Pthread::Thread_object::entry()
|
||||
|
||||
void Libc::Pthread::join(void **retval)
|
||||
{
|
||||
struct Check : Suspend_functor
|
||||
{
|
||||
bool retry { false };
|
||||
Genode::Mutex::Guard guard(_mutex);
|
||||
|
||||
Pthread &_thread;
|
||||
monitor().monitor(_mutex, [&] {
|
||||
if (!_exiting)
|
||||
return Fn::INCOMPLETE;
|
||||
|
||||
Check(Pthread &thread) : _thread(thread) { }
|
||||
|
||||
bool suspend() override
|
||||
{
|
||||
retry = !_thread._exiting;
|
||||
return retry;
|
||||
}
|
||||
} check(*this);
|
||||
|
||||
struct Missing_call_of_init_pthread_support : Exception { };
|
||||
if (!_suspend_ptr)
|
||||
throw Missing_call_of_init_pthread_support();
|
||||
|
||||
do {
|
||||
_suspend_ptr->suspend(check);
|
||||
} while (check.retry);
|
||||
|
||||
_join_blockade.block();
|
||||
|
||||
if (retval)
|
||||
*retval = _retval;
|
||||
if (retval)
|
||||
*retval = _retval;
|
||||
return Fn::COMPLETE;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
void Libc::Pthread::cancel()
|
||||
{
|
||||
Genode::Mutex::Guard guard(_mutex);
|
||||
|
||||
_exiting = true;
|
||||
|
||||
struct Missing_call_of_init_pthread_support : Exception { };
|
||||
if (!_resume_ptr)
|
||||
throw Missing_call_of_init_pthread_support();
|
||||
|
||||
_resume_ptr->resume_all();
|
||||
|
||||
_join_blockade.wakeup();
|
||||
monitor().trigger_monitor_examination();
|
||||
}
|
||||
|
||||
|
||||
@ -278,7 +263,7 @@ class pthread_mutex : Genode::Noncopyable
|
||||
/**
|
||||
* Enqueue current context as applicant for mutex
|
||||
*
|
||||
* Return true if mutex was aquired, false on timeout expiration.
|
||||
* Return true if mutex was acquired, false on timeout expiration.
|
||||
*/
|
||||
bool _apply_for_mutex(pthread_t thread, Libc::uint64_t timeout_ms)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user