forked from RIOT-OS/RIOT
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cond.c
88 lines (74 loc) · 1.93 KB
/
cond.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
* Copyright (C) 2016 Sam Kumar <[email protected]>
* 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 <[email protected]>
*
* @}
*/
#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_t *)sched_active_thread;
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);
}