/* * \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 #include namespace Libc { class Pthread_pool; } struct Libc::Pthread_pool { struct Pthread : Timeout_handler { Genode::Lock lock { Genode::Lock::LOCKED }; Pthread *next { nullptr }; Timer_accessor &_timer_accessor; Constructible _timeout; void _construct_timeout_once() { if (!_timeout.constructed()) _timeout.construct(_timer_accessor, *this); } Pthread(Timer_accessor &timer_accessor, Genode::uint64_t timeout_ms) : _timer_accessor(timer_accessor) { if (timeout_ms > 0) { _construct_timeout_once(); _timeout->start(timeout_ms); } } Genode::uint64_t duration_left() { _construct_timeout_once(); return _timeout->duration_left(); } void handle_timeout() override { lock.unlock(); } }; Genode::Lock mutex; Pthread *pthreads = nullptr; Timer_accessor &timer_accessor; Pthread_pool(Timer_accessor &timer_accessor) : timer_accessor(timer_accessor) { } void resume_all() { Genode::Lock::Guard g(mutex); for (Pthread *p = pthreads; p; p = p->next) p->lock.unlock(); } Genode::uint64_t suspend_myself(Suspend_functor & check, Genode::uint64_t timeout_ms) { Pthread myself { timer_accessor, timeout_ms }; { Genode::Lock::Guard g(mutex); myself.next = pthreads; pthreads = &myself; } if (check.suspend()) myself.lock.lock(); { Genode::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_ */