From 300f6a481aaf9e6d29811faca71bf7104a01492c Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 22 Jun 2016 17:09:23 +0200 Subject: score: Rework thread priority management Add priority nodes which contribute to the overall thread priority. The actual priority of a thread is now an aggregation of priority nodes. The thread priority aggregation for the home scheduler instance of a thread consists of at least one priority node, which is normally the real priority of the thread. The locking protocols (e.g. priority ceiling and priority inheritance), rate-monotonic period objects and the POSIX sporadic server add, change and remove priority nodes. A thread changes its priority now immediately, e.g. priority changes are not deferred until the thread releases its last resource. Replace the _Thread_Change_priority() function with * _Thread_Priority_perform_actions(), * _Thread_Priority_add(), * _Thread_Priority_remove(), * _Thread_Priority_change(), and * _Thread_Priority_update(). Update #2412. Update #2556. --- cpukit/score/include/rtems/score/coremuteximpl.h | 146 +++++++++++------------ 1 file changed, 69 insertions(+), 77 deletions(-) (limited to 'cpukit/score/include/rtems/score/coremuteximpl.h') diff --git a/cpukit/score/include/rtems/score/coremuteximpl.h b/cpukit/score/include/rtems/score/coremuteximpl.h index 25094a49df..a30d1a880e 100644 --- a/cpukit/score/include/rtems/score/coremuteximpl.h +++ b/cpukit/score/include/rtems/score/coremuteximpl.h @@ -124,32 +124,6 @@ RTEMS_INLINE_ROUTINE bool _CORE_mutex_Is_owner( return _CORE_mutex_Get_owner( the_mutex ) == the_thread; } -RTEMS_INLINE_ROUTINE void _CORE_mutex_Restore_priority( - Thread_Control *executing -) -{ - /* - * Whether or not someone is waiting for the mutex, an - * inherited priority must be lowered if this is the last - * mutex (i.e. resource) this task has. - */ - if ( !_Thread_Owns_resources( executing ) ) { - /* - * Ensure that the executing resource count is visible to all other - * processors and that we read the latest priority restore hint. - */ - _Atomic_Fence( ATOMIC_ORDER_ACQ_REL ); - - if ( executing->priority_restore_hint ) { - Per_CPU_Control *cpu_self; - - cpu_self = _Thread_Dispatch_disable(); - _Thread_Restore_priority( executing ); - _Thread_Dispatch_enable( cpu_self ); - } - } -} - RTEMS_INLINE_ROUTINE void _CORE_recursive_mutex_Initialize( CORE_recursive_mutex_Control *the_mutex ) @@ -212,7 +186,6 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender( { unsigned int nest_level; Thread_queue_Heads *heads; - bool keep_priority; _CORE_mutex_Acquire_critical( &the_mutex->Mutex, queue_context ); @@ -232,29 +205,19 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_recursive_mutex_Surrender( --executing->resource_count; _CORE_mutex_Set_owner( &the_mutex->Mutex, NULL ); - /* - * Ensure that the owner resource count is visible to all other - * processors and that we read the latest priority restore - * hint. - */ - _Atomic_Fence( ATOMIC_ORDER_ACQ_REL ); - heads = the_mutex->Mutex.Wait_queue.Queue.heads; - keep_priority = _Thread_Owns_resources( executing ) - || !executing->priority_restore_hint; - if ( heads == NULL && keep_priority ) { + if ( heads == NULL ) { _CORE_mutex_Release( &the_mutex->Mutex, queue_context ); return STATUS_SUCCESSFUL; } _Thread_queue_Surrender( &the_mutex->Mutex.Wait_queue.Queue, - CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS, heads, executing, - keep_priority, - queue_context + queue_context, + CORE_MUTEX_TQ_PRIORITY_INHERIT_OPERATIONS ); return STATUS_SUCCESSFUL; } @@ -349,7 +312,7 @@ RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Initialize( ) { _CORE_recursive_mutex_Initialize( &the_mutex->Recursive ); - the_mutex->priority_ceiling = priority_ceiling; + _Priority_Node_initialize( &the_mutex->Priority_ceiling, priority_ceiling ); #if defined(RTEMS_SMP) the_mutex->scheduler = scheduler; #endif @@ -369,17 +332,34 @@ _CORE_ceiling_mutex_Get_scheduler( RTEMS_INLINE_ROUTINE void _CORE_ceiling_mutex_Set_priority( CORE_ceiling_mutex_Control *the_mutex, - Priority_Control priority_ceiling + Priority_Control priority_ceiling, + Thread_queue_Context *queue_context ) { - the_mutex->priority_ceiling = priority_ceiling; + Thread_Control *owner; + + owner = _CORE_mutex_Get_owner( &the_mutex->Recursive.Mutex ); + + if ( owner != NULL ) { + _Thread_Wait_acquire( owner, queue_context ); + _Thread_Priority_change( + owner, + &the_mutex->Priority_ceiling, + priority_ceiling, + false, + queue_context + ); + _Thread_Wait_release( owner, queue_context ); + } else { + the_mutex->Priority_ceiling.priority = priority_ceiling; + } } RTEMS_INLINE_ROUTINE Priority_Control _CORE_ceiling_mutex_Get_priority( const CORE_ceiling_mutex_Control *the_mutex ) { - return the_mutex->priority_ceiling; + return the_mutex->Priority_ceiling.priority; } RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Set_owner( @@ -388,31 +368,38 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Set_owner( Thread_queue_Context *queue_context ) { - Priority_Control priority_ceiling; - Priority_Control current_priority; + ISR_lock_Context lock_context; + Scheduler_Node *own_node; Per_CPU_Control *cpu_self; - priority_ceiling = the_mutex->priority_ceiling; - current_priority = _Thread_Get_priority( owner ); + _Thread_queue_Context_clear_priority_updates( queue_context ); + _Thread_Wait_acquire_default_critical( owner, &lock_context ); - if ( current_priority < priority_ceiling ) { + own_node = _Thread_Scheduler_get_own_node( owner ); + + if ( + own_node->Wait.Priority.Node.priority + < the_mutex->Priority_ceiling.priority + ) { + _Thread_Wait_release_default_critical( owner, &lock_context ); _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context ); return STATUS_MUTEX_CEILING_VIOLATED; } _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, owner ); ++owner->resource_count; - - if ( current_priority == priority_ceiling ) { - _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context ); - return STATUS_SUCCESSFUL; - } + _Thread_Priority_add( + owner, + &the_mutex->Priority_ceiling, + queue_context + ); + _Thread_Wait_release_default_critical( owner, &lock_context ); cpu_self = _Thread_Dispatch_disable_critical( &queue_context->Lock_context.Lock_context ); _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context ); - _Thread_Raise_priority( owner, priority_ceiling ); + _Thread_Priority_update( queue_context ); _Thread_Dispatch_enable( cpu_self ); return STATUS_SUCCESSFUL; } @@ -472,8 +459,10 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Surrender( Thread_queue_Context *queue_context ) { - unsigned int nest_level; - Thread_Control *new_owner; + unsigned int nest_level; + ISR_lock_Context lock_context; + Per_CPU_Control *cpu_self; + Thread_Control *new_owner; _CORE_mutex_Acquire_critical( &the_mutex->Recursive.Mutex, queue_context ); @@ -492,47 +481,50 @@ RTEMS_INLINE_ROUTINE Status_Control _CORE_ceiling_mutex_Surrender( --executing->resource_count; + _Thread_queue_Context_clear_priority_updates( queue_context ); + _Thread_Wait_acquire_default_critical( executing, &lock_context ); + _Thread_Priority_remove( + executing, + &the_mutex->Priority_ceiling, + queue_context + ); + _Thread_Wait_release_default_critical( executing, &lock_context ); + new_owner = _Thread_queue_First_locked( &the_mutex->Recursive.Mutex.Wait_queue, CORE_MUTEX_TQ_OPERATIONS ); _CORE_mutex_Set_owner( &the_mutex->Recursive.Mutex, new_owner ); - if ( new_owner != NULL ) { - bool unblock; - - /* - * We must extract the thread now since this will restore its default - * thread lock. This is necessary to avoid a deadlock in the - * _Thread_Change_priority() below due to a recursive thread queue lock - * acquire. - */ - unblock = _Thread_queue_Extract_locked( - &the_mutex->Recursive.Mutex.Wait_queue.Queue, - CORE_MUTEX_TQ_OPERATIONS, - new_owner, - queue_context - ); + cpu_self = _Thread_Dispatch_disable_critical( + &queue_context->Lock_context.Lock_context + ); + if ( new_owner != NULL ) { #if defined(RTEMS_MULTIPROCESSING) if ( _Objects_Is_local_id( new_owner->Object.id ) ) #endif { ++new_owner->resource_count; - _Thread_Raise_priority( new_owner, the_mutex->priority_ceiling ); + _Thread_Priority_add( + new_owner, + &the_mutex->Priority_ceiling, + queue_context + ); } - _Thread_queue_Unblock_critical( - unblock, + _Thread_queue_Extract_critical( &the_mutex->Recursive.Mutex.Wait_queue.Queue, + CORE_MUTEX_TQ_OPERATIONS, new_owner, - &queue_context->Lock_context.Lock_context + queue_context ); } else { _CORE_mutex_Release( &the_mutex->Recursive.Mutex, queue_context ); } - _CORE_mutex_Restore_priority( executing ); + _Thread_Priority_update( queue_context ); + _Thread_Dispatch_enable( cpu_self ); return STATUS_SUCCESSFUL; } -- cgit v1.2.3