blob: c360233b377b2a9e6de887058b9562a146f1e9bd [file] [edit]
/*
* Copyright The Zephyr Project Contributors
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <kspinlock.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)
{
Z_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 = z_sched_spinlock_lock();
__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 = z_sched_spinlock_lock();
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;
Z_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 the scheduler 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
*/
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;
}