mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 00:09:46 +01:00
89 lines
1.9 KiB
C
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);
|
|
}
|