In addition protect scheduler of thread by thread state lock. Enables use of scheduler per-instance locks.
Update #2555. --- cpukit/libmisc/cpuuse/cpuusagereset.c | 13 ++- cpukit/rtems/src/taskmode.c | 4 +- cpukit/score/include/rtems/score/schedulerimpl.h | 134 +++++++++++++++-------- cpukit/score/include/rtems/score/thread.h | 7 +- cpukit/score/src/schedulercbsunblock.c | 7 +- cpukit/score/src/threadchangepriority.c | 4 +- cpukit/score/src/threadclearstate.c | 4 +- cpukit/score/src/threadgetcputimeused.c | 11 +- cpukit/score/src/threadsetstate.c | 4 +- cpukit/score/src/threadyield.c | 4 +- testsuites/smptests/smpscheduler03/init.c | 56 +++++++--- testsuites/tmtests/tm27/task1.c | 18 ++- 12 files changed, 182 insertions(+), 84 deletions(-) diff --git a/cpukit/libmisc/cpuuse/cpuusagereset.c b/cpukit/libmisc/cpuuse/cpuusagereset.c index 6ef50f9..74f273a 100644 --- a/cpukit/libmisc/cpuuse/cpuusagereset.c +++ b/cpukit/libmisc/cpuuse/cpuusagereset.c @@ -28,11 +28,18 @@ static void CPU_usage_Per_thread_handler( Thread_Control *the_thread ) { - ISR_lock_Context lock_context; + const Scheduler_Control *scheduler; + ISR_lock_Context state_lock_context; + ISR_lock_Context scheduler_lock_context; + + _Thread_State_acquire( the_thread, &state_lock_context ); + scheduler = _Scheduler_Get( the_thread ); + _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context ); - _Scheduler_Acquire( the_thread, &lock_context ); _Timestamp_Set_to_zero( &the_thread->cpu_time_used ); - _Scheduler_Release( the_thread, &lock_context ); + + _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); + _Thread_State_release( the_thread, &state_lock_context ); } /* diff --git a/cpukit/rtems/src/taskmode.c b/cpukit/rtems/src/taskmode.c index 131632d..a345409 100644 --- a/cpukit/rtems/src/taskmode.c +++ b/cpukit/rtems/src/taskmode.c @@ -120,9 +120,9 @@ rtems_status_code rtems_task_mode( Per_CPU_Control *cpu_self; cpu_self = _Thread_Dispatch_disable(); - _Scheduler_Acquire( executing, &lock_context ); + _Thread_State_acquire( executing, &lock_context ); _Scheduler_Schedule( executing ); - _Scheduler_Release( executing, &lock_context ); + _Thread_State_release( executing, &lock_context ); _Thread_Dispatch_enable( cpu_self ); } diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 5cf3503..99f590e 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -10,7 +10,7 @@ /* * Copyright (C) 2010 Gedare Bloom. * Copyright (C) 2011 On-Line Applications Research Corporation (OAR). - * Copyright (c) 2014-2015 embedded brains GmbH + * Copyright (c) 2014, 2016 embedded brains GmbH * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -118,6 +118,42 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Node_get_user( } #endif +ISR_LOCK_DECLARE( extern, _Scheduler_Lock ) + +/** + * @brief Acquires the scheduler instance inside a critical section (interrupts + * disabled). + * + * @param[in] scheduler The scheduler instance. + * @param[in] lock_context The lock context to use for + * _Scheduler_Release_critical(). + */ +RTEMS_INLINE_ROUTINE void _Scheduler_Acquire_critical( + const Scheduler_Control *scheduler, + ISR_lock_Context *lock_context +) +{ + (void) scheduler; + _ISR_lock_Acquire( &_Scheduler_Lock, lock_context ); +} + +/** + * @brief Releases the scheduler instance inside a critical section (interrupts + * disabled). + * + * @param[in] scheduler The scheduler instance. + * @param[in] lock_context The lock context used for + * _Scheduler_Acquire_critical(). + */ +RTEMS_INLINE_ROUTINE void _Scheduler_Release_critical( + const Scheduler_Control *scheduler, + ISR_lock_Context *lock_context +) +{ + (void) scheduler; + _ISR_lock_Release( &_Scheduler_Lock, lock_context ); +} + /** * The preferred method to add a new scheduler is to define the jump table * entries and add a case to the _Scheduler_Initialize routine. @@ -143,9 +179,15 @@ RTEMS_INLINE_ROUTINE Thread_Control *_Scheduler_Node_get_user( */ RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( Thread_Control *the_thread ) { - const Scheduler_Control *scheduler = _Scheduler_Get( the_thread ); + const Scheduler_Control *scheduler; + ISR_lock_Context lock_context; + + scheduler = _Scheduler_Get( the_thread ); + _Scheduler_Acquire_critical( scheduler, &lock_context ); ( *scheduler->Operations.schedule )( scheduler, the_thread ); + + _Scheduler_Release_critical( scheduler, &lock_context ); } #if defined(RTEMS_SMP) @@ -252,14 +294,22 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Ask_for_help_if_necessary( */ RTEMS_INLINE_ROUTINE void _Scheduler_Yield( Thread_Control *the_thread ) { - const Scheduler_Control *scheduler = _Scheduler_Get( the_thread ); + const Scheduler_Control *scheduler; + ISR_lock_Context lock_context; #if defined(RTEMS_SMP) - Thread_Control *needs_help; + Thread_Control *needs_help; +#endif + + scheduler = _Scheduler_Get( the_thread ); + _Scheduler_Acquire_critical( scheduler, &lock_context ); +#if defined(RTEMS_SMP) needs_help = #endif ( *scheduler->Operations.yield )( scheduler, the_thread ); + _Scheduler_Release_critical( scheduler, &lock_context ); + #if defined(RTEMS_SMP) _Scheduler_Ask_for_help_if_necessary( needs_help ); #endif @@ -277,9 +327,15 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Yield( Thread_Control *the_thread ) */ RTEMS_INLINE_ROUTINE void _Scheduler_Block( Thread_Control *the_thread ) { - const Scheduler_Control *scheduler = _Scheduler_Get( the_thread ); + const Scheduler_Control *scheduler; + ISR_lock_Context lock_context; + + scheduler = _Scheduler_Get( the_thread ); + _Scheduler_Acquire_critical( scheduler, &lock_context ); ( *scheduler->Operations.block )( scheduler, the_thread ); + + _Scheduler_Release_critical( scheduler, &lock_context ); } /** @@ -294,14 +350,22 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Block( Thread_Control *the_thread ) */ RTEMS_INLINE_ROUTINE void _Scheduler_Unblock( Thread_Control *the_thread ) { - const Scheduler_Control *scheduler = _Scheduler_Get( the_thread ); + const Scheduler_Control *scheduler; + ISR_lock_Context lock_context; #if defined(RTEMS_SMP) - Thread_Control *needs_help; + Thread_Control *needs_help; +#endif + scheduler = _Scheduler_Get( the_thread ); + _Scheduler_Acquire_critical( scheduler, &lock_context ); + +#if defined(RTEMS_SMP) needs_help = #endif ( *scheduler->Operations.unblock )( scheduler, the_thread ); + _Scheduler_Release_critical( scheduler, &lock_context ); + #if defined(RTEMS_SMP) _Scheduler_Ask_for_help_if_necessary( needs_help ); #endif @@ -329,19 +393,27 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority( bool prepend_it ) { - const Scheduler_Control *scheduler = _Scheduler_Get_own( the_thread ); + const Scheduler_Control *own_scheduler; + ISR_lock_Context lock_context; #if defined(RTEMS_SMP) - Thread_Control *needs_help; + Thread_Control *needs_help; +#endif + own_scheduler = _Scheduler_Get_own( the_thread ); + _Scheduler_Acquire_critical( own_scheduler, &lock_context ); + +#if defined(RTEMS_SMP) needs_help = #endif - ( *scheduler->Operations.change_priority )( - scheduler, + ( *own_scheduler->Operations.change_priority )( + own_scheduler, the_thread, new_priority, prepend_it ); + _Scheduler_Release_critical( own_scheduler, &lock_context ); + #if defined(RTEMS_SMP) _Scheduler_Ask_for_help_if_necessary( needs_help ); #endif @@ -394,13 +466,19 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Update_priority( Priority_Control new_priority ) { - const Scheduler_Control *scheduler = _Scheduler_Get( the_thread ); + const Scheduler_Control *scheduler; + ISR_lock_Context lock_context; + + scheduler = _Scheduler_Get( the_thread ); + _Scheduler_Acquire_critical( scheduler, &lock_context ); ( *scheduler->Operations.update_priority )( scheduler, the_thread, new_priority ); + + _Scheduler_Release_critical( scheduler, &lock_context ); } /** @@ -1341,8 +1419,6 @@ RTEMS_INLINE_ROUTINE bool _Scheduler_Ask_blocked_node_for_help( } #endif -ISR_LOCK_DECLARE( extern, _Scheduler_Lock ) - RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir( Thread_Control *new_heir, bool force_dispatch @@ -1367,36 +1443,6 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Update_heir( } } -/** - * @brief Acquires the scheduler instance of the thread. - * - * @param[in] the_thread The thread. - * @param[in] lock_context The lock context for _Scheduler_Release(). - */ -RTEMS_INLINE_ROUTINE void _Scheduler_Acquire( - Thread_Control *the_thread, - ISR_lock_Context *lock_context -) -{ - (void) the_thread; - _ISR_lock_ISR_disable_and_acquire( &_Scheduler_Lock, lock_context ); -} - -/** - * @brief Releases the scheduler instance of the thread. - * - * @param[in] the_thread The thread. - * @param[in] lock_context The lock context used for _Scheduler_Acquire(). - */ -RTEMS_INLINE_ROUTINE void _Scheduler_Release( - Thread_Control *the_thread, - ISR_lock_Context *lock_context -) -{ - (void) the_thread; - _ISR_lock_Release_and_ISR_enable( &_Scheduler_Lock, lock_context ); -} - /** @} */ #ifdef __cplusplus diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index d2a6d4b..15b068d 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -718,8 +718,11 @@ struct _Thread_Control { * The lock of this thread queue is used for various purposes. It protects * the following fields * - * - RTEMS_API_Control::Signal, and - * - Thread_Control::Post_switch_actions. + * - RTEMS_API_Control::Signal, + * - Thread_Control::current_state, + * - Thread_Control::Post_switch_actions, + * - Thread_Control::Scheduler::control, and + * - Thread_Control::Scheduler::own_control. * * @see _Thread_State_acquire(). */ diff --git a/cpukit/score/src/schedulercbsunblock.c b/cpukit/score/src/schedulercbsunblock.c index 9170889..2b35a9b 100644 --- a/cpukit/score/src/schedulercbsunblock.c +++ b/cpukit/score/src/schedulercbsunblock.c @@ -56,7 +56,12 @@ Scheduler_Void_or_thread _Scheduler_CBS_Unblock( the_thread->real_priority = new_priority; if ( the_thread->current_priority != new_priority ) { the_thread->current_priority = new_priority; - _Scheduler_Change_priority(the_thread, new_priority, true); + ( *scheduler->Operations.change_priority )( + scheduler, + the_thread, + new_priority, + true + ); } } } diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c index 35e5e5b..152646f 100644 --- a/cpukit/score/src/threadchangepriority.c +++ b/cpukit/score/src/threadchangepriority.c @@ -64,7 +64,7 @@ void _Thread_Change_priority( _Thread_Lock_release( lock, &lock_context ); - _Scheduler_Acquire( the_thread, &lock_context ); + _Thread_State_acquire( the_thread, &lock_context ); if ( the_thread->priority_generation == my_generation ) { if ( _States_Is_ready( the_thread->current_state ) ) { @@ -78,7 +78,7 @@ void _Thread_Change_priority( } } - _Scheduler_Release( the_thread, &lock_context ); + _Thread_State_release( the_thread, &lock_context ); } else { _Thread_Lock_release( lock, &lock_context ); } diff --git a/cpukit/score/src/threadclearstate.c b/cpukit/score/src/threadclearstate.c index ae54e3a..3da3538 100644 --- a/cpukit/score/src/threadclearstate.c +++ b/cpukit/score/src/threadclearstate.c @@ -32,7 +32,7 @@ States_Control _Thread_Clear_state( _Assert( state != 0 ); - _Scheduler_Acquire( the_thread, &lock_context ); + _Thread_State_acquire( the_thread, &lock_context ); previous_state = the_thread->current_state; @@ -47,7 +47,7 @@ States_Control _Thread_Clear_state( } } - _Scheduler_Release( the_thread, &lock_context ); + _Thread_State_release( the_thread, &lock_context ); return previous_state; } diff --git a/cpukit/score/src/threadgetcputimeused.c b/cpukit/score/src/threadgetcputimeused.c index 6bfe8ea..9026007 100644 --- a/cpukit/score/src/threadgetcputimeused.c +++ b/cpukit/score/src/threadgetcputimeused.c @@ -33,9 +33,13 @@ void _Thread_Get_CPU_time_used( Timestamp_Control *cpu_time_used ) { - ISR_lock_Context lock_context; + const Scheduler_Control *scheduler; + ISR_lock_Context state_lock_context; + ISR_lock_Context scheduler_lock_context; - _Scheduler_Acquire( the_thread, &lock_context ); + _Thread_State_acquire( the_thread, &state_lock_context ); + scheduler = _Scheduler_Get( the_thread ); + _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context ); if ( _Thread_Is_scheduled( the_thread ) ) { _Thread_Update_CPU_time_used( the_thread, _Thread_Get_CPU( the_thread ) ); @@ -43,5 +47,6 @@ void _Thread_Get_CPU_time_used( *cpu_time_used = the_thread->cpu_time_used; - _Scheduler_Release( the_thread, &lock_context ); + _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); + _Thread_State_release( the_thread, &state_lock_context ); } diff --git a/cpukit/score/src/threadsetstate.c b/cpukit/score/src/threadsetstate.c index 5112827..3aaa463 100644 --- a/cpukit/score/src/threadsetstate.c +++ b/cpukit/score/src/threadsetstate.c @@ -36,7 +36,7 @@ States_Control _Thread_Set_state( _Assert( state != 0 ); - _Scheduler_Acquire( the_thread, &lock_context ); + _Thread_State_acquire( the_thread, &lock_context ); previous_state = the_thread->current_state; next_state = _States_Set( state, previous_state); @@ -46,7 +46,7 @@ States_Control _Thread_Set_state( _Scheduler_Block( the_thread ); } - _Scheduler_Release( the_thread, &lock_context ); + _Thread_State_release( the_thread, &lock_context ); return previous_state; } diff --git a/cpukit/score/src/threadyield.c b/cpukit/score/src/threadyield.c index 7f1c175..cfd8118 100644 --- a/cpukit/score/src/threadyield.c +++ b/cpukit/score/src/threadyield.c @@ -31,11 +31,11 @@ void _Thread_Yield( Thread_Control *executing ) { ISR_lock_Context lock_context; - _Scheduler_Acquire( executing, &lock_context ); + _Thread_State_acquire( executing, &lock_context ); if ( _States_Is_ready( executing->current_state ) ) { _Scheduler_Yield( executing ); } - _Scheduler_Release( executing, &lock_context ); + _Thread_State_release( executing, &lock_context ); } diff --git a/testsuites/smptests/smpscheduler03/init.c b/testsuites/smptests/smpscheduler03/init.c index 4a3aa54..1888048 100644 --- a/testsuites/smptests/smpscheduler03/init.c +++ b/testsuites/smptests/smpscheduler03/init.c @@ -193,11 +193,15 @@ static Thread_Control *change_priority_op( bool prepend_it ) { - const Scheduler_Control *scheduler = _Scheduler_Get(thread); + const Scheduler_Control *scheduler; + ISR_lock_Context state_lock_context; + ISR_lock_Context scheduler_lock_context; Thread_Control *needs_help; - ISR_lock_Context lock_context; - _Scheduler_Acquire(thread, &lock_context); + _Thread_State_acquire( thread, &state_lock_context ); + scheduler = _Scheduler_Get( thread ); + _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context ); + thread->current_priority = new_priority; needs_help = (*scheduler->Operations.change_priority)( scheduler, @@ -205,7 +209,9 @@ static Thread_Control *change_priority_op( new_priority, prepend_it ); - _Scheduler_Release(thread, &lock_context); + + _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); + _Thread_State_release( thread, &state_lock_context ); return needs_help; } @@ -302,13 +308,19 @@ static void test_change_priority_op(void) static Thread_Control *yield_op(Thread_Control *thread) { - const Scheduler_Control *scheduler = _Scheduler_Get(thread); + const Scheduler_Control *scheduler; + ISR_lock_Context state_lock_context; + ISR_lock_Context scheduler_lock_context; Thread_Control *needs_help; - ISR_lock_Context lock_context; - _Scheduler_Acquire(thread, &lock_context); + _Thread_State_acquire( thread, &state_lock_context ); + scheduler = _Scheduler_Get( thread ); + _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context ); + needs_help = (*scheduler->Operations.yield)(scheduler, thread); - _Scheduler_Release(thread, &lock_context); + + _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); + _Thread_State_release( thread, &state_lock_context ); return needs_help; } @@ -429,23 +441,35 @@ static void test_yield_op(void) static void block_op(Thread_Control *thread) { - const Scheduler_Control *scheduler = _Scheduler_Get(thread); - ISR_lock_Context lock_context; + const Scheduler_Control *scheduler; + ISR_lock_Context state_lock_context; + ISR_lock_Context scheduler_lock_context; + + _Thread_State_acquire( thread, &state_lock_context ); + scheduler = _Scheduler_Get( thread ); + _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context ); - _Scheduler_Acquire(thread, &lock_context); (*scheduler->Operations.block)(scheduler, thread); - _Scheduler_Release(thread, &lock_context); + + _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); + _Thread_State_release( thread, &state_lock_context ); } static Thread_Control *unblock_op(Thread_Control *thread) { - const Scheduler_Control *scheduler = _Scheduler_Get(thread); + const Scheduler_Control *scheduler; + ISR_lock_Context state_lock_context; + ISR_lock_Context scheduler_lock_context; Thread_Control *needs_help; - ISR_lock_Context lock_context; - _Scheduler_Acquire(thread, &lock_context); + _Thread_State_acquire( thread, &state_lock_context ); + scheduler = _Scheduler_Get( thread ); + _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context ); + needs_help = (*scheduler->Operations.unblock)(scheduler, thread); - _Scheduler_Release(thread, &lock_context); + + _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); + _Thread_State_release( thread, &state_lock_context ); return needs_help; } diff --git a/testsuites/tmtests/tm27/task1.c b/testsuites/tmtests/tm27/task1.c index d351b41..77072bb 100644 --- a/testsuites/tmtests/tm27/task1.c +++ b/testsuites/tmtests/tm27/task1.c @@ -225,9 +225,15 @@ rtems_task Task_2( ) { Thread_Control *executing = _Thread_Get_executing(); - Scheduler_priority_Context *scheduler_context = - _Scheduler_priority_Get_context( _Scheduler_Get( executing ) ); - ISR_lock_Context lock_context; + const Scheduler_Control *scheduler; + Scheduler_priority_Context *scheduler_context; + ISR_lock_Context state_lock_context; + ISR_lock_Context scheduler_lock_context; + + _Thread_State_acquire( executing, &state_lock_context ); + scheduler = _Scheduler_Get( executing ); + scheduler_context = _Scheduler_priority_Get_context( scheduler ); + _Thread_State_release( executing, &state_lock_context ); #if (MUST_WAIT_FOR_INTERRUPT == 1) while ( Interrupt_occurred == 0 ); @@ -256,14 +262,16 @@ rtems_task Task_2( * Switch back to the other task to exit the test. */ - _Scheduler_Acquire( executing, &lock_context ); + _Thread_State_acquire( executing, &state_lock_context ); + _Scheduler_Acquire_critical( scheduler, &scheduler_lock_context ); _Thread_Executing = (Thread_Control *) _Chain_First(&scheduler_context->Ready[LOW_PRIORITY]); _Thread_Dispatch_necessary = 1; - _Scheduler_Release( executing, &lock_context ); + _Scheduler_Release_critical( scheduler, &scheduler_lock_context ); + _Thread_State_release( executing, &state_lock_context ); _Thread_Dispatch(); -- 1.8.4.5 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel