2017-10-03 22:31:55 +08:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2010-2015 Wind River Systems, Inc.
|
|
|
|
* Copyright (c) 2017 Oticon A/S
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @brief Kernel swapper code for POSIX
|
|
|
|
*
|
|
|
|
* This module implements the __swap() routine for the POSIX architecture.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kernel.h"
|
|
|
|
#include <kernel_structs.h>
|
|
|
|
#include "posix_core.h"
|
|
|
|
#include "irq.h"
|
2018-08-02 18:54:21 +08:00
|
|
|
#include "kswap.h"
|
2017-10-03 22:31:55 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @brief Initiate a cooperative context switch
|
|
|
|
*
|
|
|
|
* The __swap() routine is invoked by various kernel services to effect
|
|
|
|
* a cooperative context switch. Prior to invoking __swap(), the
|
|
|
|
* caller disables interrupts (via irq_lock) and the return 'key'
|
|
|
|
* is passed as a parameter to __swap().
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @return -EAGAIN, or a return value set by a call to
|
|
|
|
* _set_thread_return_value()
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-09-12 09:33:37 +08:00
|
|
|
int __swap(unsigned int key)
|
2017-10-03 22:31:55 +08:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* struct k_thread * _kernel.current is the currently runnig thread
|
|
|
|
* struct k_thread * _kernel.ready_q.cache contains the next thread to run
|
|
|
|
* (cannot be NULL)
|
|
|
|
*
|
|
|
|
* Here a "real" arch would save all processor registers, stack pointer and so
|
|
|
|
* forth.
|
|
|
|
* But we do not need to do so because we use posix threads => those are all
|
|
|
|
* nicely kept by the native OS kernel
|
|
|
|
*/
|
|
|
|
_kernel.current->callee_saved.key = key;
|
|
|
|
_kernel.current->callee_saved.retval = -EAGAIN;
|
|
|
|
/* retval may be modified with a call to _set_thread_return_value() */
|
|
|
|
|
2018-04-06 09:06:33 +08:00
|
|
|
z_sys_trace_thread_switched_in();
|
2017-10-03 22:31:55 +08:00
|
|
|
|
|
|
|
posix_thread_status_t *ready_thread_ptr =
|
|
|
|
(posix_thread_status_t *)
|
|
|
|
_kernel.ready_q.cache->callee_saved.thread_status;
|
|
|
|
|
|
|
|
posix_thread_status_t *this_thread_ptr =
|
|
|
|
(posix_thread_status_t *)
|
|
|
|
_kernel.current->callee_saved.thread_status;
|
|
|
|
|
|
|
|
|
|
|
|
_kernel.current = _kernel.ready_q.cache;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Here a "real" arch would load all processor registers for the thread
|
|
|
|
* to run. In this arch case, we just block this thread until allowed to
|
|
|
|
* run later, and signal to whomever is allowed to run to continue.
|
|
|
|
*/
|
|
|
|
posix_swap(ready_thread_ptr->thread_idx,
|
|
|
|
this_thread_ptr->thread_idx);
|
|
|
|
|
|
|
|
/* When we continue, _kernel->current points back to this thread */
|
|
|
|
|
|
|
|
irq_unlock(_kernel.current->callee_saved.key);
|
|
|
|
|
|
|
|
return _kernel.current->callee_saved.retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef CONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAIN
|
|
|
|
/**
|
|
|
|
* This is just a version of __swap() in which we do not save anything about the
|
|
|
|
* current thread.
|
|
|
|
*
|
|
|
|
* Note that we will never come back to this thread:
|
|
|
|
* posix_core_main_thread_start() does never return
|
|
|
|
*/
|
|
|
|
void _arch_switch_to_main_thread(struct k_thread *main_thread,
|
|
|
|
k_thread_stack_t *main_stack,
|
|
|
|
size_t main_stack_size, k_thread_entry_t _main)
|
|
|
|
{
|
|
|
|
posix_thread_status_t *ready_thread_ptr =
|
|
|
|
(posix_thread_status_t *)
|
|
|
|
_kernel.ready_q.cache->callee_saved.thread_status;
|
|
|
|
_kernel.current = _kernel.ready_q.cache;
|
|
|
|
|
|
|
|
posix_main_thread_start(ready_thread_ptr->thread_idx);
|
2018-02-08 00:28:43 +08:00
|
|
|
} /* LCOV_EXCL_LINE */
|
2017-10-03 22:31:55 +08:00
|
|
|
#endif
|
|
|
|
|
2018-02-06 21:24:27 +08:00
|
|
|
#ifdef CONFIG_SYS_POWER_MANAGEMENT
|
|
|
|
/**
|
|
|
|
* If the kernel is in idle mode, take it out
|
|
|
|
*/
|
|
|
|
void posix_irq_check_idle_exit(void)
|
|
|
|
{
|
|
|
|
if (_kernel.idle) {
|
|
|
|
s32_t idle_val = _kernel.idle;
|
|
|
|
|
|
|
|
_kernel.idle = 0;
|
|
|
|
_sys_power_save_idle_exit(idle_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|