1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 00:09:46 +01:00
RIOT/core/cond.c
2020-10-23 00:45:56 +02:00

89 lines
1.9 KiB
C

/*
* Copyright (C) 2016 Sam Kumar <samkumar@berkeley.edu>
* 2016 University of California, Berkeley
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup core_sync
* @{
*
* @file
* @brief Kernel condition variable implementation
*
* @author Sam Kumar <samkumar@berkeley.edu>
*
* @}
*/
#include "cond.h"
#include "irq.h"
#include "mutex.h"
#include "thread.h"
#define ENABLE_DEBUG 0
#include "debug.h"
void cond_init(cond_t *cond)
{
cond->queue.next = NULL;
}
void cond_wait(cond_t *cond, mutex_t *mutex)
{
unsigned irqstate = irq_disable();
thread_t *me = thread_get_active();
mutex_unlock(mutex);
sched_set_status(me, STATUS_COND_BLOCKED);
thread_add_to_list(&cond->queue, me);
irq_restore(irqstate);
thread_yield_higher();
/*
* Once we reach this point, the condition variable was signalled,
* and we are free to continue.
*/
mutex_lock(mutex);
}
static void _cond_signal(cond_t *cond, bool broadcast)
{
unsigned irqstate = irq_disable();
list_node_t *next;
uint16_t min_prio = THREAD_PRIORITY_MIN + 1;
while ((next = list_remove_head(&cond->queue)) != NULL) {
thread_t *process = container_of((clist_node_t *)next, thread_t,
rq_entry);
sched_set_status(process, STATUS_PENDING);
uint16_t process_priority = process->priority;
if (process_priority < min_prio) {
min_prio = process_priority;
}
if (!broadcast) {
break;
}
}
irq_restore(irqstate);
if (min_prio <= THREAD_PRIORITY_MIN) {
sched_switch(min_prio);
}
}
void cond_signal(cond_t *cond)
{
_cond_signal(cond, false);
}
void cond_broadcast(cond_t *cond)
{
_cond_signal(cond, true);
}