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
This commit is contained in:
Norman Feske 2019-01-18 11:40:23 +01:00
parent 7b37546a4d
commit af146e7dcd
25 changed files with 365 additions and 130 deletions

View File

@ -1,4 +0,0 @@
SRC_CC = timed_semaphore.cc
LIBS = alarm
vpath timed_semaphore.cc $(REP_DIR)/src/lib/timed_semaphore

View File

@ -4,7 +4,7 @@
# These static libraries are filtered out when linking dynamically linked # These static libraries are filtered out when linking dynamically linked
# binaries. # binaries.
# #
BASE_LIBS += cxx timed_semaphore alarm BASE_LIBS += cxx alarm
# #
# Name of Genode's dynamic linker # Name of Genode's dynamic linker

View File

@ -1 +0,0 @@
2019-01-13 fda13bc38b2fc67126485df088b8a84d0a3e8ff7

View File

@ -19,7 +19,6 @@
#include <util/string.h> #include <util/string.h>
#include <base/thread.h> #include <base/thread.h>
#include <base/heap.h> #include <base/heap.h>
#include <base/timed_semaphore.h>
/* base-internal includes */ /* base-internal includes */
#include <base/internal/unmanaged_singleton.h> #include <base/internal/unmanaged_singleton.h>
@ -711,9 +710,6 @@ void Component::construct(Genode::Env &env)
Link_map::dump(); Link_map::dump();
/* FIXME: remove 'Timeout_thread' from the base library */
Timeout_thread::env(env);
binary_ready_hook_for_gdb(); binary_ready_hook_for_gdb();
/* start binary */ /* start binary */

View File

@ -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 <base/timed_semaphore.h>
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;
}

View File

@ -1,3 +0,0 @@
TARGET = test-timed_semaphore
SRC_CC = main.cc
LIBS = base timed_semaphore

View File

@ -18,6 +18,7 @@
#include <base/env.h> #include <base/env.h>
#include <base/heap.h> #include <base/heap.h>
#include <util/reconstructible.h> #include <util/reconstructible.h>
#include <rump/timed_semaphore.h>
namespace Rump { namespace Rump {
class Env; class Env;
@ -32,6 +33,7 @@ class Rump::Env
private: private:
Genode::Env &_env; Genode::Env &_env;
Timeout_entrypoint _timeout_ep { _env };
Genode::Heap _heap { _env.ram(), _env.rm() }; Genode::Heap _heap { _env.ram(), _env.rm() };
Genode::Attached_rom_dataspace _config { _env, "config" }; Genode::Attached_rom_dataspace _config { _env, "config" };
@ -40,6 +42,7 @@ class Rump::Env
Env(Genode::Env &env) : _env(env) { } Env(Genode::Env &env) : _env(env) { }
Genode::Env &env() { return _env; } Genode::Env &env() { return _env; }
Timeout_entrypoint &timeout_ep() { return _timeout_ep; }
Genode::Heap &heap() { return _heap; } Genode::Heap &heap() { return _heap; }
Genode::Attached_rom_dataspace &config_rom() { return _config; } Genode::Attached_rom_dataspace &config_rom() { return _config; }
}; };

View File

@ -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 <base/thread.h>
#include <base/semaphore.h>
#include <base/alarm.h>
#include <timer_session/connection.h>
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<Timeout_entrypoint> _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_ */

View File

@ -14,7 +14,7 @@
#include <rump/env.h> #include <rump/env.h>
/* /*
* Genode nviroment instance * Genode enviroment instance
*/ */
static Genode::Constructible<Rump::Env> _env; static Genode::Constructible<Rump::Env> _env;

View File

@ -16,7 +16,6 @@
#include <base/log.h> #include <base/log.h>
#include <base/sleep.h> #include <base/sleep.h>
#include <base/timed_semaphore.h>
#include <rump/env.h> #include <rump/env.h>
#include <util/allocator_fap.h> #include <util/allocator_fap.h>
#include <util/random.h> #include <util/random.h>
@ -127,13 +126,6 @@ int rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
main_context()->thread(Genode::Thread::myself()); main_context()->thread(Genode::Thread::myself());
Hard_context_registry::r().insert(main_context()); 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; return 0;
} }

