648bcd1505
This patch unifies the patterns of using the 'Genode' and 'Libc' namespaces. Types defined in the 'internal/' headers reside in the 'Libc' namespace. The code in the headers does not need to use the 'Libc::' prefix. Compilation units import the 'Libc' namespace after the definition of local types. Local types reside in the 'Libc' namespace (and should eventually move to an 'internal/' header). Since the 'Libc' namespace imports the 'Genode' namespace, there is no need to use the 'Genode::' prefix. Consequently, code in the compilation units rarely need to qualify the 'Genode' or 'Libc' namespaces. There are a few cases where the 'Libc', the 'Genode', and the global (libc) namespaces are ambigious. In these cases, an explicit clarification is needed: - 'Genode::Allocator' differs from 'Libc::Allocator'. - 'Genode::Env' differs from 'Libc::Env'. - Genode's string functions (strcmp, memcpy, strcpy) conflict with the names of the (global) libc functions. - There exist both 'Genode::uint64_t' and the libc'c 'uint64_t'. Issue #3497
108 lines
2.1 KiB
C++
108 lines
2.1 KiB
C++
/*
|
|
* \brief Pthread handling
|
|
* \author Christian Prochaska
|
|
* \author Christian Helmuth
|
|
* \date 2016-12-13
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2019 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.
|
|
*/
|
|
|
|
#ifndef _LIBC__INTERNAL__PTHREAD_POOL_H_
|
|
#define _LIBC__INTERNAL__PTHREAD_POOL_H_
|
|
|
|
/* libc-internal includes */
|
|
#include <internal/legacy.h>
|
|
#include <internal/suspend.h>
|
|
|
|
namespace Libc { class Pthread_pool; }
|
|
|
|
|
|
struct Libc::Pthread_pool
|
|
{
|
|
struct Pthread : Timeout_handler
|
|
{
|
|
Lock lock { Lock::LOCKED };
|
|
Pthread *next { nullptr };
|
|
|
|
Timer_accessor &_timer_accessor;
|
|
Constructible<Timeout> _timeout;
|
|
|
|
void _construct_timeout_once()
|
|
{
|
|
if (!_timeout.constructed())
|
|
_timeout.construct(_timer_accessor, *this);
|
|
}
|
|
|
|
Pthread(Timer_accessor &timer_accessor, uint64_t timeout_ms)
|
|
: _timer_accessor(timer_accessor)
|
|
{
|
|
if (timeout_ms > 0) {
|
|
_construct_timeout_once();
|
|
_timeout->start(timeout_ms);
|
|
}
|
|
}
|
|
|
|
uint64_t duration_left()
|
|
{
|
|
_construct_timeout_once();
|
|
return _timeout->duration_left();
|
|
}
|
|
|
|
void handle_timeout() override
|
|
{
|
|
lock.unlock();
|
|
}
|
|
};
|
|
|
|
Lock mutex;
|
|
Pthread *pthreads = nullptr;
|
|
Timer_accessor &timer_accessor;
|
|
|
|
|
|
Pthread_pool(Timer_accessor &timer_accessor)
|
|
: timer_accessor(timer_accessor) { }
|
|
|
|
void resume_all()
|
|
{
|
|
Lock::Guard g(mutex);
|
|
|
|
for (Pthread *p = pthreads; p; p = p->next)
|
|
p->lock.unlock();
|
|
}
|
|
|
|
uint64_t suspend_myself(Suspend_functor & check, uint64_t timeout_ms)
|
|
{
|
|
Pthread myself { timer_accessor, timeout_ms };
|
|
{
|
|
Lock::Guard g(mutex);
|
|
|
|
myself.next = pthreads;
|
|
pthreads = &myself;
|
|
}
|
|
|
|
if (check.suspend())
|
|
myself.lock.lock();
|
|
|
|
{
|
|
Lock::Guard g(mutex);
|
|
|
|
/* address of pointer to next pthread allows to change the head */
|
|
for (Pthread **next = &pthreads; *next; next = &(*next)->next) {
|
|
if (*next == &myself) {
|
|
*next = myself.next;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return timeout_ms > 0 ? myself.duration_left() : 0;
|
|
}
|
|
};
|
|
|
|
#endif /* _LIBC__INTERNAL__PTHREAD_POOL_H_ */
|