From 82e221671315e975036bb5bd80c370609f1381d0 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 23 Sep 2021 07:35:09 +0200 Subject: score: Avoid dead code in thread queue surrender For uniprocessor configurations, this patch removes dead code in the _Thread_queue_Surrender() and _Thread_queue_Surrender_priority_ceiling() functions. Dead code is removed from _Thread_queue_Surrender_sticky(). --- cpukit/score/src/threadqenqueue.c | 79 +++++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 12 deletions(-) diff --git a/cpukit/score/src/threadqenqueue.c b/cpukit/score/src/threadqenqueue.c index 4b138ba4d1..1b8b82eab9 100644 --- a/cpukit/score/src/threadqenqueue.c +++ b/cpukit/score/src/threadqenqueue.c @@ -544,6 +544,16 @@ static bool _Thread_queue_MP_set_callout( } #endif +static void _Thread_queue_Force_ready_again( Thread_Control *the_thread ) +{ + /* + * We must set the wait flags under protection of the current thread lock, + * otherwise a _Thread_Timeout() running on another processor may interfere. + */ + _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_READY_AGAIN ); + _Thread_Wait_restore_default( the_thread ); +} + static bool _Thread_queue_Make_ready_again( Thread_Control *the_thread ) { bool success; @@ -570,6 +580,45 @@ static bool _Thread_queue_Make_ready_again( Thread_Control *the_thread ) return unblock; } +/* + * This function is used instead of _Thread_queue_Make_ready_again() in + * _Thread_queue_Surrender() and _Thread_queue_Surrender_priority_ceiling() + * since only the previous owner thread is allowed to surrender the thread + * queue. + * + * In uniprocessor configurations, there is only one executing thread (in this + * case the previous owner), so the new owner thread must be fully blocked. + * + * In SMP configurations, the new owner may execute on another processor in + * parallel, so we have to use _Thread_queue_Make_ready_again(). + */ +static bool _Thread_queue_Make_new_owner_ready_again( Thread_Control *new_owner ) +{ +#if defined(RTEMS_SMP) + return _Thread_queue_Make_ready_again( new_owner ); +#else + _Assert( _Thread_Wait_flags_get( new_owner ) == THREAD_QUEUE_BLOCKED ); + _Thread_queue_Force_ready_again( new_owner ); + return false; +#endif +} + +static void _Thread_queue_Unblock_new_owner_and_remove_timer( + Thread_queue_Queue *queue, + Thread_Control *new_owner, + bool unblock +) +{ +#if defined(RTEMS_SMP) + if ( unblock ) { + _Thread_Remove_timer_and_unblock( new_owner, queue ); + } +#else + (void) unblock; + _Thread_Remove_timer_and_unblock( new_owner, queue ); +#endif +} + bool _Thread_queue_Extract_locked( Thread_queue_Queue *queue, const Thread_queue_Operations *operations, @@ -673,7 +722,7 @@ void _Thread_queue_Surrender( _Thread_Resource_count_increment( new_owner ); } - unblock = _Thread_queue_Make_ready_again( new_owner ); + unblock = _Thread_queue_Make_new_owner_ready_again( new_owner ); cpu_self = _Thread_queue_Dispatch_disable( queue_context ); _Thread_queue_Queue_release( @@ -682,10 +731,11 @@ void _Thread_queue_Surrender( ); _Thread_Priority_update( queue_context ); - - if ( unblock ) { - _Thread_Remove_timer_and_unblock( new_owner, queue ); - } + _Thread_queue_Unblock_new_owner_and_remove_timer( + queue, + new_owner, + unblock + ); _Thread_Dispatch_enable( cpu_self ); } @@ -771,7 +821,7 @@ Status_Control _Thread_queue_Surrender_priority_ceiling( queue->owner = new_owner; - unblock = _Thread_queue_Make_ready_again( new_owner ); + unblock = _Thread_queue_Make_new_owner_ready_again( new_owner ); #if defined(RTEMS_MULTIPROCESSING) if ( _Objects_Is_local_id( new_owner->Object.id ) ) @@ -790,10 +840,11 @@ Status_Control _Thread_queue_Surrender_priority_ceiling( ); _Thread_Priority_update( queue_context ); - - if ( unblock ) { - _Thread_Remove_timer_and_unblock( new_owner, queue ); - } + _Thread_queue_Unblock_new_owner_and_remove_timer( + queue, + new_owner, + unblock + ); _Thread_Dispatch_direct( cpu_self ); return STATUS_SUCCESSFUL; @@ -823,11 +874,15 @@ void _Thread_queue_Surrender_sticky( queue->owner = new_owner; /* - * There is no need to check the unblock status, since in the corresponding + * There is no need to unblock the thread, since in the corresponding * _Thread_queue_Enqueue_sticky() the thread is not blocked by the scheduler. * Instead, the thread busy waits for a change of its thread wait flags. + * Timeouts cannot interfere since we hold the thread queue lock. */ - (void) _Thread_queue_Make_ready_again( new_owner ); + _Assert( + _Thread_Wait_flags_get( new_owner ) == THREAD_QUEUE_INTEND_TO_BLOCK + ); + _Thread_queue_Force_ready_again( new_owner ); cpu_self = _Thread_queue_Dispatch_disable( queue_context ); _Thread_queue_Queue_release( -- cgit v1.2.3