blob: 2633b7d98e7d7d77807496dff8e457ef7afc4d36 [file]
/*
* Copyright The Zephyr Project Contributors
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <ksched.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/spinlock.h>
#include <zephyr/internal/syscall_handler.h>
#include <run_q.h>
#include <wait_q.h>
#include <scheduler.h>
void z_sched_init(void)
{
#ifdef CONFIG_SCHED_CPU_MASK_PIN_ONLY
for (int i = 0; i < CONFIG_MP_MAX_NUM_CPUS; i++) {
_priq_run_init(&_kernel.cpus[i].ready_q.runq);
}
#else
_priq_run_init(&_kernel.ready_q.runq);
#endif /* CONFIG_SCHED_CPU_MASK_PIN_ONLY */
}
void k_sched_lock(void)
{
K_SPINLOCK(&_sched_spinlock) {
SYS_PORT_TRACING_FUNC(k_thread, sched_lock);
__ASSERT(!arch_is_in_isr(), "");
__ASSERT(_current->base.sched_locked != 1U, "");
--_current->base.sched_locked;
compiler_barrier();
}
}
void k_sched_unlock(void)
{
SYS_PORT_TRACING_FUNC(k_thread, sched_unlock);
k_spinlock_key_t key = k_spin_lock(&_sched_spinlock);
__ASSERT(_current->base.sched_locked != 0U, "");
__ASSERT(!arch_is_in_isr(), "");
++_current->base.sched_locked;
z_sched_lock_reschedule(key);
}
void z_impl_k_reschedule(void)
{
k_spinlock_key_t key;
key = k_spin_lock(&_sched_spinlock);
z_sched_lock_reschedule(key);
}
#ifdef CONFIG_USERSPACE
static inline void z_vrfy_k_reschedule(void)
{
z_impl_k_reschedule();
}
#include <zephyr/syscalls/k_reschedule_mrsh.c>
#endif /* CONFIG_USERSPACE */
k_tid_t z_impl_k_sched_current_thread_query(void)
{
return _current;
}
#ifdef CONFIG_USERSPACE
static inline k_tid_t z_vrfy_k_sched_current_thread_query(void)
{
return z_impl_k_sched_current_thread_query();
}
#include <zephyr/syscalls/k_sched_current_thread_query_mrsh.c>
#endif /* CONFIG_USERSPACE */
int z_sched_waitq_walk(_wait_q_t *wait_q, _waitq_walk_cb_t walk_func,
_waitq_post_walk_cb_t post_func, void *data)
{
struct k_thread *thread;
int status = 0;
K_SPINLOCK(&_sched_spinlock) {
#ifndef CONFIG_WAITQ_SCALABLE
struct k_thread *tmp;
_WAIT_Q_FOR_EACH_SAFE(wait_q, thread, tmp)
#else /* !CONFIG_WAITQ_SCALABLE */
_WAIT_Q_FOR_EACH(wait_q, thread)
#endif /* !CONFIG_WAITQ_SCALABLE */
{
/*
* Invoke the callback function on each waiting thread
* for as long as there are both waiting threads AND
* it returns 0.
*/
status = walk_func(thread, data);
if (status != 0) {
break;
}
}
/*
* Invoke post-walk callback. This is done while
* still holding _sched_spinlock to enable atomic
* operations (from the scheduler's point of view).
*/
if (post_func != NULL) {
post_func(status, data);
}
}
return status;
}
/*
* future scheduler.h API implementations
*/
bool z_sched_wake(_wait_q_t *wait_q, int swap_retval, void *swap_data)
{
struct k_thread *thread;
bool ret = false;
K_SPINLOCK(&_sched_spinlock) {
thread = _priq_wait_best(&wait_q->waitq);
if (thread != NULL) {
z_thread_return_value_set_with_data(thread,
swap_retval,
swap_data);
unpend_thread_no_timeout(thread);
z_abort_thread_timeout(thread);
z_sched_ready_locked(thread);
ret = true;
}
}
return ret;
}
int z_sched_wait(struct k_spinlock *lock, k_spinlock_key_t key,
_wait_q_t *wait_q, k_timeout_t timeout, void **data)
{
int ret = z_pend_curr(lock, key, wait_q, timeout);
if (data != NULL) {
*data = _current->base.swap_data;
}
return ret;
}