/* SPDX-License-Identifier: BSD-2-Clause */ /** * @file * * @ingroup RTEMSScoreScheduler * * @brief This header file provides interfaces of the supporting the * implementation of uniprocessor schedulers. */ /* * Copyright (C) 2010 Gedare Bloom. * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). * Copyright (C) 2014, 2022 embedded brains GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RTEMS_SCORE_SCHEDULERUNIIMPL_H #define _RTEMS_SCORE_SCHEDULERUNIIMPL_H #include #ifdef __cplusplus extern "C" { #endif /** * @addtogroup RTEMSScoreScheduler * * @{ */ /** * @brief Updates the heir thread of the processor. * * @param[in, out] heir is the current heir thread. * @param[in, out] new_heir is the new heir thread. */ RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Update_heir( Thread_Control *heir, Thread_Control *new_heir ) { _Assert( heir != new_heir ); #if defined(RTEMS_SMP) /* * We need this state only for _Thread_Get_CPU_time_used_locked(). Cannot * use _Scheduler_Thread_change_state() since THREAD_SCHEDULER_BLOCKED to * THREAD_SCHEDULER_BLOCKED state changes are illegal for the real SMP * schedulers. */ heir->Scheduler.state = THREAD_SCHEDULER_BLOCKED; new_heir->Scheduler.state = THREAD_SCHEDULER_SCHEDULED; #endif _Thread_Update_CPU_time_used( heir, _Thread_Get_CPU( heir ) ); _Thread_Heir = new_heir; _Thread_Dispatch_necessary = true; } /** * @brief Updates the heir thread of the processor if the current heir is * not equal to the new heir thread. * * The update takes place even if the current heir thread is not preemptible. * * @param[in, out] new_heir is the new heir thread. */ RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Update_heir_if_necessary( Thread_Control *new_heir ) { Thread_Control *heir = _Thread_Heir; if ( heir != new_heir ) { _Scheduler_uniprocessor_Update_heir( heir, new_heir ); } } /** * @brief Updates the heir thread of the processor if the current heir thread * is preemptible. * * @param[in, out] heir is the current heir thread. * @param[in, out] new_heir is the new heir thread. */ RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Update_heir_if_preemptible( Thread_Control *heir, Thread_Control *new_heir ) { if ( heir != new_heir && heir->is_preemptible ) { _Scheduler_uniprocessor_Update_heir( heir, new_heir ); } } /** * @brief Blocks the thread. * * @param scheduler is the scheduler. * @param the_thread is the thread to block. * @param node is the scheduler node of the thread. * @param extract is the handler to extract the thread. * @param get_highest_ready is the handler to get the highest ready thread. */ RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Block( const Scheduler_Control *scheduler, Thread_Control *the_thread, Scheduler_Node *node, void ( *extract )( const Scheduler_Control *, Thread_Control *, Scheduler_Node * ), Thread_Control *( *get_highest_ready )( const Scheduler_Control * ) ) { ( *extract )( scheduler, the_thread, node ); /* TODO: flash critical section? */ if ( _Thread_Is_heir( the_thread ) ) { Thread_Control *highest_ready; highest_ready = ( *get_highest_ready )( scheduler ); _Scheduler_uniprocessor_Update_heir( _Thread_Heir, highest_ready ); } } /** * @brief Schedule the unblocked thread if it is the highest ready thread. * * @param scheduler is the scheduler. * @param the_thread is the thread. * @param priority is the priority of the thread. */ RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Unblock( const Scheduler_Control *scheduler, Thread_Control *the_thread, Priority_Control priority ) { Thread_Control *heir; heir = _Thread_Heir; /* * If the thread is more important than the heir, then we have a new heir. * This may or may not result in a context switch. If the current heir * thread is preemptible, then we need to do a context switch. */ if ( priority < _Thread_Get_priority( heir ) ) { _Scheduler_uniprocessor_Update_heir_if_preemptible( heir, the_thread ); } } /** * @brief Schedules the highest ready thread if the current heir thread of the * processor is preemptible. * * @param scheduler is the scheduler. * @param get_highest_ready is the handler to get the highest ready thread. */ RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Schedule( const Scheduler_Control *scheduler, Thread_Control *( *get_highest_ready )( const Scheduler_Control * ) ) { Thread_Control *highest_ready; highest_ready = ( *get_highest_ready )( scheduler ); _Scheduler_uniprocessor_Update_heir_if_preemptible( _Thread_Heir, highest_ready ); } /** * @brief Yields to the highest ready thread. * * @param scheduler is the scheduler. * @param get_highest_ready is the handler to get the highest ready thread. */ RTEMS_INLINE_ROUTINE void _Scheduler_uniprocessor_Yield( const Scheduler_Control *scheduler, Thread_Control *( *get_highest_ready )( const Scheduler_Control * ) ) { Thread_Control *highest_ready; highest_ready = ( *get_highest_ready )( scheduler ); _Scheduler_uniprocessor_Update_heir_if_necessary( highest_ready ); } /** @} */ #ifdef __cplusplus } #endif #endif /* _RTEMS_SCORE_SCHEDULERUNIIMPL_H */