102 lines
2.1 KiB
C
102 lines
2.1 KiB
C
/*
|
|
* Copyright (c) 2019 Intel corporation
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <zephyr/kernel.h>
|
|
#include <zephyr/kernel_structs.h>
|
|
#include <zephyr/spinlock.h>
|
|
#include <kswap.h>
|
|
#include <zephyr/internal/syscall_handler.h>
|
|
#include <zephyr/init.h>
|
|
#include <ksched.h>
|
|
|
|
static struct z_futex_data *k_futex_find_data(struct k_futex *futex)
|
|
{
|
|
struct k_object *obj;
|
|
|
|
obj = k_object_find(futex);
|
|
if (obj == NULL || obj->type != K_OBJ_FUTEX) {
|
|
return NULL;
|
|
}
|
|
|
|
return obj->data.futex_data;
|
|
}
|
|
|
|
int z_impl_k_futex_wake(struct k_futex *futex, bool wake_all)
|
|
{
|
|
k_spinlock_key_t key;
|
|
unsigned int woken = 0U;
|
|
struct k_thread *thread;
|
|
struct z_futex_data *futex_data;
|
|
|
|
futex_data = k_futex_find_data(futex);
|
|
if (futex_data == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
key = k_spin_lock(&futex_data->lock);
|
|
|
|
do {
|
|
thread = z_unpend_first_thread(&futex_data->wait_q);
|
|
if (thread != NULL) {
|
|
woken++;
|
|
arch_thread_return_value_set(thread, 0);
|
|
z_ready_thread(thread);
|
|
}
|
|
} while (thread && wake_all);
|
|
|
|
z_reschedule(&futex_data->lock, key);
|
|
|
|
return woken;
|
|
}
|
|
|
|
static inline int z_vrfy_k_futex_wake(struct k_futex *futex, bool wake_all)
|
|
{
|
|
if (K_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) {
|
|
return -EACCES;
|
|
}
|
|
|
|
return z_impl_k_futex_wake(futex, wake_all);
|
|
}
|
|
#include <syscalls/k_futex_wake_mrsh.c>
|
|
|
|
int z_impl_k_futex_wait(struct k_futex *futex, int expected,
|
|
k_timeout_t timeout)
|
|
{
|
|
int ret;
|
|
k_spinlock_key_t key;
|
|
struct z_futex_data *futex_data;
|
|
|
|
futex_data = k_futex_find_data(futex);
|
|
if (futex_data == NULL) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
if (atomic_get(&futex->val) != (atomic_val_t)expected) {
|
|
return -EAGAIN;
|
|
}
|
|
|
|
key = k_spin_lock(&futex_data->lock);
|
|
|
|
ret = z_pend_curr(&futex_data->lock,
|
|
key, &futex_data->wait_q, timeout);
|
|
if (ret == -EAGAIN) {
|
|
ret = -ETIMEDOUT;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static inline int z_vrfy_k_futex_wait(struct k_futex *futex, int expected,
|
|
k_timeout_t timeout)
|
|
{
|
|
if (K_SYSCALL_MEMORY_WRITE(futex, sizeof(struct k_futex)) != 0) {
|
|
return -EACCES;
|
|
}
|
|
|
|
return z_impl_k_futex_wait(futex, expected, timeout);
|
|
}
|
|
#include <syscalls/k_futex_wait_mrsh.c>
|