You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
4.0 KiB
163 lines
4.0 KiB
/* |
|
* Copyright (c) 2020 Intel Corporation. |
|
* |
|
* SPDX-License-Identifier: Apache-2.0 |
|
*/ |
|
|
|
#include <zephyr/kernel.h> |
|
#include <zephyr/kernel_structs.h> |
|
#include <zephyr/toolchain.h> |
|
#include <ksched.h> |
|
#include <wait_q.h> |
|
#include <zephyr/internal/syscall_handler.h> |
|
#include <zephyr/init.h> |
|
|
|
#ifdef CONFIG_OBJ_CORE_CONDVAR |
|
static struct k_obj_type obj_type_condvar; |
|
#endif /* CONFIG_OBJ_CORE_CONDVAR */ |
|
|
|
static struct k_spinlock lock; |
|
|
|
int z_impl_k_condvar_init(struct k_condvar *condvar) |
|
{ |
|
z_waitq_init(&condvar->wait_q); |
|
k_object_init(condvar); |
|
|
|
#ifdef CONFIG_OBJ_CORE_CONDVAR |
|
k_obj_core_init_and_link(K_OBJ_CORE(condvar), &obj_type_condvar); |
|
#endif /* CONFIG_OBJ_CORE_CONDVAR */ |
|
|
|
SYS_PORT_TRACING_OBJ_INIT(k_condvar, condvar, 0); |
|
|
|
return 0; |
|
} |
|
|
|
#ifdef CONFIG_USERSPACE |
|
int z_vrfy_k_condvar_init(struct k_condvar *condvar) |
|
{ |
|
K_OOPS(K_SYSCALL_OBJ_INIT(condvar, K_OBJ_CONDVAR)); |
|
return z_impl_k_condvar_init(condvar); |
|
} |
|
#include <zephyr/syscalls/k_condvar_init_mrsh.c> |
|
#endif /* CONFIG_USERSPACE */ |
|
|
|
int z_impl_k_condvar_signal(struct k_condvar *condvar) |
|
{ |
|
k_spinlock_key_t key = k_spin_lock(&lock); |
|
|
|
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, signal, condvar); |
|
|
|
struct k_thread *thread = z_unpend_first_thread(&condvar->wait_q); |
|
|
|
if (unlikely(thread != NULL)) { |
|
SYS_PORT_TRACING_OBJ_FUNC_BLOCKING(k_condvar, signal, condvar, K_FOREVER); |
|
|
|
arch_thread_return_value_set(thread, 0); |
|
z_ready_thread(thread); |
|
z_reschedule(&lock, key); |
|
} else { |
|
k_spin_unlock(&lock, key); |
|
} |
|
|
|
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, signal, condvar, 0); |
|
|
|
return 0; |
|
} |
|
|
|
#ifdef CONFIG_USERSPACE |
|
int z_vrfy_k_condvar_signal(struct k_condvar *condvar) |
|
{ |
|
K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); |
|
return z_impl_k_condvar_signal(condvar); |
|
} |
|
#include <zephyr/syscalls/k_condvar_signal_mrsh.c> |
|
#endif /* CONFIG_USERSPACE */ |
|
|
|
int z_impl_k_condvar_broadcast(struct k_condvar *condvar) |
|
{ |
|
struct k_thread *pending_thread; |
|
k_spinlock_key_t key; |
|
int woken = 0; |
|
|
|
key = k_spin_lock(&lock); |
|
|
|
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, broadcast, condvar); |
|
|
|
/* wake up any threads that are waiting to write */ |
|
for (pending_thread = z_unpend_first_thread(&condvar->wait_q); pending_thread != NULL; |
|
pending_thread = z_unpend_first_thread(&condvar->wait_q)) { |
|
woken++; |
|
arch_thread_return_value_set(pending_thread, 0); |
|
z_ready_thread(pending_thread); |
|
} |
|
|
|
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, broadcast, condvar, woken); |
|
|
|
|
|
if (woken == 0) { |
|
k_spin_unlock(&lock, key); |
|
} else { |
|
z_reschedule(&lock, key); |
|
} |
|
|
|
return woken; |
|
} |
|
#ifdef CONFIG_USERSPACE |
|
int z_vrfy_k_condvar_broadcast(struct k_condvar *condvar) |
|
{ |
|
K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); |
|
return z_impl_k_condvar_broadcast(condvar); |
|
} |
|
#include <zephyr/syscalls/k_condvar_broadcast_mrsh.c> |
|
#endif /* CONFIG_USERSPACE */ |
|
|
|
int z_impl_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, |
|
k_timeout_t timeout) |
|
{ |
|
k_spinlock_key_t key; |
|
int ret; |
|
|
|
SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, wait, condvar); |
|
|
|
key = k_spin_lock(&lock); |
|
k_mutex_unlock(mutex); |
|
|
|
ret = z_pend_curr(&lock, key, &condvar->wait_q, timeout); |
|
k_mutex_lock(mutex, K_FOREVER); |
|
|
|
SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_condvar, wait, condvar, ret); |
|
|
|
return ret; |
|
} |
|
#ifdef CONFIG_USERSPACE |
|
int z_vrfy_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, |
|
k_timeout_t timeout) |
|
{ |
|
K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); |
|
K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); |
|
return z_impl_k_condvar_wait(condvar, mutex, timeout); |
|
} |
|
#include <zephyr/syscalls/k_condvar_wait_mrsh.c> |
|
#endif /* CONFIG_USERSPACE */ |
|
|
|
#ifdef CONFIG_OBJ_CORE_CONDVAR |
|
static int init_condvar_obj_core_list(void) |
|
{ |
|
/* Initialize condvar object type */ |
|
|
|
z_obj_type_init(&obj_type_condvar, K_OBJ_TYPE_CONDVAR_ID, |
|
offsetof(struct k_condvar, obj_core)); |
|
|
|
/* Initialize and link statically defined condvars */ |
|
|
|
STRUCT_SECTION_FOREACH(k_condvar, condvar) { |
|
k_obj_core_init_and_link(K_OBJ_CORE(condvar), |
|
&obj_type_condvar); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
SYS_INIT(init_condvar_obj_core_list, PRE_KERNEL_1, |
|
CONFIG_KERNEL_INIT_PRIORITY_OBJECTS); |
|
#endif /* CONFIG_OBJ_CORE_CONDVAR */
|
|
|