Add call to _Scheduler_Schedule() in missing path after _Thread_Set_transient() in _Thread_Change_priority(). See also sptests/spintrcritical19.
Add thread parameter to _Scheduler_Schedule(). This parameter is currently unused but may be used in future SMP schedulers. Do heir selection in _Scheduler_Schedule(). Use _Scheduler_Update_heir() for this in the particular scheduler implementation. Add and use _Scheduler_Generic_block(). --- cpukit/score/Makefile.am | 1 + cpukit/score/include/rtems/score/scheduler.h | 2 +- cpukit/score/include/rtems/score/scheduleredf.h | 2 +- .../score/include/rtems/score/scheduleredfimpl.h | 56 ++++++++++++++++++++ cpukit/score/include/rtems/score/schedulerimpl.h | 35 ++++++++++++- .../score/include/rtems/score/schedulerpriority.h | 2 +- .../include/rtems/score/schedulerpriorityimpl.h | 12 ++++- cpukit/score/include/rtems/score/schedulersimple.h | 2 +- .../include/rtems/score/schedulersimpleimpl.h | 16 +++++- .../score/include/rtems/score/schedulersimplesmp.h | 2 +- cpukit/score/include/rtems/score/threadimpl.h | 10 ---- cpukit/score/preinstall.am | 4 ++ cpukit/score/src/scheduleredfblock.c | 17 ++---- cpukit/score/src/scheduleredfschedule.c | 12 +--- cpukit/score/src/scheduleredfyield.c | 9 +--- cpukit/score/src/schedulerpriorityblock.c | 16 ++---- cpukit/score/src/schedulerpriorityschedule.c | 4 +- cpukit/score/src/schedulersimpleblock.c | 15 ++--- cpukit/score/src/schedulersimpleschedule.c | 9 +-- cpukit/score/src/schedulersimplesmp.c | 4 +- cpukit/score/src/schedulersimpleyield.c | 5 +-- cpukit/score/src/threadchangepriority.c | 14 ++++-- 22 files changed, 164 insertions(+), 85 deletions(-) create mode 100644 cpukit/score/include/rtems/score/scheduleredfimpl.h diff --git a/cpukit/score/Makefile.am b/cpukit/score/Makefile.am index f3f76c5..584c53d 100644 --- a/cpukit/score/Makefile.am +++ b/cpukit/score/Makefile.am @@ -50,6 +50,7 @@ include_rtems_score_HEADERS += include/rtems/score/scheduler.h include_rtems_score_HEADERS += include/rtems/score/schedulerimpl.h include_rtems_score_HEADERS += include/rtems/score/schedulercbs.h include_rtems_score_HEADERS += include/rtems/score/scheduleredf.h +include_rtems_score_HEADERS += include/rtems/score/scheduleredfimpl.h include_rtems_score_HEADERS += include/rtems/score/schedulerpriority.h include_rtems_score_HEADERS += include/rtems/score/schedulerpriorityimpl.h include_rtems_score_HEADERS += include/rtems/score/schedulerprioritysmp.h diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h index a34387d..10a2a97 100644 --- a/cpukit/score/include/rtems/score/scheduler.h +++ b/cpukit/score/include/rtems/score/scheduler.h @@ -46,7 +46,7 @@ typedef struct { void ( *initialize )(void); /** Implements the scheduling decision logic (policy). */ - void ( *schedule )(void); + void ( *schedule )( Thread_Control *thread ); /** * @brief Voluntarily yields the processor per the scheduling policy. diff --git a/cpukit/score/include/rtems/score/scheduleredf.h b/cpukit/score/include/rtems/score/scheduleredf.h index b28bed1..01f91e6 100644 --- a/cpukit/score/include/rtems/score/scheduleredf.h +++ b/cpukit/score/include/rtems/score/scheduleredf.h @@ -129,7 +129,7 @@ void _Scheduler_EDF_Block( * This kernel routine sets the heir thread to be the next ready thread * in the rbtree ready queue. */ -void _Scheduler_EDF_Schedule( void ); +void _Scheduler_EDF_Schedule( Thread_Control *thread ); /** * @brief Allocates EDF specific information of @a the_thread. diff --git a/cpukit/score/include/rtems/score/scheduleredfimpl.h b/cpukit/score/include/rtems/score/scheduleredfimpl.h new file mode 100644 index 0000000..04201bc --- /dev/null +++ b/cpukit/score/include/rtems/score/scheduleredfimpl.h @@ -0,0 +1,56 @@ +/** + * @file + * + * @ingroup ScoreSchedulerEDF + * + * @brief EDF Scheduler Implementation + */ + +/* + * Copryight (c) 2011 Petr Benes. + * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef _RTEMS_SCORE_SCHEDULEREDFIMPL_H +#define _RTEMS_SCORE_SCHEDULEREDFIMPL_H + +#include <rtems/score/scheduleredf.h> +#include <rtems/score/schedulerimpl.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup ScoreSchedulerEDF EDF + * + * @{ + */ + +RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body( + Thread_Control *thread, + bool force_dispatch +) +{ + RBTree_Node *first = _RBTree_First(&_Scheduler_EDF_Ready_queue, RBT_LEFT); + Scheduler_EDF_Per_thread *sched_info = + _RBTree_Container_of(first, Scheduler_EDF_Per_thread, Node); + Thread_Control *heir = (Thread_Control *) sched_info->thread; + + ( void ) thread; + + _Scheduler_Update_heir( heir, force_dispatch ); +} + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif +/* end of include file */ diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 5ea4bb8..2d9957a 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -20,6 +20,7 @@ #define _RTEMS_SCORE_SCHEDULERIMPL_H #include <rtems/score/scheduler.h> +#include <rtems/score/threadimpl.h> #ifdef __cplusplus extern "C" { @@ -59,10 +60,12 @@ void _Scheduler_Handler_initialization( void ); * * This kernel routine implements the scheduling decision logic for * the scheduler. It does NOT dispatch. + * + * @param[in] thread The thread which state changed previously. */ -RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( void ) +RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( Thread_Control *thread ) { - _Scheduler.Operations.schedule(); + _Scheduler.Operations.schedule( thread ); } /** @@ -237,6 +240,34 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Start_idle( ( *_Scheduler.Operations.start_idle )( thread, processor ); } +RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir( + Thread_Control *heir, + bool force_dispatch +) +{ + Thread_Control *executing = _Thread_Executing; + + _Thread_Heir = heir; + + if ( executing != heir && ( force_dispatch || executing->is_preemptible ) ) + _Thread_Dispatch_necessary = true; +} + +RTEMS_INLINE_ROUTINE void _Scheduler_Generic_block( + void ( *extract )( Thread_Control *thread ), + void ( *schedule )( Thread_Control *thread, bool force_dispatch ), + Thread_Control *thread +) +{ + ( *extract )( thread ); + + /* TODO: flash critical section? */ + + if ( _Thread_Is_executing( thread ) || _Thread_Is_heir( thread ) ) { + ( *schedule )( thread, true ); + } +} + /** * Macro testing whether @a p1 has lower priority than @a p2 * in the intuitive sense of priority. diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h index 6964943..cbe0066 100644 --- a/cpukit/score/include/rtems/score/schedulerpriority.h +++ b/cpukit/score/include/rtems/score/schedulerpriority.h @@ -93,7 +93,7 @@ void _Scheduler_priority_Block( * This kernel routine sets the heir thread to be the next ready thread * by invoking the_scheduler->ready_queue->operations->first(). */ -void _Scheduler_priority_Schedule(void); +void _Scheduler_priority_Schedule( Thread_Control *thread ); /** * @brief Allocates @a the_thread->scheduler. diff --git a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h index b69a910..6c57952 100644 --- a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h +++ b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h @@ -23,6 +23,7 @@ #include <rtems/score/schedulerpriority.h> #include <rtems/score/chainimpl.h> #include <rtems/score/prioritybitmapimpl.h> +#include <rtems/score/schedulerimpl.h> #include <rtems/score/thread.h> #include <rtems/score/wkspace.h> @@ -188,11 +189,18 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_requeue( * This kernel routine implements scheduling decision logic * for priority-based scheduling. */ -RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body(void) +RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body( + Thread_Control *thread, + bool force_dispatch +) { - _Thread_Heir = _Scheduler_priority_Ready_queue_first( + Thread_Control *heir = _Scheduler_priority_Ready_queue_first( (Chain_Control *) _Scheduler.information ); + + ( void ) thread; + + _Scheduler_Update_heir( heir, force_dispatch ); } /** diff --git a/cpukit/score/include/rtems/score/schedulersimple.h b/cpukit/score/include/rtems/score/schedulersimple.h index 5180d36..477ea2c 100644 --- a/cpukit/score/include/rtems/score/schedulersimple.h +++ b/cpukit/score/include/rtems/score/schedulersimple.h @@ -66,7 +66,7 @@ void _Scheduler_simple_Initialize( void ); * on the ready queue by getting the first node in the scheduler * information. */ -void _Scheduler_simple_Schedule( void ); +void _Scheduler_simple_Schedule( Thread_Control *thread ); /** * @brief Invoked when a thread wishes to voluntarily diff --git a/cpukit/score/include/rtems/score/schedulersimpleimpl.h b/cpukit/score/include/rtems/score/schedulersimpleimpl.h index 076d1a9..51d3774 100644 --- a/cpukit/score/include/rtems/score/schedulersimpleimpl.h +++ b/cpukit/score/include/rtems/score/schedulersimpleimpl.h @@ -21,7 +21,7 @@ #include <rtems/score/schedulersimple.h> #include <rtems/score/chainimpl.h> -#include <rtems/score/thread.h> +#include <rtems/score/schedulerimpl.h> #ifdef __cplusplus extern "C" { @@ -96,6 +96,20 @@ RTEMS_INLINE_ROUTINE void _Scheduler_simple_Insert_priority_fifo( ); } +RTEMS_INLINE_ROUTINE void _Scheduler_simple_Schedule_body( + Thread_Control *thread, + bool force_dispatch +) +{ + Thread_Control *heir = (Thread_Control *) _Chain_First( + (Chain_Control *) _Scheduler.information + ); + + ( void ) thread; + + _Scheduler_Update_heir( heir, force_dispatch ); +} + /** @} */ #ifdef __cplusplus diff --git a/cpukit/score/include/rtems/score/schedulersimplesmp.h b/cpukit/score/include/rtems/score/schedulersimplesmp.h index 1b827cb..6cc87f3 100644 --- a/cpukit/score/include/rtems/score/schedulersimplesmp.h +++ b/cpukit/score/include/rtems/score/schedulersimplesmp.h @@ -85,7 +85,7 @@ void _Scheduler_simple_smp_Extract( Thread_Control *thread ); void _Scheduler_simple_smp_Yield( Thread_Control *thread ); -void _Scheduler_simple_smp_Schedule( void ); +void _Scheduler_simple_smp_Schedule( Thread_Control *thread ); void _Scheduler_simple_smp_Start_idle( Thread_Control *thread, diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 06d4ee6..a3b6904 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -498,16 +498,6 @@ RTEMS_INLINE_ROUTINE bool _Thread_Is_heir ( } /** - * This function returns true if the currently executing thread - * is also the heir thread, and false otherwise. - */ - -RTEMS_INLINE_ROUTINE bool _Thread_Is_executing_also_the_heir( void ) -{ - return ( _Thread_Executing == _Thread_Heir ); -} - -/** * This routine clears any blocking state for the_thread. It performs * any necessary scheduling operations including the selection of * a new heir thread. diff --git a/cpukit/score/preinstall.am b/cpukit/score/preinstall.am index 509d1dd..e79b8bb 100644 --- a/cpukit/score/preinstall.am +++ b/cpukit/score/preinstall.am @@ -183,6 +183,10 @@ $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h: include/rtems/score/scheduleredf. $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/scheduleredf.h +$(PROJECT_INCLUDE)/rtems/score/scheduleredfimpl.h: include/rtems/score/scheduleredfimpl.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/scheduleredfimpl.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/scheduleredfimpl.h + $(PROJECT_INCLUDE)/rtems/score/schedulerpriority.h: include/rtems/score/schedulerpriority.h $(PROJECT_INCLUDE)/rtems/score/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/score/schedulerpriority.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/score/schedulerpriority.h diff --git a/cpukit/score/src/scheduleredfblock.c b/cpukit/score/src/scheduleredfblock.c index 4ad767d..80bb1d5 100644 --- a/cpukit/score/src/scheduleredfblock.c +++ b/cpukit/score/src/scheduleredfblock.c @@ -19,20 +19,15 @@ #include "config.h" #endif -#include <rtems/score/scheduleredf.h> -#include <rtems/score/threadimpl.h> +#include <rtems/score/scheduleredfimpl.h> void _Scheduler_EDF_Block( Thread_Control *the_thread ) { - _Scheduler_EDF_Extract( the_thread ); - - /* TODO: flash critical section? */ - - if ( _Thread_Is_heir( the_thread ) ) - _Scheduler_EDF_Schedule(); - - if ( _Thread_Is_executing( the_thread ) ) - _Thread_Dispatch_necessary = true; + _Scheduler_Generic_block( + _Scheduler_EDF_Extract, + _Scheduler_EDF_Schedule_body, + the_thread + ); } diff --git a/cpukit/score/src/scheduleredfschedule.c b/cpukit/score/src/scheduleredfschedule.c index dbe21dc..a71a5b5 100644 --- a/cpukit/score/src/scheduleredfschedule.c +++ b/cpukit/score/src/scheduleredfschedule.c @@ -18,15 +18,9 @@ #include "config.h" #endif -#include <rtems/system.h> -#include <rtems/score/scheduler.h> -#include <rtems/score/scheduleredf.h> +#include <rtems/score/scheduleredfimpl.h> -void _Scheduler_EDF_Schedule(void) +void _Scheduler_EDF_Schedule( Thread_Control *thread ) { - RBTree_Node *first = _RBTree_First(&_Scheduler_EDF_Ready_queue, RBT_LEFT); - Scheduler_EDF_Per_thread *sched_info = - _RBTree_Container_of(first, Scheduler_EDF_Per_thread, Node); - - _Thread_Heir = (Thread_Control *) sched_info->thread; + _Scheduler_EDF_Schedule_body( thread, false ); } diff --git a/cpukit/score/src/scheduleredfyield.c b/cpukit/score/src/scheduleredfyield.c index 4ba9f79..fc5b13a 100644 --- a/cpukit/score/src/scheduleredfyield.c +++ b/cpukit/score/src/scheduleredfyield.c @@ -19,11 +19,7 @@ #include "config.h" #endif -#include <rtems/system.h> -#include <rtems/score/isr.h> -#include <rtems/score/scheduler.h> -#include <rtems/score/scheduleredf.h> -#include <rtems/score/thread.h> +#include <rtems/score/scheduleredfimpl.h> void _Scheduler_EDF_Yield( Thread_Control *thread ) { @@ -44,8 +40,7 @@ void _Scheduler_EDF_Yield( Thread_Control *thread ) _ISR_Flash( level ); - _Scheduler_EDF_Schedule(); - _Thread_Dispatch_necessary = true; + _Scheduler_EDF_Schedule_body( thread, false ); _ISR_Enable( level ); } diff --git a/cpukit/score/src/schedulerpriorityblock.c b/cpukit/score/src/schedulerpriorityblock.c index 9e48101..329ddd7 100644 --- a/cpukit/score/src/schedulerpriorityblock.c +++ b/cpukit/score/src/schedulerpriorityblock.c @@ -21,20 +21,14 @@ #endif #include <rtems/score/schedulerpriorityimpl.h> -#include <rtems/score/threadimpl.h> void _Scheduler_priority_Block( Thread_Control *the_thread ) { - _Scheduler_priority_Ready_queue_extract( the_thread ); - - /* TODO: flash critical section? */ - - if ( _Thread_Is_heir( the_thread ) ) - _Scheduler_priority_Schedule_body(); - - if ( _Thread_Is_executing( the_thread ) ) - _Thread_Dispatch_necessary = true; - + _Scheduler_Generic_block( + _Scheduler_priority_Ready_queue_extract, + _Scheduler_priority_Schedule_body, + the_thread + ); } diff --git a/cpukit/score/src/schedulerpriorityschedule.c b/cpukit/score/src/schedulerpriorityschedule.c index 22ed5f4..42647e6 100644 --- a/cpukit/score/src/schedulerpriorityschedule.c +++ b/cpukit/score/src/schedulerpriorityschedule.c @@ -20,7 +20,7 @@ #include <rtems/score/schedulerpriorityimpl.h> -void _Scheduler_priority_Schedule(void) +void _Scheduler_priority_Schedule( Thread_Control *thread ) { - _Scheduler_priority_Schedule_body(); + _Scheduler_priority_Schedule_body( thread, false ); } diff --git a/cpukit/score/src/schedulersimpleblock.c b/cpukit/score/src/schedulersimpleblock.c index b9753b5..1e6e8a0 100644 --- a/cpukit/score/src/schedulersimpleblock.c +++ b/cpukit/score/src/schedulersimpleblock.c @@ -19,18 +19,15 @@ #include "config.h" #endif -#include <rtems/score/schedulersimple.h> -#include <rtems/score/threadimpl.h> +#include <rtems/score/schedulersimpleimpl.h> void _Scheduler_simple_Block( Thread_Control *the_thread ) { - _Scheduler_simple_Extract(the_thread); - - if ( _Thread_Is_heir( the_thread ) ) - _Scheduler_simple_Schedule(); - - if ( _Thread_Is_executing( the_thread ) ) - _Thread_Dispatch_necessary = true; + _Scheduler_Generic_block( + _Scheduler_simple_Extract, + _Scheduler_simple_Schedule_body, + the_thread + ); } diff --git a/cpukit/score/src/schedulersimpleschedule.c b/cpukit/score/src/schedulersimpleschedule.c index b60f096..5018e0b 100644 --- a/cpukit/score/src/schedulersimpleschedule.c +++ b/cpukit/score/src/schedulersimpleschedule.c @@ -18,12 +18,9 @@ #include "config.h" #endif -#include <rtems/score/schedulersimple.h> -#include <rtems/score/chainimpl.h> +#include <rtems/score/schedulersimpleimpl.h> -void _Scheduler_simple_Schedule(void) +void _Scheduler_simple_Schedule( Thread_Control *thread ) { - _Thread_Heir = (Thread_Control *) _Chain_First( - (Chain_Control *) _Scheduler.information - ); + _Scheduler_simple_Schedule_body( thread, false ); } diff --git a/cpukit/score/src/schedulersimplesmp.c b/cpukit/score/src/schedulersimplesmp.c index db08b96..e261510 100644 --- a/cpukit/score/src/schedulersimplesmp.c +++ b/cpukit/score/src/schedulersimplesmp.c @@ -182,9 +182,9 @@ void _Scheduler_simple_smp_Yield( Thread_Control *thread ) _ISR_Enable( level ); } -void _Scheduler_simple_smp_Schedule( void ) +void _Scheduler_simple_smp_Schedule( Thread_Control *thread ) { - /* Nothing to do */ + ( void ) thread; } void _Scheduler_simple_smp_Start_idle( diff --git a/cpukit/score/src/schedulersimpleyield.c b/cpukit/score/src/schedulersimpleyield.c index cb8dc6f..43784d6 100644 --- a/cpukit/score/src/schedulersimpleyield.c +++ b/cpukit/score/src/schedulersimpleyield.c @@ -32,10 +32,7 @@ void _Scheduler_simple_Yield( Thread_Control *thread ) _ISR_Flash( level ); - _Scheduler_simple_Schedule(); - - if ( !_Thread_Is_heir( thread ) ) - _Thread_Dispatch_necessary = true; + _Scheduler_simple_Schedule_body( thread, false ); _ISR_Enable( level ); } diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c index b443731..b3d7984 100644 --- a/cpukit/score/src/threadchangepriority.c +++ b/cpukit/score/src/threadchangepriority.c @@ -62,6 +62,15 @@ void _Thread_Change_priority( /* Only clear the transient state if it wasn't set already */ if ( ! _States_Is_transient( original_state ) ) the_thread->current_state = _States_Clear( STATES_TRANSIENT, state ); + + /* + * The thread may have new blocking states added by interrupt service + * routines after the change into the transient state. This will not + * result in a _Scheduler_Block() operation. Make sure we select an heir + * now. + */ + _Scheduler_Schedule( the_thread ); + _ISR_Enable( level ); if ( _States_Is_waiting_on_thread_queue( state ) ) { _Thread_queue_Requeue( the_thread->Wait.queue, the_thread ); @@ -91,10 +100,7 @@ void _Thread_Change_priority( * We altered the set of thread priorities. So let's figure out * who is the heir and if we need to switch to them. */ - _Scheduler_Schedule(); + _Scheduler_Schedule( the_thread ); - if ( !_Thread_Is_executing_also_the_heir() && - _Thread_Executing->is_preemptible ) - _Thread_Dispatch_necessary = true; _ISR_Enable( level ); } -- 1.7.7 _______________________________________________ rtems-devel mailing list rtems-devel@rtems.org http://www.rtems.org/mailman/listinfo/rtems-devel