67 lines
1.8 KiB
C
67 lines
1.8 KiB
C
#include <rt/cond.h>
|
|
|
|
#include <rt/atomic.h>
|
|
#include <rt/log.h>
|
|
#include <rt/mutex.h>
|
|
#include <rt/syscall.h>
|
|
#include <rt/task.h>
|
|
#include <rt/tick.h>
|
|
|
|
#include <limits.h>
|
|
|
|
void rt_cond_signal(struct rt_cond *cond)
|
|
{
|
|
rt_logf("%s cond signal\n", rt_task_name());
|
|
rt_sem_post(&cond->sem);
|
|
}
|
|
|
|
void rt_cond_broadcast(struct rt_cond *cond)
|
|
{
|
|
rt_logf("%s cond broadcast\n", rt_task_name());
|
|
rt_sem_post_n(&cond->sem, INT_MAX);
|
|
}
|
|
|
|
void rt_cond_wait(struct rt_cond *cond, struct rt_mutex *mutex)
|
|
{
|
|
/* Decrement the semaphore while still holding the mutex so that
|
|
* signals from higher priority tasks on the same monitor can see
|
|
* there is a waiter. */
|
|
const int value =
|
|
rt_atomic_fetch_sub(&cond->sem.value, 1, RT_ATOMIC_ACQUIRE);
|
|
|
|
rt_logf("%s cond wait, new value %d\n", rt_task_name(), value - 1);
|
|
|
|
if (value > 0)
|
|
{
|
|
/* The condition was signaled after the caller evaluated the predicate,
|
|
* so let the caller re-evaluate it without releasing the mutex. */
|
|
return;
|
|
}
|
|
|
|
rt_mutex_unlock(mutex);
|
|
rt_logf("%s cond wait, waiting\n", rt_task_name());
|
|
rt_syscall_sem_wait(&cond->sem);
|
|
rt_logf("%s cond wait, awoken\n", rt_task_name());
|
|
rt_mutex_lock(mutex);
|
|
}
|
|
|
|
bool rt_cond_timedwait(struct rt_cond *cond, struct rt_mutex *mutex,
|
|
unsigned long ticks)
|
|
{
|
|
unsigned long start_tick = rt_tick_count();
|
|
const int value =
|
|
rt_atomic_fetch_sub(&cond->sem.value, 1, RT_ATOMIC_ACQUIRE);
|
|
rt_logf("%s cond wait, new value %d\n", rt_task_name(), value - 1);
|
|
if (value > 0)
|
|
{
|
|
return true;
|
|
}
|
|
rt_mutex_unlock(mutex);
|
|
if ((ticks == 0) || !rt_syscall_sem_timedwait(&cond->sem, ticks))
|
|
{
|
|
return false;
|
|
}
|
|
rt_tick_elapse(&ticks, &start_tick);
|
|
return rt_mutex_timedlock(mutex, ticks);
|
|
}
|