Compare commits
1 Commits
Author | SHA1 | Date |
---|---|---|
Chris Copeland | d800eae484 |
|
@ -2,6 +2,7 @@ Import("env")
|
|||
|
||||
env.Program("donate.c")
|
||||
env.Program("empty.c")
|
||||
env.Program("event.c")
|
||||
env.Program("fair.c")
|
||||
env.Program("float.c")
|
||||
env.Program("mutex.c")
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#include <rt/assert.h>
|
||||
#include <rt/event.h>
|
||||
#include <rt/task.h>
|
||||
#include <rt/trap.h>
|
||||
|
||||
static const int n = 10;
|
||||
static RT_EVENT(event);
|
||||
|
||||
static void setter(void)
|
||||
{
|
||||
rt_task_drop_privilege();
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
rt_task_sleep(5);
|
||||
rt_event_set(&event, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void waiter(void)
|
||||
{
|
||||
rt_task_drop_privilege();
|
||||
uint32_t bits;
|
||||
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
bits = rt_event_timedwait(&event, 1, 10);
|
||||
rt_assert((bits & 1) != 0, "wait timed out");
|
||||
}
|
||||
|
||||
bits = rt_event_timedwait(&event, 1, 10);
|
||||
rt_assert((bits & 1) == 0, "wait didn't time out");
|
||||
|
||||
rt_trap();
|
||||
}
|
||||
|
||||
RT_TASK(setter, RT_STACK_MIN, 1);
|
||||
RT_TASK(waiter, RT_STACK_MIN, 1);
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include <rt/atomic.h>
|
||||
#include <rt/cond.h>
|
||||
#include <rt/mutex.h>
|
||||
|
||||
struct rt_event;
|
||||
|
||||
uint32_t rt_event_clear(struct rt_event *, uint32_t);
|
||||
|
||||
uint32_t rt_event_get(const struct rt_event *);
|
||||
|
||||
uint32_t rt_event_set(struct rt_event *, uint32_t);
|
||||
|
||||
uint32_t rt_event_wait(struct rt_event *, uint32_t);
|
||||
|
||||
uint32_t rt_event_wait_all(struct rt_event *, uint32_t);
|
||||
|
||||
uint32_t rt_event_trywait(struct rt_event *, uint32_t);
|
||||
|
||||
uint32_t rt_event_trywait_all(struct rt_event *, uint32_t);
|
||||
|
||||
uint32_t rt_event_timedwait(struct rt_event *, uint32_t, unsigned long ticks);
|
||||
|
||||
uint32_t rt_event_timedwait_all(struct rt_event *, uint32_t,
|
||||
unsigned long ticks);
|
||||
|
||||
struct rt_event
|
||||
{
|
||||
rt_atomic_uint32_t bits;
|
||||
struct rt_mutex mutex;
|
||||
struct rt_cond cond;
|
||||
};
|
||||
|
||||
#define RT_EVENT_INIT(name) \
|
||||
{ \
|
||||
.bits = UINT32_C(0), .mutex = RT_MUTEX_INIT(name.mutex), \
|
||||
.cond = RT_COND_INIT(name.cond), \
|
||||
}
|
||||
|
||||
#define RT_EVENT(name) struct rt_event name = RT_EVENT_INIT(name)
|
|
@ -5,6 +5,7 @@ librt = env.StaticLibrary(
|
|||
source=[
|
||||
"assert.c",
|
||||
"barrier.c",
|
||||
"event.c",
|
||||
"cond.c",
|
||||
"list.c",
|
||||
"mutex.c",
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
#include <rt/event.h>
|
||||
|
||||
#include <rt/tick.h>
|
||||
|
||||
static inline bool match_any(uint32_t bits, uint32_t wait)
|
||||
{
|
||||
return ((bits & wait) != UINT32_C(0));
|
||||
}
|
||||
|
||||
static inline bool match_all(uint32_t bits, uint32_t wait)
|
||||
{
|
||||
return ((bits & wait) == wait);
|
||||
}
|
||||
|
||||
uint32_t rt_event_clear(struct rt_event *event, uint32_t clear)
|
||||
{
|
||||
return rt_atomic_fetch_and(&event->bits, ~clear, RT_ATOMIC_ACQ_REL);
|
||||
}
|
||||
|
||||
uint32_t rt_event_get(const struct rt_event *event)
|
||||
{
|
||||
return rt_atomic_load(&event->bits, RT_ATOMIC_ACQUIRE);
|
||||
}
|
||||
|
||||
uint32_t rt_event_set(struct rt_event *event, uint32_t set)
|
||||
{
|
||||
const uint32_t oldbits =
|
||||
rt_atomic_fetch_or(&event->bits, set, RT_ATOMIC_RELEASE);
|
||||
rt_cond_broadcast(&event->cond);
|
||||
return oldbits;
|
||||
}
|
||||
|
||||
uint32_t rt_event_wait(struct rt_event *event, uint32_t wait)
|
||||
{
|
||||
uint32_t bits = rt_event_trywait(event, wait);
|
||||
if (match_any(bits, wait))
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
rt_mutex_lock(&event->mutex);
|
||||
while (!match_any(bits = rt_event_trywait(event, wait), wait))
|
||||
{
|
||||
rt_cond_wait(&event->cond, &event->mutex);
|
||||
}
|
||||
rt_mutex_unlock(&event->mutex);
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint32_t rt_event_trywait(struct rt_event *event, uint32_t wait)
|
||||
{
|
||||
uint32_t bits = rt_atomic_load(&event->bits, RT_ATOMIC_RELAXED);
|
||||
while (match_any(bits, wait) &&
|
||||
!rt_atomic_compare_exchange_weak(&event->bits, &bits, bits & ~wait,
|
||||
RT_ATOMIC_ACQUIRE,
|
||||
RT_ATOMIC_RELAXED))
|
||||
{
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint32_t rt_event_timedwait(struct rt_event *event, uint32_t wait,
|
||||
unsigned long ticks)
|
||||
{
|
||||
unsigned long start_tick = rt_tick_count();
|
||||
uint32_t bits = rt_event_trywait(event, wait);
|
||||
if (match_any(bits, wait) || !rt_mutex_timedlock(&event->mutex, ticks))
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
while (!match_any(bits = rt_event_trywait(event, wait), wait))
|
||||
{
|
||||
rt_tick_elapse(&ticks, &start_tick);
|
||||
if (!rt_cond_timedwait(&event->cond, &event->mutex, ticks))
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
}
|
||||
rt_mutex_unlock(&event->mutex);
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint32_t rt_event_wait_all(struct rt_event *event, uint32_t wait)
|
||||
{
|
||||
uint32_t bits = rt_event_trywait_all(event, wait);
|
||||
if (match_all(bits, wait))
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
rt_mutex_lock(&event->mutex);
|
||||
while (!match_all(bits = rt_event_trywait_all(event, wait), wait))
|
||||
{
|
||||
rt_cond_wait(&event->cond, &event->mutex);
|
||||
}
|
||||
rt_mutex_unlock(&event->mutex);
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint32_t rt_event_trywait_all(struct rt_event *event, uint32_t wait)
|
||||
{
|
||||
uint32_t bits = rt_atomic_load(&event->bits, RT_ATOMIC_RELAXED);
|
||||
while (match_all(bits, wait) &&
|
||||
!rt_atomic_compare_exchange_weak(&event->bits, &bits, bits & ~wait,
|
||||
RT_ATOMIC_ACQUIRE,
|
||||
RT_ATOMIC_RELAXED))
|
||||
{
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint32_t rt_event_timedwait_all(struct rt_event *event, uint32_t wait,
|
||||
unsigned long ticks)
|
||||
{
|
||||
unsigned long start_tick = rt_tick_count();
|
||||
uint32_t bits = rt_event_trywait_all(event, wait);
|
||||
if (match_all(bits, wait) || !rt_mutex_timedlock(&event->mutex, ticks))
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
while (!match_all(bits = rt_event_trywait_all(event, wait), wait))
|
||||
{
|
||||
rt_tick_elapse(&ticks, &start_tick);
|
||||
if (!rt_cond_timedwait(&event->cond, &event->mutex, ticks))
|
||||
{
|
||||
return bits;
|
||||
}
|
||||
}
|
||||
rt_mutex_unlock(&event->mutex);
|
||||
return bits;
|
||||
}
|
|
@ -7,7 +7,7 @@ scons -j $(nproc)
|
|||
trap 'if [ "$?" != "0" ]; then echo "test failed!"; fi' EXIT
|
||||
|
||||
examples=(
|
||||
donate empty float mutex notify once queue rwlock sem simple tls
|
||||
donate empty event float mutex notify once queue rwlock sem simple tls
|
||||
water/barrier water/cond water/sem cycle/mutex cycle/notify cycle/queue
|
||||
cycle/sem cycle/sleep cycle/yield cxx/mutex cxx/notify cxx/once cxx/queue
|
||||
cxx/rwlock cxx/sem cxx/water/barrier cxx/water/cond cxx/water/sem
|
||||
|
|
Loading…
Reference in New Issue