summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/rtems/score/mrspimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/score/include/rtems/score/mrspimpl.h')
-rw-r--r--cpukit/score/include/rtems/score/mrspimpl.h136
1 files changed, 98 insertions, 38 deletions
diff --git a/cpukit/score/include/rtems/score/mrspimpl.h b/cpukit/score/include/rtems/score/mrspimpl.h
index 05aee42a22..82ecb07047 100644
--- a/cpukit/score/include/rtems/score/mrspimpl.h
+++ b/cpukit/score/include/rtems/score/mrspimpl.h
@@ -36,6 +36,23 @@ extern "C" {
* @{
*/
+/*
+ * 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 )
+{
+ _ISR_lock_Acquire( &_Scheduler_Lock, lock_context );
+}
+
+RTEMS_INLINE_ROUTINE void _MRSP_Giant_release( ISR_lock_Context *lock_context )
+{
+ _ISR_lock_Release( &_Scheduler_Lock, lock_context );
+}
+
RTEMS_INLINE_ROUTINE bool _MRSP_Restore_priority_filter(
Thread_Control *thread,
Priority_Control *new_priority,
@@ -74,14 +91,23 @@ RTEMS_INLINE_ROUTINE void _MRSP_Claim_ownership(
MRSP_Control *mrsp,
Thread_Control *new_owner,
Priority_Control initial_priority,
- Priority_Control ceiling_priority
+ Priority_Control ceiling_priority,
+ ISR_lock_Context *lock_context
)
{
+ Per_CPU_Control *cpu_self;
+
_Resource_Node_add_resource( &new_owner->Resource_node, &mrsp->Resource );
_Resource_Set_owner( &mrsp->Resource, &new_owner->Resource_node );
mrsp->initial_priority_of_owner = initial_priority;
- _Thread_Raise_priority( new_owner, ceiling_priority );
_Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER );
+
+ cpu_self = _Thread_Dispatch_disable_critical();
+ _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context );
+
+ _Thread_Raise_priority( new_owner, ceiling_priority );
+
+ _Thread_Dispatch_enable( cpu_self );
}
RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Initialize(
@@ -111,6 +137,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Initialize(
_Resource_Initialize( &mrsp->Resource );
_Chain_Initialize_empty( &mrsp->Rivals );
+ _ISR_lock_Initialize( &mrsp->Lock, "MrsP" );
return MRSP_SUCCESSFUL;
}
@@ -138,27 +165,32 @@ RTEMS_INLINE_ROUTINE void _MRSP_Timeout(
)
{
MRSP_Rival *rival = arg;
+ MRSP_Control *mrsp = rival->resource;
Thread_Control *thread = rival->thread;
- ISR_Level level;
+ ISR_lock_Context lock_context;
(void) id;
- _ISR_Disable( level );
+ _ISR_lock_ISR_disable_and_acquire( &mrsp->Lock, &lock_context );
if ( rival->status == MRSP_WAIT_FOR_OWNERSHIP ) {
- rival->status = MRSP_TIMEOUT;
+ ISR_lock_Context giant_lock_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 );
-
- _ISR_Enable( level );
-
_Scheduler_Thread_change_help_state( thread, rival->initial_help_state );
_Scheduler_Thread_change_resource_root( thread, thread );
- _MRSP_Restore_priority( thread, rival->initial_priority );
+
+ _MRSP_Giant_release( &giant_lock_context );
+
+ rival->status = MRSP_TIMEOUT;
+
+ _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, &lock_context );
} else {
- _ISR_Enable( level );
+ _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, &lock_context );
}
}
@@ -168,35 +200,41 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
Thread_Control *executing,
Priority_Control initial_priority,
Priority_Control ceiling_priority,
- Watchdog_Interval timeout
+ Watchdog_Interval timeout,
+ ISR_lock_Context *lock_context
)
{
MRSP_Status status;
MRSP_Rival rival;
bool initial_life_protection;
- ISR_Level level;
+ Per_CPU_Control *cpu_self;
+ ISR_lock_Context giant_lock_context;
rival.thread = executing;
+ rival.resource = mrsp;
rival.initial_priority = initial_priority;
+
+ _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;
- _Thread_Raise_priority( executing, ceiling_priority );
-
- _ISR_Disable( level );
-
_Chain_Append_unprotected( &mrsp->Rivals, &rival.Node );
_Resource_Add_rival( &mrsp->Resource, &executing->Resource_node );
_Resource_Node_set_dependency( &executing->Resource_node, &mrsp->Resource );
-
- _ISR_Enable( level );
-
_Scheduler_Thread_change_resource_root(
executing,
THREAD_RESOURCE_NODE_TO_THREAD( _Resource_Node_get_root( owner ) )
);
+ _MRSP_Giant_release( &giant_lock_context );
+
+ cpu_self = _Thread_Dispatch_disable_critical();
+ _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context );
+
+ _Thread_Raise_priority( executing, ceiling_priority );
+
if ( timeout > 0 ) {
_Watchdog_Initialize(
&executing->Timer,
@@ -208,7 +246,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
}
initial_life_protection = _Thread_Set_life_protection( true );
- _Thread_Enable_dispatch();
+ _Thread_Dispatch_enable( cpu_self );
_Assert( _Debug_Is_thread_dispatching_allowed() );
@@ -217,11 +255,14 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Wait_for_ownership(
status = rival.status;
} while ( status == MRSP_WAIT_FOR_OWNERSHIP );
- _Thread_Disable_dispatch();
_Thread_Set_life_protection( initial_life_protection );
if ( timeout > 0 ) {
_Watchdog_Remove_ticks( &executing->Timer );
+
+ if ( status == MRSP_TIMEOUT ) {
+ _MRSP_Restore_priority( executing, initial_priority );
+ }
}
return status;
@@ -231,7 +272,8 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Obtain(
MRSP_Control *mrsp,
Thread_Control *executing,
bool wait,
- Watchdog_Interval timeout
+ Watchdog_Interval timeout,
+ ISR_lock_Context *lock_context
)
{
MRSP_Status status;
@@ -247,31 +289,37 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Obtain(
Resource_Node *owner;
if ( !priority_ok) {
+ _ISR_lock_ISR_enable( lock_context );
return MRSP_INVALID_PRIORITY;
}
+ _ISR_lock_Acquire( &mrsp->Lock, lock_context );
owner = _Resource_Get_owner( &mrsp->Resource );
if ( owner == NULL ) {
_MRSP_Claim_ownership(
mrsp,
executing,
initial_priority,
- ceiling_priority
+ ceiling_priority,
+ lock_context
);
status = MRSP_SUCCESSFUL;
- } else if ( _Resource_Node_get_root( owner ) == &executing->Resource_node ) {
- /* Nested access or deadlock */
- status = MRSP_UNSATISFIED;
- } else if ( wait ) {
+ } else if (
+ wait
+ && _Resource_Node_get_root( owner ) != &executing->Resource_node
+ ) {
status = _MRSP_Wait_for_ownership(
mrsp,
owner,
executing,
initial_priority,
ceiling_priority,
- timeout
+ timeout,
+ lock_context
);
} else {
+ _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context );
+ /* Not available, nested access or deadlock */
status = MRSP_UNSATISFIED;
}
@@ -279,13 +327,17 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Obtain(
}
RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Release(
- MRSP_Control *mrsp,
- Thread_Control *executing
+ MRSP_Control *mrsp,
+ Thread_Control *executing,
+ ISR_lock_Context *lock_context
)
{
- ISR_Level level;
+ Priority_Control initial_priority;
+ Per_CPU_Control *cpu_self;
+ ISR_lock_Context giant_lock_context;
if ( _Resource_Get_owner( &mrsp->Resource ) != &executing->Resource_node ) {
+ _ISR_lock_ISR_enable( lock_context );
return MRSP_NOT_OWNER_OF_RESOURCE;
}
@@ -295,18 +347,19 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Release(
&executing->Resource_node
)
) {
+ _ISR_lock_ISR_enable( lock_context );
return MRSP_INCORRECT_STATE;
}
- _MRSP_Restore_priority( executing, mrsp->initial_priority_of_owner );
+ initial_priority = mrsp->initial_priority_of_owner;
+
+ _ISR_lock_Acquire( &mrsp->Lock, lock_context );
- _ISR_Disable( level );
+ _MRSP_Giant_acquire( &giant_lock_context );
_Resource_Extract( &mrsp->Resource );
if ( _Chain_Is_empty( &mrsp->Rivals ) ) {
- _ISR_Enable( level );
-
_Resource_Set_owner( &mrsp->Resource, NULL );
} else {
MRSP_Rival *rival = (MRSP_Rival *)
@@ -325,9 +378,6 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Release(
_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 );
-
- _ISR_Enable( level );
-
_Scheduler_Thread_change_help_state( new_owner, SCHEDULER_HELP_ACTIVE_OWNER );
_Scheduler_Thread_change_resource_root( new_owner, new_owner );
}
@@ -336,6 +386,15 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Release(
_Scheduler_Thread_change_help_state( executing, SCHEDULER_HELP_YOURSELF );
}
+ _MRSP_Giant_release( &giant_lock_context );
+
+ cpu_self = _Thread_Dispatch_disable_critical();
+ _ISR_lock_Release_and_ISR_enable( &mrsp->Lock, lock_context );
+
+ _MRSP_Restore_priority( executing, initial_priority );
+
+ _Thread_Dispatch_enable( cpu_self );
+
return MRSP_SUCCESSFUL;
}
@@ -345,6 +404,7 @@ RTEMS_INLINE_ROUTINE MRSP_Status _MRSP_Destroy( MRSP_Control *mrsp )
return MRSP_RESOUCE_IN_USE;
}
+ _ISR_lock_Destroy( &mrsp->Lock );
_Workspace_Free( mrsp->ceiling_priorities );
return MRSP_SUCCESSFUL;