blob: 3ec3b05d2f6ebac97b81ae0499b5835c301344bf [file] [log] [blame]
Wentong Wu5611e922019-06-20 23:51:27 +08001/*
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
15static struct z_futex_data *k_futex_find_data(struct k_futex *futex)
16{
Andrew Boie2dc2ecf2020-03-11 07:13:07 -070017 struct z_object *obj;
Wentong Wu5611e922019-06-20 23:51:27 +080018
19 obj = z_object_find(futex);
20 if (obj == NULL || obj->type != K_OBJ_FUTEX) {
21 return NULL;
22 }
23
Andrew Boief2734ab2020-03-11 06:37:42 -070024 return obj->data.futex_data;
Wentong Wu5611e922019-06-20 23:51:27 +080025}
26
Wentong Wu5611e922019-06-20 23:51:27 +080027int z_impl_k_futex_wake(struct k_futex *futex, bool wake_all)
28{
29 k_spinlock_key_t key;
30 unsigned int woken = 0;
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) {
44 z_ready_thread(thread);
Andrew Boie4f77c2a2019-11-07 12:43:29 -080045 arch_thread_return_value_set(thread, 0);
Wentong Wu5611e922019-06-20 23:51:27 +080046 woken++;
47 }
48 } while (thread && wake_all);
49
50 z_reschedule(&futex_data->lock, key);
51
52 return woken;
53}
54
Andy Ross65649742019-08-06 13:34:31 -070055static inline int z_vrfy_k_futex_wake(struct k_futex *futex, bool wake_all)
Wentong Wu5611e922019-06-20 23:51:27 +080056{
57 if (Z_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) {
58 return -EACCES;
59 }
60
Andy Ross65649742019-08-06 13:34:31 -070061 return z_impl_k_futex_wake(futex, wake_all);
Wentong Wu5611e922019-06-20 23:51:27 +080062}
Andy Ross65649742019-08-06 13:34:31 -070063#include <syscalls/k_futex_wake_mrsh.c>
Wentong Wu5611e922019-06-20 23:51:27 +080064
65int z_impl_k_futex_wait(struct k_futex *futex, int expected, s32_t timeout)
66{
67 int ret;
68 k_spinlock_key_t key;
69 struct z_futex_data *futex_data;
70
71 futex_data = k_futex_find_data(futex);
72 if (futex_data == NULL) {
73 return -EINVAL;
74 }
75
76 key = k_spin_lock(&futex_data->lock);
77
78 if (atomic_get(&futex->val) != (atomic_val_t)expected) {
79 k_spin_unlock(&futex_data->lock, key);
80 return -EAGAIN;
81 }
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
Andy Ross643701a2019-08-13 12:58:38 -070092static inline int z_vrfy_k_futex_wait(struct k_futex *futex, int expected,
93 s32_t timeout)
Wentong Wu5611e922019-06-20 23:51:27 +080094{
95 if (Z_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) {
96 return -EACCES;
97 }
98
Andy Ross65649742019-08-06 13:34:31 -070099 return z_impl_k_futex_wait(futex, expected, timeout);
Wentong Wu5611e922019-06-20 23:51:27 +0800100}
Andy Ross65649742019-08-06 13:34:31 -0700101#include <syscalls/k_futex_wait_mrsh.c>