1 /*
2 * Copyright (c) 2020 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <kernel.h>
8 #include <kernel_structs.h>
9 #include <toolchain.h>
10 #include <ksched.h>
11 #include <wait_q.h>
12 #include <syscall_handler.h>
13
14 static struct k_spinlock lock;
15
z_impl_k_condvar_init(struct k_condvar * condvar)16 int z_impl_k_condvar_init(struct k_condvar *condvar)
17 {
18 z_waitq_init(&condvar->wait_q);
19 z_object_init(condvar);
20
21 SYS_PORT_TRACING_OBJ_INIT(k_condvar, condvar, 0);
22
23 return 0;
24 }
25
26 #ifdef CONFIG_USERSPACE
z_vrfy_k_condvar_init(struct k_condvar * condvar)27 int z_vrfy_k_condvar_init(struct k_condvar *condvar)
28 {
29 Z_OOPS(Z_SYSCALL_OBJ_INIT(condvar, K_OBJ_CONDVAR));
30 return z_impl_k_condvar_init(condvar);
31 }
32 #include <syscalls/k_condvar_init_mrsh.c>
33 #endif
34
z_impl_k_condvar_signal(struct k_condvar * condvar)35 int z_impl_k_condvar_signal(struct k_condvar *condvar)
36 {
37 k_spinlock_key_t key = k_spin_lock(&lock);
38
39 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, signal, condvar);
40
41 struct k_thread *thread = z_unpend_first_thread(&condvar->wait_q);
42
43 if (thread != NULL) {
44 SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_condvar, signal, condvar, K_FOREVER);
45
46 arch_thread_return_value_set(thread, 0);
47 z_ready_thread(thread);
48 z_reschedule(&lock, key);
49 } else {
50 k_spin_unlock(&lock, key);
51 }
52
53 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, signal, condvar, 0);
54
55 return 0;
56 }
57
58 #ifdef CONFIG_USERSPACE
z_vrfy_k_condvar_signal(struct k_condvar * condvar)59 int z_vrfy_k_condvar_signal(struct k_condvar *condvar)
60 {
61 Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR));
62 return z_impl_k_condvar_signal(condvar);
63 }
64 #include <syscalls/k_condvar_signal_mrsh.c>
65 #endif
66
z_impl_k_condvar_broadcast(struct k_condvar * condvar)67 int z_impl_k_condvar_broadcast(struct k_condvar *condvar)
68 {
69 struct k_thread *pending_thread;
70 k_spinlock_key_t key;
71 int woken = 0;
72
73 key = k_spin_lock(&lock);
74
75 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, broadcast, condvar);
76
77 /* wake up any threads that are waiting to write */
78 while ((pending_thread = z_unpend_first_thread(&condvar->wait_q)) !=
79 NULL) {
80 woken++;
81 arch_thread_return_value_set(pending_thread, 0);
82 z_ready_thread(pending_thread);
83 }
84
85 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, broadcast, condvar, woken);
86
87 z_reschedule(&lock, key);
88
89 return woken;
90 }
91 #ifdef CONFIG_USERSPACE
z_vrfy_k_condvar_broadcast(struct k_condvar * condvar)92 int z_vrfy_k_condvar_broadcast(struct k_condvar *condvar)
93 {
94 Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR));
95 return z_impl_k_condvar_broadcast(condvar);
96 }
97 #include <syscalls/k_condvar_broadcast_mrsh.c>
98 #endif
99
z_impl_k_condvar_wait(struct k_condvar * condvar,struct k_mutex * mutex,k_timeout_t timeout)100 int z_impl_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex,
101 k_timeout_t timeout)
102 {
103 k_spinlock_key_t key;
104 int ret;
105
106 SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, wait, condvar);
107
108 key = k_spin_lock(&lock);
109 k_mutex_unlock(mutex);
110
111 ret = z_pend_curr(&lock, key, &condvar->wait_q, timeout);
112 k_mutex_lock(mutex, K_FOREVER);
113
114 SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, wait, condvar, ret);
115
116 return ret;
117 }
118 #ifdef CONFIG_USERSPACE
z_vrfy_k_condvar_wait(struct k_condvar * condvar,struct k_mutex * mutex,k_timeout_t timeout)119 int z_vrfy_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex,
120 k_timeout_t timeout)
121 {
122 Z_OOPS(Z_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR));
123 Z_OOPS(Z_SYSCALL_OBJ(mutex, K_OBJ_MUTEX));
124 return z_impl_k_condvar_wait(condvar, mutex, timeout);
125 }
126 #include <syscalls/k_condvar_wait_mrsh.c>
127 #endif
128