From af146e7dcde200674a452681bb876b1c1f2dc591 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 18 Jan 2019 11:40:23 +0100 Subject: [PATCH] Remove base/timed_semaphore.h from API The former 'Genode::Timed_semaphore' mechanism is moved to the private part of the two remaining users, namely dde_rump and the libc. Note there are now two private copies of 'timed_semaphore.h'. This should be regarded as an interim step until the use of this mechanism is removed from both users. This patch also cleans up the mechanism from legacy Genode API calls and global side effects (alarm-thread singleton). The test/timed_semaphore is now located at the libports repository as it now tests a mechanism of the libc. The former timed_semaphore library is no more. Fixes #3121 --- repos/base/lib/mk/timed_semaphore.mk | 4 - repos/base/mk/base-libs.mk | 2 +- .../recipes/src/test-timed_semaphore/hash | 1 - repos/base/src/lib/ldso/main.cc | 4 - .../lib/timed_semaphore/timed_semaphore.cc | 35 --- repos/base/src/test/timed_semaphore/target.mk | 3 - repos/dde_rump/include/rump/env.h | 3 + repos/dde_rump/include/rump/timed_semaphore.h | 256 ++++++++++++++++++ repos/dde_rump/src/lib/rump/env.cc | 2 +- repos/dde_rump/src/lib/rump/hypercall.cc | 8 - repos/dde_rump/src/lib/rump/sync.cc | 3 +- .../recipes/pkg/test-timed_semaphore/README | 0 .../recipes/pkg/test-timed_semaphore/archives | 0 .../recipes/pkg/test-timed_semaphore/hash | 1 + .../recipes/pkg/test-timed_semaphore/runtime | 0 .../src/test-timed_semaphore/content.mk | 4 +- .../recipes/src/test-timed_semaphore/hash | 1 + .../src/test-timed_semaphore/used_apis | 0 .../libports/run/libc_vfs_filesystem_test.inc | 2 +- repos/libports/src/lib/libc/thread.cc | 28 +- repos/libports/src/lib/libc/thread.h | 3 + .../src/lib/libc}/timed_semaphore.h | 102 +++---- .../src/test/timed_semaphore/main.cc | 28 +- .../src/test/timed_semaphore/target.mk | 4 + .../os/recipes/pkg/test-timed_semaphore/hash | 1 - 25 files changed, 365 insertions(+), 130 deletions(-) delete mode 100644 repos/base/lib/mk/timed_semaphore.mk delete mode 100644 repos/base/recipes/src/test-timed_semaphore/hash delete mode 100644 repos/base/src/lib/timed_semaphore/timed_semaphore.cc delete mode 100644 repos/base/src/test/timed_semaphore/target.mk create mode 100644 repos/dde_rump/include/rump/timed_semaphore.h rename repos/{os => libports}/recipes/pkg/test-timed_semaphore/README (100%) rename repos/{os => libports}/recipes/pkg/test-timed_semaphore/archives (100%) create mode 100644 repos/libports/recipes/pkg/test-timed_semaphore/hash rename repos/{os => libports}/recipes/pkg/test-timed_semaphore/runtime (100%) rename repos/{base => libports}/recipes/src/test-timed_semaphore/content.mk (50%) create mode 100644 repos/libports/recipes/src/test-timed_semaphore/hash rename repos/{base => libports}/recipes/src/test-timed_semaphore/used_apis (100%) rename repos/{base/include/base => libports/src/lib/libc}/timed_semaphore.h (66%) rename repos/{base => libports}/src/test/timed_semaphore/main.cc (70%) create mode 100644 repos/libports/src/test/timed_semaphore/target.mk delete mode 100644 repos/os/recipes/pkg/test-timed_semaphore/hash diff --git a/repos/base/lib/mk/timed_semaphore.mk b/repos/base/lib/mk/timed_semaphore.mk deleted file mode 100644 index fc8efb759..000000000 --- a/repos/base/lib/mk/timed_semaphore.mk +++ /dev/null @@ -1,4 +0,0 @@ -SRC_CC = timed_semaphore.cc -LIBS = alarm - -vpath timed_semaphore.cc $(REP_DIR)/src/lib/timed_semaphore diff --git a/repos/base/mk/base-libs.mk b/repos/base/mk/base-libs.mk index addace958..06a5c2275 100644 --- a/repos/base/mk/base-libs.mk +++ b/repos/base/mk/base-libs.mk @@ -4,7 +4,7 @@ # These static libraries are filtered out when linking dynamically linked # binaries. # -BASE_LIBS += cxx timed_semaphore alarm +BASE_LIBS += cxx alarm # # Name of Genode's dynamic linker diff --git a/repos/base/recipes/src/test-timed_semaphore/hash b/repos/base/recipes/src/test-timed_semaphore/hash deleted file mode 100644 index 7bce9c375..000000000 --- a/repos/base/recipes/src/test-timed_semaphore/hash +++ /dev/null @@ -1 +0,0 @@ -2019-01-13 fda13bc38b2fc67126485df088b8a84d0a3e8ff7 diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc index d6a143767..978346b12 100644 --- a/repos/base/src/lib/ldso/main.cc +++ b/repos/base/src/lib/ldso/main.cc @@ -19,7 +19,6 @@ #include #include #include -#include /* base-internal includes */ #include @@ -711,9 +710,6 @@ void Component::construct(Genode::Env &env) Link_map::dump(); - /* FIXME: remove 'Timeout_thread' from the base library */ - Timeout_thread::env(env); - binary_ready_hook_for_gdb(); /* start binary */ diff --git a/repos/base/src/lib/timed_semaphore/timed_semaphore.cc b/repos/base/src/lib/timed_semaphore/timed_semaphore.cc deleted file mode 100644 index 40b47d45c..000000000 --- a/repos/base/src/lib/timed_semaphore/timed_semaphore.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - * \brief Semaphore implementation with timeout facility. - * \author Stefan Kalkowski - * \date 2010-03-05 - */ - -/* - * Copyright (C) 2010-2017 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. - */ - -#include - - -Genode::Env *Genode::Timeout_thread::_env = nullptr; - - -void Genode::Timeout_thread::entry() -{ - while (true) { - Signal s = _receiver.wait_for_signal(); - - /* handle timouts of this point in time */ - Genode::Alarm_scheduler::handle(_timer.elapsed_ms()); - } -} - - -Genode::Timeout_thread *Genode::Timeout_thread::alarm_timer() -{ - static Timeout_thread _alarm_timer; - return &_alarm_timer; -} diff --git a/repos/base/src/test/timed_semaphore/target.mk b/repos/base/src/test/timed_semaphore/target.mk deleted file mode 100644 index dcc78183f..000000000 --- a/repos/base/src/test/timed_semaphore/target.mk +++ /dev/null @@ -1,3 +0,0 @@ -TARGET = test-timed_semaphore -SRC_CC = main.cc -LIBS = base timed_semaphore diff --git a/repos/dde_rump/include/rump/env.h b/repos/dde_rump/include/rump/env.h index 31d8b8ac6..1b94bd5ff 100644 --- a/repos/dde_rump/include/rump/env.h +++ b/repos/dde_rump/include/rump/env.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace Rump { class Env; @@ -32,6 +33,7 @@ class Rump::Env private: Genode::Env &_env; + Timeout_entrypoint _timeout_ep { _env }; Genode::Heap _heap { _env.ram(), _env.rm() }; Genode::Attached_rom_dataspace _config { _env, "config" }; @@ -40,6 +42,7 @@ class Rump::Env Env(Genode::Env &env) : _env(env) { } Genode::Env &env() { return _env; } + Timeout_entrypoint &timeout_ep() { return _timeout_ep; } Genode::Heap &heap() { return _heap; } Genode::Attached_rom_dataspace &config_rom() { return _config; } }; diff --git a/repos/dde_rump/include/rump/timed_semaphore.h b/repos/dde_rump/include/rump/timed_semaphore.h new file mode 100644 index 000000000..50353dad3 --- /dev/null +++ b/repos/dde_rump/include/rump/timed_semaphore.h @@ -0,0 +1,256 @@ +/* + * \brief Semaphore implementation with timeout facility + * \author Stefan Kalkowski + * \date 2010-03-05 + * + * This semaphore implementation allows to block on a semaphore for a + * given time instead of blocking indefinetely. + * + * For the timeout functionality the alarm framework is used. + */ + +/* + * Copyright (C) 2010-2017 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 _INCLUDE__RUMP__TIMED_SEMAPHORE_H_ +#define _INCLUDE__RUMP__TIMED_SEMAPHORE_H_ + +#include +#include +#include +#include + +using Genode::Exception; +using Genode::Entrypoint; +using Genode::Alarm; +using Genode::Alarm_scheduler; +using Genode::Semaphore; +using Genode::Signal_handler; + +/** + * Exception types + */ +class Timeout_exception : public Exception { }; +class Nonblocking_exception : public Exception { }; + + +/** + * Alarm thread, which counts jiffies and triggers timeout events. + */ +class Timeout_entrypoint : private Entrypoint +{ + private: + + enum { JIFFIES_STEP_MS = 10 }; + + Alarm_scheduler _alarm_scheduler { }; + + Timer::Connection _timer; + + Signal_handler _timer_handler; + + void _handle_timer() { _alarm_scheduler.handle(_timer.elapsed_ms()); } + + static Genode::size_t constexpr STACK_SIZE = 2048*sizeof(long); + + public: + + Timeout_entrypoint(Genode::Env &env) + : + Entrypoint(env, STACK_SIZE, "alarm-timer", Genode::Affinity::Location()), + _timer(env), + _timer_handler(*this, *this, &Timeout_entrypoint::_handle_timer) + { + _timer.sigh(_timer_handler); + _timer.trigger_periodic(JIFFIES_STEP_MS*1000); + } + + Alarm::Time time(void) { return _timer.elapsed_ms(); } + + void schedule_absolute(Alarm &alarm, Alarm::Time timeout) + { + _alarm_scheduler.schedule_absolute(&alarm, timeout); + } + + void discard(Alarm &alarm) { _alarm_scheduler.discard(&alarm); } +}; + + +/** + * Semaphore with timeout on down operation. + */ +class Timed_semaphore : public Semaphore +{ + private: + + typedef Semaphore::Element Element; + + Timeout_entrypoint &_timeout_ep; + + /** + * Aborts blocking on the semaphore, raised when a timeout occured. + * + * \param element the waiting-queue element associated with a timeout. + * \return true if a thread was aborted/woken up + */ + bool _abort(Element &element) + { + Genode::Lock::Guard lock_guard(Semaphore::_meta_lock); + + /* potentially, the queue is empty */ + if (++Semaphore::_cnt <= 0) { + + /* + * Iterate through the queue and find the thread, + * with the corresponding timeout. + */ + Element *first = Semaphore::_queue.dequeue(); + Element *e = first; + + while (true) { + + /* + * Wakeup the thread. + */ + if (&element == e) { + e->wake_up(); + return true; + } + + /* + * Noninvolved threads are enqueued again. + */ + Semaphore::_queue.enqueue(e); + e = Semaphore::_queue.dequeue(); + + /* + * Maybe, the alarm was triggered just after the corresponding + * thread was already dequeued, that's why we have to track + * whether we processed the whole queue. + */ + if (e == first) + break; + } + } + + /* The right element was not found, so decrease counter again */ + --Semaphore::_cnt; + return false; + } + + + /** + * Represents a timeout associated with the blocking + * operation on a semaphore. + */ + class Timeout : public Alarm + { + private: + + Timed_semaphore &_sem; /* semaphore we block on */ + Element &_element; /* queue element timeout belongs to */ + bool _triggered { false }; + Time const _start; + + public: + + Timeout(Time start, Timed_semaphore &s, Element &e) + : _sem(s), _element(e), _triggered(false), _start(start) + { } + + bool triggered(void) { return _triggered; } + Time start() { return _start; } + + protected: + + bool on_alarm(unsigned) override + { + _triggered = _sem._abort(_element); + return false; + } + }; + + public: + + /** + * Constructor + * + * \param n initial counter value of the semphore + */ + Timed_semaphore(Timeout_entrypoint &timeout_ep, int n = 0) + : Semaphore(n), _timeout_ep(timeout_ep) { } + + /** + * Decrements semaphore and blocks when it's already zero. + * + * \param t after t milliseconds of blocking a Timeout_exception is thrown. + * if t is zero do not block, instead raise an + * Nonblocking_exception. + * \return milliseconds the caller was blocked + */ + Alarm::Time down(Alarm::Time t) + { + Semaphore::_meta_lock.lock(); + + if (--Semaphore::_cnt < 0) { + + /* If t==0 we shall not block */ + if (t == 0) { + ++_cnt; + Semaphore::_meta_lock.unlock(); + throw Nonblocking_exception(); + } + + /* + * Create semaphore queue element representing the thread + * in the wait queue. + */ + Element queue_element; + Semaphore::_queue.enqueue(&queue_element); + Semaphore::_meta_lock.unlock(); + + /* Create the timeout */ + Alarm::Time const curr_time = _timeout_ep.time(); + Timeout timeout(curr_time, *this, queue_element); + _timeout_ep.schedule_absolute(timeout, curr_time + t); + + /* + * The thread is going to block on a local lock now, + * waiting for getting waked from another thread + * calling 'up()' + * */ + queue_element.block(); + + /* Deactivate timeout */ + _timeout_ep.discard(timeout); + + /* + * When we were only woken up, because of a timeout, + * throw an exception. + */ + if (timeout.triggered()) + throw Timeout_exception(); + + /* return blocking time */ + return _timeout_ep.time() - timeout.start(); + + } else { + Semaphore::_meta_lock.unlock(); + } + return 0; + } + + + /******************************** + ** Base class implementations ** + ********************************/ + + void down() { Semaphore::down(); } + void up() { Semaphore::up(); } +}; + +#endif /* _INCLUDE__RUMP__TIMED_SEMAPHORE_H_ */ diff --git a/repos/dde_rump/src/lib/rump/env.cc b/repos/dde_rump/src/lib/rump/env.cc index 5cdffa574..0b322eae9 100644 --- a/repos/dde_rump/src/lib/rump/env.cc +++ b/repos/dde_rump/src/lib/rump/env.cc @@ -14,7 +14,7 @@ #include /* - * Genode nviroment instance + * Genode enviroment instance */ static Genode::Constructible _env; diff --git a/repos/dde_rump/src/lib/rump/hypercall.cc b/repos/dde_rump/src/lib/rump/hypercall.cc index a3ff19a60..8a15a8584 100644 --- a/repos/dde_rump/src/lib/rump/hypercall.cc +++ b/repos/dde_rump/src/lib/rump/hypercall.cc @@ -16,7 +16,6 @@ #include #include -#include #include #include #include @@ -127,13 +126,6 @@ int rumpuser_init(int version, const struct rumpuser_hyperup *hyp) main_context()->thread(Genode::Thread::myself()); Hard_context_registry::r().insert(main_context()); - /* - * Start 'Timeout_thread' so it does not get constructed concurrently (which - * causes one thread to spin in cxa_guard_aqcuire), making emulation *really* - * slow - */ - Genode::Timeout_thread::alarm_timer(); - return 0; } diff --git a/repos/dde_rump/src/lib/rump/sync.cc b/repos/dde_rump/src/lib/rump/sync.cc index 35f6318b2..beae68c57 100644 --- a/repos/dde_rump/src/lib/rump/sync.cc +++ b/repos/dde_rump/src/lib/rump/sync.cc @@ -17,7 +17,6 @@ extern "C" { } #include #include -#include #include #include "sched.h" @@ -215,7 +214,7 @@ struct Cond int num_waiters; int num_signallers; Genode::Lock counter_lock; - Genode::Timed_semaphore signal_sem; + Timed_semaphore signal_sem { Rump::env().timeout_ep() }; Genode::Semaphore handshake_sem; Cond() : num_waiters(0), num_signallers(0) { } diff --git a/repos/os/recipes/pkg/test-timed_semaphore/README b/repos/libports/recipes/pkg/test-timed_semaphore/README similarity index 100% rename from repos/os/recipes/pkg/test-timed_semaphore/README rename to repos/libports/recipes/pkg/test-timed_semaphore/README diff --git a/repos/os/recipes/pkg/test-timed_semaphore/archives b/repos/libports/recipes/pkg/test-timed_semaphore/archives similarity index 100% rename from repos/os/recipes/pkg/test-timed_semaphore/archives rename to repos/libports/recipes/pkg/test-timed_semaphore/archives diff --git a/repos/libports/recipes/pkg/test-timed_semaphore/hash b/repos/libports/recipes/pkg/test-timed_semaphore/hash new file mode 100644 index 000000000..f696d5280 --- /dev/null +++ b/repos/libports/recipes/pkg/test-timed_semaphore/hash @@ -0,0 +1 @@ +2019-01-21 fe6ffef91c2261bc4f7476c9ef842c86178ddef3 diff --git a/repos/os/recipes/pkg/test-timed_semaphore/runtime b/repos/libports/recipes/pkg/test-timed_semaphore/runtime similarity index 100% rename from repos/os/recipes/pkg/test-timed_semaphore/runtime rename to repos/libports/recipes/pkg/test-timed_semaphore/runtime diff --git a/repos/base/recipes/src/test-timed_semaphore/content.mk b/repos/libports/recipes/src/test-timed_semaphore/content.mk similarity index 50% rename from repos/base/recipes/src/test-timed_semaphore/content.mk rename to repos/libports/recipes/src/test-timed_semaphore/content.mk index c00045b37..5066c0a00 100644 --- a/repos/base/recipes/src/test-timed_semaphore/content.mk +++ b/repos/libports/recipes/src/test-timed_semaphore/content.mk @@ -1,7 +1,7 @@ -SRC_DIR = src/test/timed_semaphore src/lib/timed_semaphore src/lib/alarm +SRC_DIR = src/test/timed_semaphore include $(GENODE_DIR)/repos/base/recipes/src/content.inc -MIRROR_FROM_REP_DIR := lib/mk/timed_semaphore.mk lib/mk/alarm.mk +MIRROR_FROM_REP_DIR := src/lib/libc/timed_semaphore.h content: $(MIRROR_FROM_REP_DIR) diff --git a/repos/libports/recipes/src/test-timed_semaphore/hash b/repos/libports/recipes/src/test-timed_semaphore/hash new file mode 100644 index 000000000..c98bcb53b --- /dev/null +++ b/repos/libports/recipes/src/test-timed_semaphore/hash @@ -0,0 +1 @@ +2019-01-21 ca889298ade8aca17f07ae66e5200b642f531f28 diff --git a/repos/base/recipes/src/test-timed_semaphore/used_apis b/repos/libports/recipes/src/test-timed_semaphore/used_apis similarity index 100% rename from repos/base/recipes/src/test-timed_semaphore/used_apis rename to repos/libports/recipes/src/test-timed_semaphore/used_apis diff --git a/repos/libports/run/libc_vfs_filesystem_test.inc b/repos/libports/run/libc_vfs_filesystem_test.inc index 099764126..a5e3a9d7a 100644 --- a/repos/libports/run/libc_vfs_filesystem_test.inc +++ b/repos/libports/run/libc_vfs_filesystem_test.inc @@ -87,7 +87,7 @@ set config { - + } append_if [have_include "power_on/qemu"] config { diff --git a/repos/libports/src/lib/libc/thread.cc b/repos/libports/src/lib/libc/thread.cc index 71c362ee4..26ab173ea 100644 --- a/repos/libports/src/lib/libc/thread.cc +++ b/repos/libports/src/lib/libc/thread.cc @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -23,6 +22,7 @@ #include /* malloc, free */ #include "thread.h" #include "task.h" +#include "timed_semaphore.h" using namespace Genode; @@ -31,6 +31,24 @@ void * operator new(__SIZE_TYPE__ size) { return malloc(size); } void operator delete (void * p) { return free(p); } +static Env *_env_ptr; /* solely needed to spawn the timeout thread for the + timed semaphore */ + + +namespace Libc { void init_pthread_support(Env &env) { _env_ptr = &env; } } + + +static Libc::Timeout_entrypoint &_global_timeout_ep() +{ + class Missing_call_of_init_pthread_support { }; + if (!_env_ptr) + throw Missing_call_of_init_pthread_support(); + + static Libc::Timeout_entrypoint timeout_ep { *_env_ptr }; + return timeout_ep; +} + + /* * We initialize the main-thread pointer in a constructor depending on the * assumption that libpthread is loaded on application startup by ldso. During @@ -72,7 +90,7 @@ void pthread::join(void **retval) { retry = !_thread._exiting; return retry; - } + } } check(*this); do { @@ -579,7 +597,7 @@ extern "C" { int num_waiters; int num_signallers; Lock counter_lock; - Timed_semaphore signal_sem; + Libc::Timed_semaphore signal_sem { _global_timeout_ep() }; Semaphore handshake_sem; pthread_cond() : num_waiters(0), num_signallers(0) { } @@ -712,9 +730,9 @@ extern "C" { try { c->signal_sem.down(timeout); - } catch (Timeout_exception) { + } catch (Libc::Timeout_exception) { result = ETIMEDOUT; - } catch (Genode::Nonblocking_exception) { + } catch (Libc::Nonblocking_exception) { errno = ETIMEDOUT; result = ETIMEDOUT; } diff --git a/repos/libports/src/lib/libc/thread.h b/repos/libports/src/lib/libc/thread.h index c8728b040..c4f3af108 100644 --- a/repos/libports/src/lib/libc/thread.h +++ b/repos/libports/src/lib/libc/thread.h @@ -224,4 +224,7 @@ struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base size_t stack_size() const { return _stack_size; } }; + +namespace Libc { void init_pthread_support(Env &env); } + #endif /* _INCLUDE__SRC_LIB_PTHREAD_THREAD_H_ */ diff --git a/repos/base/include/base/timed_semaphore.h b/repos/libports/src/lib/libc/timed_semaphore.h similarity index 66% rename from repos/base/include/base/timed_semaphore.h rename to repos/libports/src/lib/libc/timed_semaphore.h index 12dd83906..9fc52ce2b 100644 --- a/repos/base/include/base/timed_semaphore.h +++ b/repos/libports/src/lib/libc/timed_semaphore.h @@ -16,86 +16,87 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _INCLUDE__BASE__TIMED_SEMAPHORE_H_ -#define _INCLUDE__BASE__TIMED_SEMAPHORE_H_ +#ifndef _TIMED_SEMAPHORE_H_ +#define _TIMED_SEMAPHORE_H_ #include #include #include #include -namespace Genode { +namespace Libc { - class Timeout_thread; + using namespace Genode; + + class Timeout_entrypoint; class Timed_semaphore; /** * Exception types */ - class Timeout_exception; - class Nonblocking_exception; + class Timeout_exception : public Exception { }; + class Nonblocking_exception : public Exception { }; } /** * Alarm thread, which counts jiffies and triggers timeout events. */ -class Genode::Timeout_thread : public Thread_deprecated<2048*sizeof(long)>, - private Alarm_scheduler +class Libc::Timeout_entrypoint : private Entrypoint { private: enum { JIFFIES_STEP_MS = 10 }; - static Genode::Env *_env; + Alarm_scheduler _alarm_scheduler { }; - Timer::Connection _timer { *_env }; - Signal_context _context { }; - Signal_receiver _receiver { }; + Timer::Connection _timer; - void entry(void); + Signal_handler _timer_handler; + + void _handle_timer() { _alarm_scheduler.handle(_timer.elapsed_ms()); } + + static size_t constexpr STACK_SIZE = 2048*sizeof(long); public: - using Alarm_scheduler::schedule_absolute; - using Alarm_scheduler::discard; - - Timeout_thread() : Thread_deprecated("alarm-timer") + Timeout_entrypoint(Genode::Env &env) + : + Entrypoint(env, STACK_SIZE, "alarm-timer", Affinity::Location()), + _timer(env), + _timer_handler(*this, *this, &Timeout_entrypoint::_handle_timer) { - _timer.sigh(_receiver.manage(&_context)); + _timer.sigh(_timer_handler); _timer.trigger_periodic(JIFFIES_STEP_MS*1000); - start(); } - Genode::Alarm::Time time(void) { return _timer.elapsed_ms(); } + Alarm::Time time(void) { return _timer.elapsed_ms(); } - /* - * Returns the singleton timeout-thread used for all timeouts. - */ - static Timeout_thread *alarm_timer(); + void schedule_absolute(Alarm &alarm, Alarm::Time timeout) + { + _alarm_scheduler.schedule_absolute(&alarm, timeout); + } - static void env(Genode::Env &env) { _env = &env; } + void discard(Alarm &alarm) { _alarm_scheduler.discard(&alarm); } }; -class Genode::Timeout_exception : public Exception { }; -class Genode::Nonblocking_exception : public Exception { }; - - /** * Semaphore with timeout on down operation. */ -class Genode::Timed_semaphore : public Semaphore +class Libc::Timed_semaphore : public Semaphore { private: typedef Semaphore::Element Element; + Timeout_entrypoint &_timeout_ep; + /** * Aborts blocking on the semaphore, raised when a timeout occured. * * \param element the waiting-queue element associated with a timeout. - * \return true if a thread was aborted/woken up + * \return true if a thread was aborted/woken up */ bool _abort(Element &element) { @@ -151,22 +152,17 @@ class Genode::Timed_semaphore : public Semaphore { private: - Timed_semaphore &_sem; /* semaphore we block on */ - Element &_element; /* queue element timeout belongs to */ - bool _triggered; /* timeout expired */ - Time _start { }; + Timed_semaphore &_sem; /* semaphore we block on */ + Element &_element; /* queue element timeout belongs to */ + bool _triggered { false }; + Time const _start; public: - Timeout(Time duration, Timed_semaphore *s, Element *e) - : _sem(*s), _element(*e), _triggered(false) - { - Timeout_thread *tt = Timeout_thread::alarm_timer(); - _start = tt->time(); - tt->schedule_absolute(this, _start + duration); - } + Timeout(Time start, Timed_semaphore &s, Element &e) + : _sem(s), _element(e), _triggered(false), _start(start) + { } - void discard(void) { Timeout_thread::alarm_timer()->discard(this); } bool triggered(void) { return _triggered; } Time start() { return _start; } @@ -186,7 +182,8 @@ class Genode::Timed_semaphore : public Semaphore * * \param n initial counter value of the semphore */ - Timed_semaphore(int n = 0) : Semaphore(n) { } + Timed_semaphore(Timeout_entrypoint &timeout_ep, int n = 0) + : Semaphore(n), _timeout_ep(timeout_ep) { } /** * Decrements semaphore and blocks when it's already zero. @@ -206,7 +203,7 @@ class Genode::Timed_semaphore : public Semaphore if (t == 0) { ++_cnt; Semaphore::_meta_lock.unlock(); - throw Genode::Nonblocking_exception(); + throw Nonblocking_exception(); } /* @@ -218,7 +215,9 @@ class Genode::Timed_semaphore : public Semaphore Semaphore::_meta_lock.unlock(); /* Create the timeout */ - Timeout to(t, this, &queue_element); + Alarm::Time const curr_time = _timeout_ep.time(); + Timeout timeout(curr_time, *this, queue_element); + _timeout_ep.schedule_absolute(timeout, curr_time + t); /* * The thread is going to block on a local lock now, @@ -228,17 +227,18 @@ class Genode::Timed_semaphore : public Semaphore queue_element.block(); /* Deactivate timeout */ - to.discard(); + _timeout_ep.discard(timeout); /* * When we were only woken up, because of a timeout, * throw an exception. */ - if (to.triggered()) - throw Genode::Timeout_exception(); + if (timeout.triggered()) + throw Timeout_exception(); /* return blocking time */ - return Timeout_thread::alarm_timer()->time() - to.start(); + return _timeout_ep.time() - timeout.start(); + } else { Semaphore::_meta_lock.unlock(); } @@ -254,4 +254,4 @@ class Genode::Timed_semaphore : public Semaphore void up() { Semaphore::up(); } }; -#endif /* _INCLUDE__BASE__TIMED_SEMAPHORE_H_ */ +#endif /* _TIMED_SEMAPHORE_H_ */ diff --git a/repos/base/src/test/timed_semaphore/main.cc b/repos/libports/src/test/timed_semaphore/main.cc similarity index 70% rename from repos/base/src/test/timed_semaphore/main.cc rename to repos/libports/src/test/timed_semaphore/main.cc index 5a4386038..0bcd84b46 100644 --- a/repos/base/src/test/timed_semaphore/main.cc +++ b/repos/libports/src/test/timed_semaphore/main.cc @@ -1,5 +1,5 @@ /* - * \brief Test for the timed-semaphore + * \brief Test for the libc-internal timed semaphore * \author Stefan Kalkowski * \author Martin Stein * \date 2010-03-05 @@ -14,24 +14,28 @@ /* Genode includes */ #include -#include #include #include +/* libc-internal include */ +#include + using namespace Genode; +using namespace Libc; struct Test : Thread { struct Failed : Exception { }; - unsigned id; - Timer::Connection wakeup_timer; - unsigned const wakeup_period; - Timed_semaphore sem { }; - bool stop_wakeup { false }; - Lock wakeup_stopped { Lock::LOCKED }; - bool got_timeouts { false }; + Timeout_entrypoint timeout_ep; + unsigned id; + Timer::Connection wakeup_timer; + unsigned const wakeup_period; + Timed_semaphore sem { timeout_ep }; + bool stop_wakeup { false }; + Lock wakeup_stopped { Lock::LOCKED }; + bool got_timeouts { false }; void entry() { @@ -43,8 +47,10 @@ struct Test : Thread } Test(Env &env, bool timeouts, unsigned id, char const *brief) - : Thread(env, "wakeup", 1024 * sizeof(addr_t)), id(id), wakeup_timer(env), - wakeup_period(timeouts ? 1000 : 100) + : + Thread(env, "wakeup", 1024 * sizeof(addr_t)), + timeout_ep(env), id(id), wakeup_timer(env), + wakeup_period(timeouts ? 1000 : 100) { log("\nTEST ", id, ": ", brief, "\n"); Thread::start(); diff --git a/repos/libports/src/test/timed_semaphore/target.mk b/repos/libports/src/test/timed_semaphore/target.mk new file mode 100644 index 000000000..e0439f85b --- /dev/null +++ b/repos/libports/src/test/timed_semaphore/target.mk @@ -0,0 +1,4 @@ +TARGET = test-timed_semaphore +SRC_CC = main.cc +LIBS = base +INC_DIR += $(REP_DIR)/src/lib/libc diff --git a/repos/os/recipes/pkg/test-timed_semaphore/hash b/repos/os/recipes/pkg/test-timed_semaphore/hash deleted file mode 100644 index fc80b55c2..000000000 --- a/repos/os/recipes/pkg/test-timed_semaphore/hash +++ /dev/null @@ -1 +0,0 @@ -2019-01-13 08224b7c04f8a7cbad27286820d81df43c4402ea