diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-10-21 09:23:58 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-11-02 10:05:43 +0100 |
commit | 3a2724805421098df505c0acea106fb294bc2f6a (patch) | |
tree | 07b225c4fdc140786851750df34433526ed2ddff /cpukit/score/include/rtems/score/mrspimpl.h | |
parent | score: Use scheduler instance specific locks (diff) | |
download | rtems-3a2724805421098df505c0acea106fb294bc2f6a.tar.bz2 |
score: First part of new MrsP implementation
Update #2556.
Diffstat (limited to 'cpukit/score/include/rtems/score/mrspimpl.h')
-rw-r--r-- | cpukit/score/include/rtems/score/mrspimpl.h | 284 |
1 files changed, 79 insertions, 205 deletions
diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h index 92cc56614c..4b4e8c3c67 100644 --- a/cpukit/score/include/rtems/score/mrspimpl.h +++ b/cpukit/score/include/rtems/score/mrspimpl.h @@ -20,9 +20,6 @@ #if defined(RTEMS_SMP) #include <rtems/score/assert.h> -#include <rtems/score/chainimpl.h> -#include <rtems/score/resourceimpl.h> -#include <rtems/score/schedulerimpl.h> #include <rtems/score/status.h> #include <rtems/score/threadqimpl.h> #include <rtems/score/watchdogimpl.h> @@ -38,28 +35,7 @@ extern "C" { * @{ */ -/** - * @brief Internal state used for MRSP_Rival::status to indicate that this - * rival waits for resource ownership. - */ -#define MRSP_WAIT_FOR_OWNERSHIP STATUS_MINUS_ONE - -/* - * FIXME: Operations with the resource dependency tree are protected by the - * global scheduler lock. Since the scheduler lock should be scheduler - * instance specific in the future this will only work temporarily. A more - * sophisticated locking strategy is necessary. - */ - -RTEMS_INLINE_ROUTINE void _MRSP_Giant_acquire( ISR_lock_Context *lock_context ) -{ - /* FIXME: MrsP protocol implementation will be reworked soon */ -} - -RTEMS_INLINE_ROUTINE void _MRSP_Giant_release( ISR_lock_Context *lock_context ) -{ - /* FIXME: MrsP protocol implementation will be reworked soon */ -} +#define MRSP_TQ_OPERATIONS &_Thread_queue_Operations_priority_inherit RTEMS_INLINE_ROUTINE void _MRSP_Acquire_critical( MRSP_Control *mrsp, @@ -77,6 +53,19 @@ RTEMS_INLINE_ROUTINE void _MRSP_Release( _Thread_queue_Release( &mrsp->Wait_queue, queue_context ); } +RTEMS_INLINE_ROUTINE Thread_Control *_MRSP_Get_owner( MRSP_Control *mrsp ) +{ + return mrsp->Wait_queue.Queue.owner; +} + +RTEMS_INLINE_ROUTINE void _MRSP_Set_owner( + MRSP_Control *mrsp, + Thread_Control *owner +) +{ + mrsp->Wait_queue.Queue.owner = owner; +} + RTEMS_INLINE_ROUTINE Priority_Control _MRSP_Get_priority( const MRSP_Control *mrsp, const Scheduler_Control *scheduler @@ -149,23 +138,23 @@ RTEMS_INLINE_ROUTINE void _MRSP_Remove_priority( RTEMS_INLINE_ROUTINE void _MRSP_Replace_priority( MRSP_Control *mrsp, Thread_Control *thread, - MRSP_Rival *rival + Priority_Node *ceiling_priority ) { ISR_lock_Context lock_context; - _Thread_Wait_acquire_default_critical( thread, &lock_context ); + _Thread_Wait_acquire_default( thread, &lock_context ); _Thread_Priority_replace( thread, - &rival->Ceiling_priority, + ceiling_priority, &mrsp->Ceiling_priority ); - _Thread_Wait_release_default_critical( thread, &lock_context ); + _Thread_Wait_release_default( thread, &lock_context ); } RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership( MRSP_Control *mrsp, - Thread_Control *new_owner, + Thread_Control *executing, Thread_queue_Context *queue_context ) { @@ -174,7 +163,7 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership( status = _MRSP_Raise_priority( mrsp, - new_owner, + executing, &mrsp->Ceiling_priority, queue_context ); @@ -184,17 +173,12 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Claim_ownership( return status; } - _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource ); - _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node ); - _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER ); - + _MRSP_Set_owner( mrsp, executing ); cpu_self = _Thread_Dispatch_disable_critical( &queue_context->Lock_context.Lock_context ); _MRSP_Release( mrsp, queue_context ); - - _Thread_Priority_update( queue_context ); - + _Thread_Priority_and_sticky_update( executing, 1 ); _Thread_Dispatch_enable( cpu_self ); return STATUS_SUCCESSFUL; } @@ -234,74 +218,23 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Initialize( } } - _Resource_Initialize( &mrsp->Resource ); - _Chain_Initialize_empty( &mrsp->Rivals ); _Thread_queue_Initialize( &mrsp->Wait_queue ); - return STATUS_SUCCESSFUL; } -RTEMS_INLINE_ROUTINE void _MRSP_Timeout( Watchdog_Control *watchdog ) -{ - MRSP_Rival *rival; - MRSP_Control *mrsp; - Thread_Control *thread; - Thread_queue_Context queue_context; - - rival = RTEMS_CONTAINER_OF( watchdog, MRSP_Rival, Watchdog ); - mrsp = rival->resource; - thread = rival->thread; - - _Thread_queue_Context_initialize( &queue_context ); - _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context ); - _MRSP_Acquire_critical( mrsp, &queue_context ); - - if ( rival->status == MRSP_WAIT_FOR_OWNERSHIP ) { - ISR_lock_Context giant_lock_context; - - _MRSP_Remove_priority( thread, &rival->Ceiling_priority, &queue_context ); - - _MRSP_Giant_acquire( &giant_lock_context ); - - _Chain_Extract_unprotected( &rival->Node ); - _Resource_Node_extract( &thread->Resource_node ); - _Resource_Node_set_dependency( &thread->Resource_node, NULL ); - _Scheduler_Thread_change_help_state( thread, rival->initial_help_state ); - _Scheduler_Thread_change_resource_root( thread, thread ); - - _MRSP_Giant_release( &giant_lock_context ); - - rival->status = STATUS_TIMEOUT; - - _MRSP_Release( mrsp, &queue_context ); - - _Thread_Priority_update( &queue_context ); - } else { - _MRSP_Release( mrsp, &queue_context ); - } -} - RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership( MRSP_Control *mrsp, - Resource_Node *owner, Thread_Control *executing, Thread_queue_Context *queue_context ) { - Status_Control status; - MRSP_Rival rival; - Thread_Life_state life_state; - Per_CPU_Control *cpu_self; - ISR_lock_Context giant_lock_context; - ISR_Level level; - Watchdog_Interval timeout; - - _Assert( queue_context->timeout_discipline == WATCHDOG_RELATIVE ); + Status_Control status; + Priority_Node ceiling_priority; status = _MRSP_Raise_priority( mrsp, executing, - &rival.Ceiling_priority, + &ceiling_priority, queue_context ); @@ -310,64 +243,38 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Wait_for_ownership( return status; } - rival.thread = executing; - rival.resource = mrsp; - _Chain_Initialize_node( &rival.Node ); - - _MRSP_Giant_acquire( &giant_lock_context ); - - rival.initial_help_state = - _Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_ACTIVE_RIVAL ); - rival.status = MRSP_WAIT_FOR_OWNERSHIP; - - _Chain_Initialize_node( &rival.Node ); - _Chain_Append_unprotected( &mrsp->Rivals, &rival.Node ); - _Resource_Add_rival( &mrsp->Resource, &executing->Resource_node ); - _Resource_Node_set_dependency( &executing->Resource_node, &mrsp->Resource ); - _Scheduler_Thread_change_resource_root( - executing, - THREAD_RESOURCE_NODE_TO_THREAD( _Resource_Node_get_root( owner ) ) + _Thread_queue_Context_set_deadlock_callout( + queue_context, + _Thread_queue_Deadlock_status ); - - _MRSP_Giant_release( &giant_lock_context ); - - cpu_self = _Thread_Dispatch_disable_critical( - &queue_context->Lock_context.Lock_context + status = _Thread_queue_Enqueue_sticky( + &mrsp->Wait_queue.Queue, + MRSP_TQ_OPERATIONS, + executing, + queue_context ); - _MRSP_Release( mrsp, queue_context ); - - _Thread_Priority_update( queue_context ); - timeout = (Watchdog_Interval) queue_context->timeout; - - if ( timeout > 0 ) { - _Watchdog_Preinitialize( &rival.Watchdog, cpu_self ); - _Watchdog_Initialize( &rival.Watchdog, _MRSP_Timeout ); - _ISR_Local_disable( level ); - _Watchdog_Per_CPU_insert_relative( &rival.Watchdog, cpu_self, timeout ); - _ISR_Local_enable( level ); - } - - life_state = _Thread_Set_life_protection( THREAD_LIFE_PROTECTED ); - _Thread_Dispatch_enable( cpu_self ); - - _Assert( _Debug_Is_thread_dispatching_allowed() ); - - /* Wait for state change */ - do { - status = rival.status; - } while ( status == MRSP_WAIT_FOR_OWNERSHIP ); + if ( status == STATUS_SUCCESSFUL ) { + _MRSP_Replace_priority( mrsp, executing, &ceiling_priority ); + } else { + Thread_queue_Context queue_context; + Per_CPU_Control *cpu_self; + int sticky_level_change; - _Thread_Set_life_protection( life_state ); + if ( status != STATUS_DEADLOCK ) { + sticky_level_change = -1; + } else { + sticky_level_change = 0; + } - if ( timeout > 0 ) { - _ISR_Local_disable( level ); - _Watchdog_Per_CPU_remove( - &rival.Watchdog, - cpu_self, - &cpu_self->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ] + _ISR_lock_ISR_disable( &queue_context.Lock_context.Lock_context ); + _MRSP_Remove_priority( executing, &ceiling_priority, &queue_context ); + cpu_self = _Thread_Dispatch_disable_critical( + &queue_context.Lock_context.Lock_context ); - _ISR_Local_enable( level ); + _ISR_lock_ISR_enable( &queue_context.Lock_context.Lock_context ); + _Thread_Priority_and_sticky_update( executing, sticky_level_change ); + _Thread_Dispatch_enable( cpu_self ); } return status; @@ -381,22 +288,21 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Seize( ) { Status_Control status; - Resource_Node *owner; + Thread_Control *owner; _MRSP_Acquire_critical( mrsp, queue_context ); - owner = _Resource_Get_owner( &mrsp->Resource ); + owner = _MRSP_Get_owner( mrsp ); if ( owner == NULL ) { status = _MRSP_Claim_ownership( mrsp, executing, queue_context ); - } else if ( - wait - && _Resource_Node_get_root( owner ) != &executing->Resource_node - ) { - status = _MRSP_Wait_for_ownership( mrsp, owner, executing, queue_context ); + } else if ( owner == executing ) { + _MRSP_Release( mrsp, queue_context ); + status = STATUS_UNAVAILABLE; + } else if ( wait ) { + status = _MRSP_Wait_for_ownership( mrsp, executing, queue_context ); } else { _MRSP_Release( mrsp, queue_context ); - /* Not available, nested access or deadlock */ status = STATUS_UNAVAILABLE; } @@ -409,77 +315,45 @@ RTEMS_INLINE_ROUTINE Status_Control _MRSP_Surrender( Thread_queue_Context *queue_context ) { - ISR_lock_Context giant_lock_context; - Per_CPU_Control *cpu_self; + Thread_queue_Heads *heads; - if ( _Resource_Get_owner( &mrsp->Resource ) != &executing->Resource_node ) { + if ( _MRSP_Get_owner( mrsp ) != executing ) { _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context ); return STATUS_NOT_OWNER; } - if ( - !_Resource_Is_most_recently_obtained( - &mrsp->Resource, - &executing->Resource_node - ) - ) { - _ISR_lock_ISR_enable( &queue_context->Lock_context.Lock_context ); - return STATUS_RELEASE_ORDER_VIOLATION; - } - _MRSP_Acquire_critical( mrsp, queue_context ); - _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context ); - _MRSP_Giant_acquire( &giant_lock_context ); - - _Resource_Extract( &mrsp->Resource ); - if ( _Chain_Is_empty( &mrsp->Rivals ) ) { - _Resource_Set_owner( &mrsp->Resource, NULL ); - } else { - MRSP_Rival *rival; - Thread_Control *new_owner; - - rival = (MRSP_Rival *) _Chain_Get_first_unprotected( &mrsp->Rivals ); - - /* - * This must be inside the critical section since the status prevents a - * potential double extraction in _MRSP_Timeout(). - */ - rival->status = STATUS_SUCCESSFUL; - - new_owner = rival->thread; + _MRSP_Set_owner( mrsp, NULL ); + _MRSP_Remove_priority( executing, &mrsp->Ceiling_priority, queue_context ); - _MRSP_Replace_priority( mrsp, new_owner, rival ); + heads = mrsp->Wait_queue.Queue.heads; - _Resource_Node_extract( &new_owner->Resource_node ); - _Resource_Node_set_dependency( &new_owner->Resource_node, NULL ); - _Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource ); - _Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node ); - _Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER ); - _Scheduler_Thread_change_resource_root( new_owner, new_owner ); - } + if ( heads == NULL ) { + Per_CPU_Control *cpu_self; - if ( !_Resource_Node_owns_resources( &executing->Resource_node ) ) { - _Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_YOURSELF ); + cpu_self = _Thread_Dispatch_disable_critical( + &queue_context->Lock_context.Lock_context + ); + _MRSP_Release( mrsp, queue_context ); + _Thread_Priority_and_sticky_update( executing, -1 ); + _Thread_Dispatch_enable( cpu_self ); + return STATUS_SUCCESSFUL; } - _MRSP_Giant_release( &giant_lock_context ); - - cpu_self = _Thread_Dispatch_disable_critical( - &queue_context->Lock_context.Lock_context + _Thread_queue_Surrender_sticky( + &mrsp->Wait_queue.Queue, + heads, + executing, + queue_context, + MRSP_TQ_OPERATIONS ); - _MRSP_Release( mrsp, queue_context ); - - _Thread_Priority_update( queue_context ); - - _Thread_Dispatch_enable( cpu_self ); - return STATUS_SUCCESSFUL; } RTEMS_INLINE_ROUTINE Status_Control _MRSP_Can_destroy( MRSP_Control *mrsp ) { - if ( _Resource_Get_owner( &mrsp->Resource ) != NULL ) { + if ( _MRSP_Get_owner( mrsp ) != NULL ) { return STATUS_RESOURCE_IN_USE; } |