Boot Linux faster!

Check our new training course

Boot Linux faster!

Check our new training course
and Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

 * Copyright (c) 2018 Linaro, Limited
 * SPDX-License-Identifier: Apache-2.0

#include <kernel.h>
#include <toolchain.h>
#include <kernel_structs.h>

extern void read_timer_start_of_swap(void);
extern const int _k_neg_eagain;

 * @brief Initiate a cooperative context switch
 * The __swap() routine is invoked by various kernel services to effect
 * a cooperative context context switch.  Prior to invoking __swap(), the caller
 * disables interrupts via irq_lock() and the return 'key' is passed as a
 * parameter to __swap().  The 'key' actually represents the BASEPRI register
 * prior to disabling interrupts via the BASEPRI mechanism.
 * __swap() itself does not do much.
 * It simply stores the intlock key (the BASEPRI value) parameter into
 * current->basepri, and then triggers a PendSV exception, which does
 * the heavy lifting of context switching.

 * This is the only place we have to save BASEPRI since the other paths to
 * __pendsv all come from handling an interrupt, which means we know the
 * interrupts were not locked: in that case the BASEPRI value is 0.
 * Given that __swap() is called to effect a cooperative context switch,
 * only the caller-saved integer registers need to be saved in the thread of the
 * outgoing thread. This is all performed by the hardware, which stores it in
 * its exception stack frame, created when handling the __pendsv exception.
 * On ARMv6-M, the intlock key is represented by the PRIMASK register,
 * as BASEPRI is not available.
 * @return -EAGAIN, or a return value set by a call to
 * z_set_thread_return_value()
int __swap(int key)
	/* Save off current privilege mode */
	_current->arch.mode = __get_CONTROL() & CONTROL_nPRIV_Msk;

	/* store off key and return value */
	_current->arch.basepri = key;
	_current->arch.swap_return_value = _k_neg_eagain;

	/* set pending bit to make sure we will take a PendSV exception */

	/* clear mask or enable all irqs to take a pendsv */

	return _current->arch.swap_return_value;