View File

@ -17,7 +17,6 @@ extern "C" {
} }
#include <base/lock.h> #include <base/lock.h>
#include <util/fifo.h> #include <util/fifo.h>
#include <base/timed_semaphore.h>
#include <rump/env.h> #include <rump/env.h>
#include "sched.h" #include "sched.h"
@ -215,7 +214,7 @@ struct Cond
int num_waiters; int num_waiters;
int num_signallers; int num_signallers;
Genode::Lock counter_lock; Genode::Lock counter_lock;
Genode::Timed_semaphore signal_sem; Timed_semaphore signal_sem { Rump::env().timeout_ep() };
Genode::Semaphore handshake_sem; Genode::Semaphore handshake_sem;
Cond() : num_waiters(0), num_signallers(0) { } Cond() : num_waiters(0), num_signallers(0) { }

View File

@ -0,0 +1 @@
2019-01-21 fe6ffef91c2261bc4f7476c9ef842c86178ddef3

View File

@ -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 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) content: $(MIRROR_FROM_REP_DIR)

View File

@ -0,0 +1 @@
2019-01-21 ca889298ade8aca17f07ae66e5200b642f531f28

View File

@ -87,7 +87,7 @@ set config {
<provides> <service name="Timer"/> </provides> <provides> <service name="Timer"/> </provides>
</start> </start>
<start name="test-libc_vfs" caps="200"> <start name="test-libc_vfs" caps="200">
<resource name="RAM" quantum="8M"/> <resource name="RAM" quantum="10M"/>
<config> <config>
<iterations value="1"/>} <iterations value="1"/>}
append_if [have_include "power_on/qemu"] config { append_if [have_include "power_on/qemu"] config {

View File

@ -15,7 +15,6 @@
#include <base/log.h> #include <base/log.h>
#include <base/sleep.h> #include <base/sleep.h>
#include <base/thread.h> #include <base/thread.h>
#include <base/timed_semaphore.h>
#include <util/list.h> #include <util/list.h>
#include <errno.h> #include <errno.h>
@ -23,6 +22,7 @@
#include <stdlib.h> /* malloc, free */ #include <stdlib.h> /* malloc, free */
#include "thread.h" #include "thread.h"
#include "task.h" #include "task.h"
#include "timed_semaphore.h"
using namespace Genode; using namespace Genode;
@ -31,6 +31,24 @@ void * operator new(__SIZE_TYPE__ size) { return malloc(size); }
void operator delete (void * p) { return free(p); } 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 * We initialize the main-thread pointer in a constructor depending on the
* assumption that libpthread is loaded on application startup by ldso. During * assumption that libpthread is loaded on application startup by ldso. During
@ -72,7 +90,7 @@ void pthread::join(void **retval)
{ {
retry = !_thread._exiting; retry = !_thread._exiting;
return retry; return retry;
} }
} check(*this); } check(*this);
do { do {
@ -579,7 +597,7 @@ extern "C" {
int num_waiters; int num_waiters;
int num_signallers; int num_signallers;
Lock counter_lock; Lock counter_lock;
Timed_semaphore signal_sem; Libc::Timed_semaphore signal_sem { _global_timeout_ep() };
Semaphore handshake_sem; Semaphore handshake_sem;
pthread_cond() : num_waiters(0), num_signallers(0) { } pthread_cond() : num_waiters(0), num_signallers(0) { }
@ -712,9 +730,9 @@ extern "C" {
try { try {
c->signal_sem.down(timeout); c->signal_sem.down(timeout);
} catch (Timeout_exception) { } catch (Libc::Timeout_exception) {
result = ETIMEDOUT; result = ETIMEDOUT;
} catch (Genode::Nonblocking_exception) { } catch (Libc::Nonblocking_exception) {
errno = ETIMEDOUT; errno = ETIMEDOUT;
result = ETIMEDOUT; result = ETIMEDOUT;
} }

View File

@ -224,4 +224,7 @@ struct pthread : Genode::Noncopyable, Genode::Thread::Tls::Base
size_t stack_size() const { return _stack_size; } size_t stack_size() const { return _stack_size; }
}; };
namespace Libc { void init_pthread_support(Env &env); }
#endif /* _INCLUDE__SRC_LIB_PTHREAD_THREAD_H_ */ #endif /* _INCLUDE__SRC_LIB_PTHREAD_THREAD_H_ */

View File

@ -16,86 +16,87 @@
* under the terms of the GNU Affero General Public License version 3. * under the terms of the GNU Affero General Public License version 3.
*/ */
#ifndef _INCLUDE__BASE__TIMED_SEMAPHORE_H_ #ifndef _TIMED_SEMAPHORE_H_
#define _INCLUDE__BASE__TIMED_SEMAPHORE_H_ #define _TIMED_SEMAPHORE_H_
#include <base/thread.h> #include <base/thread.h>
#include <base/semaphore.h> #include <base/semaphore.h>
#include <base/alarm.h> #include <base/alarm.h>
#include <timer_session/connection.h> #include <timer_session/connection.h>
namespace Genode { namespace Libc {
class Timeout_thread; using namespace Genode;
class Timeout_entrypoint;
class Timed_semaphore; class Timed_semaphore;
/** /**
* Exception types * Exception types
*/ */
class Timeout_exception; class Timeout_exception : public Exception { };
class Nonblocking_exception; class Nonblocking_exception : public Exception { };
} }
/** /**
* Alarm thread, which counts jiffies and triggers timeout events. * Alarm thread, which counts jiffies and triggers timeout events.
*/ */
class Genode::Timeout_thread : public Thread_deprecated<2048*sizeof(long)>, class Libc::Timeout_entrypoint : private Entrypoint
private Alarm_scheduler
{ {
private: private:
enum { JIFFIES_STEP_MS = 10 }; enum { JIFFIES_STEP_MS = 10 };
static Genode::Env *_env; Alarm_scheduler _alarm_scheduler { };
Timer::Connection _timer { *_env }; Timer::Connection _timer;
Signal_context _context { };
Signal_receiver _receiver { };
void entry(void); Signal_handler<Timeout_entrypoint> _timer_handler;
void _handle_timer() { _alarm_scheduler.handle(_timer.elapsed_ms()); }
static size_t constexpr STACK_SIZE = 2048*sizeof(long);
public: public:
using Alarm_scheduler::schedule_absolute; Timeout_entrypoint(Genode::Env &env)
using Alarm_scheduler::discard; :
Entrypoint(env, STACK_SIZE, "alarm-timer", Affinity::Location()),
Timeout_thread() : Thread_deprecated("alarm-timer") _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); _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(); }
/* void schedule_absolute(Alarm &alarm, Alarm::Time timeout)
* Returns the singleton timeout-thread used for all timeouts. {
*/ _alarm_scheduler.schedule_absolute(&alarm, timeout);
static Timeout_thread *alarm_timer(); }
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. * Semaphore with timeout on down operation.
*/ */
class Genode::Timed_semaphore : public Semaphore class Libc::Timed_semaphore : public Semaphore
{ {
private: private:
typedef Semaphore::Element Element; typedef Semaphore::Element Element;
Timeout_entrypoint &_timeout_ep;
/** /**
* Aborts blocking on the semaphore, raised when a timeout occured. * Aborts blocking on the semaphore, raised when a timeout occured.
* *
* \param element the waiting-queue element associated with a timeout. * \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) bool _abort(Element &element)
{ {
@ -151,22 +152,17 @@ class Genode::Timed_semaphore : public Semaphore
{ {
private: private:
Timed_semaphore &_sem; /* semaphore we block on */ Timed_semaphore &_sem; /* semaphore we block on */
Element &_element; /* queue element timeout belongs to */ Element &_element; /* queue element timeout belongs to */
bool _triggered; /* timeout expired */ bool _triggered { false };
Time _start { }; Time const _start;
public: public:
Timeout(Time duration, Timed_semaphore *s, Element *e) Timeout(Time start, Timed_semaphore &s, Element &e)
: _sem(*s), _element(*e), _triggered(false) : _sem(s), _element(e), _triggered(false), _start(start)
{ { }
Timeout_thread *tt = Timeout_thread::alarm_timer();
_start = tt->time();
tt->schedule_absolute(this, _start + duration);
}
void discard(void) { Timeout_thread::alarm_timer()->discard(this); }
bool triggered(void) { return _triggered; } bool triggered(void) { return _triggered; }
Time start() { return _start; } Time start() { return _start; }
@ -186,7 +182,8 @@ class Genode::Timed_semaphore : public Semaphore
* *
* \param n initial counter value of the semphore * \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. * Decrements semaphore and blocks when it's already zero.
@ -206,7 +203,7 @@ class Genode::Timed_semaphore : public Semaphore
if (t == 0) { if (t == 0) {
++_cnt; ++_cnt;
Semaphore::_meta_lock.unlock(); 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(); Semaphore::_meta_lock.unlock();
/* Create the timeout */ /* 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, * The thread is going to block on a local lock now,
@ -228,17 +227,18 @@ class Genode::Timed_semaphore : public Semaphore
queue_element.block(); queue_element.block();
/* Deactivate timeout */ /* Deactivate timeout */
to.discard(); _timeout_ep.discard(timeout);
/* /*
* When we were only woken up, because of a timeout, * When we were only woken up, because of a timeout,
* throw an exception. * throw an exception.
*/ */
if (to.triggered()) if (timeout.triggered())
throw Genode::Timeout_exception(); throw Timeout_exception();
/* return blocking time */ /* return blocking time */
return Timeout_thread::alarm_timer()->time() - to.start(); return _timeout_ep.time() - timeout.start();
} else { } else {
Semaphore::_meta_lock.unlock(); Semaphore::_meta_lock.unlock();
} }
@ -254,4 +254,4 @@ class Genode::Timed_semaphore : public Semaphore
void up() { Semaphore::up(); } void up() { Semaphore::up(); }
}; };
#endif /* _INCLUDE__BASE__TIMED_SEMAPHORE_H_ */ #endif /* _TIMED_SEMAPHORE_H_ */

View File

@ -1,5 +1,5 @@
/* /*
* \brief Test for the timed-semaphore * \brief Test for the libc-internal timed semaphore
* \author Stefan Kalkowski * \author Stefan Kalkowski
* \author Martin Stein * \author Martin Stein
* \date 2010-03-05 * \date 2010-03-05
@ -14,24 +14,28 @@
/* Genode includes */ /* Genode includes */
#include <timer_session/connection.h> #include <timer_session/connection.h>
#include <base/timed_semaphore.h>
#include <base/thread.h> #include <base/thread.h>
#include <base/component.h> #include <base/component.h>
/* libc-internal include */
#include <timed_semaphore.h>
using namespace Genode; using namespace Genode;
using namespace Libc;
struct Test : Thread struct Test : Thread
{ {
struct Failed : Exception { }; struct Failed : Exception { };
unsigned id; Timeout_entrypoint timeout_ep;
Timer::Connection wakeup_timer; unsigned id;
unsigned const wakeup_period; Timer::Connection wakeup_timer;
Timed_semaphore sem { }; unsigned const wakeup_period;
bool stop_wakeup { false }; Timed_semaphore sem { timeout_ep };
Lock wakeup_stopped { Lock::LOCKED }; bool stop_wakeup { false };
bool got_timeouts { false }; Lock wakeup_stopped { Lock::LOCKED };
bool got_timeouts { false };
void entry() void entry()
{ {
@ -43,8 +47,10 @@ struct Test : Thread
} }
Test(Env &env, bool timeouts, unsigned id, char const *brief) 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"); log("\nTEST ", id, ": ", brief, "\n");
Thread::start(); Thread::start();

View File

@ -0,0 +1,4 @@
TARGET = test-timed_semaphore
SRC_CC = main.cc
LIBS = base
INC_DIR += $(REP_DIR)/src/lib/libc

View File

@ -1 +0,0 @@
2019-01-13 08224b7c04f8a7cbad27286820d81df43c4402ea