1 /*
2 * Copyright (c) 2019 Intel corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <kernel.h>
8 #include <kernel_structs.h>
9 #include <spinlock.h>
10 #include <kswap.h>
11 #include <syscall_handler.h>
12 #include <init.h>
13 #include <ksched.h>
14
k_futex_find_data(struct k_futex * futex)15 static struct z_futex_data *k_futex_find_data(struct k_futex *futex)
16 {
17 struct z_object *obj;
18
19 obj = z_object_find(futex);
20 if (obj == NULL || obj->type != K_OBJ_FUTEX) {
21 return NULL;
22 }
23
24 return obj->data.futex_data;
25 }
26
z_impl_k_futex_wake(struct k_futex * futex,bool wake_all)27 int z_impl_k_futex_wake(struct k_futex *futex, bool wake_all)
28 {
29 k_spinlock_key_t key;
30 unsigned int woken = 0U;
31 struct k_thread *thread;
32 struct z_futex_data *futex_data;
33
34 futex_data = k_futex_find_data(futex);
35 if (futex_data == NULL) {
36 return -EINVAL;
37 }
38
39 key = k_spin_lock(&futex_data->lock);
40
41 do {
42 thread = z_unpend_first_thread(&futex_data->wait_q);
43 if (thread != NULL) {
44 woken++;
45 arch_thread_return_value_set(thread, 0);
46 z_ready_thread(thread);
47 }
48 } while (thread && wake_all);
49
50 z_reschedule(&futex_data->lock, key);
51
52 return woken;
53 }
54
z_vrfy_k_futex_wake(struct k_futex * futex,bool wake_all)55 static inline int z_vrfy_k_futex_wake(struct k_futex *futex, bool wake_all)
56 {
57 if (Z_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) {
58 return -EACCES;
59 }
60
61 return z_impl_k_futex_wake(futex, wake_all);
62 }
63 #include <syscalls/k_futex_wake_mrsh.c>
64
z_impl_k_futex_wait(struct k_futex * futex,int expected,k_timeout_t timeout)65 int z_impl_k_futex_wait(struct k_futex *futex, int expected,
66 k_timeout_t timeout)
67 {
68 int ret;
69 k_spinlock_key_t key;
70 struct z_futex_data *futex_data;
71
72 futex_data = k_futex_find_data(futex);
73 if (futex_data == NULL) {
74 return -EINVAL;
75 }
76
77 if (atomic_get(&futex->val) != (atomic_val_t)expected) {
78 return -EAGAIN;
79 }
80
81 key = k_spin_lock(&futex_data->lock);
82
83 ret = z_pend_curr(&futex_data->lock,
84 key, &futex_data->wait_q, timeout);
85 if (ret == -EAGAIN) {
86 ret = -ETIMEDOUT;
87 }
88
89 return ret;
90 }
91
z_vrfy_k_futex_wait(struct k_futex * futex,int expected,k_timeout_t timeout)92 static inline int z_vrfy_k_futex_wait(struct k_futex *futex, int expected,
93 k_timeout_t timeout)
94 {
95 if (Z_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) {
96 return -EACCES;
97 }
98
99 return z_impl_k_futex_wait(futex, expected, timeout);
100 }
101 #include <syscalls/k_futex_wait_mrsh.c>
102