[PATCH 10/14] score: Use thread state lock for current state
Sebastian Huber
sebastian.huber at embedded-brains.de
Wed May 11 13:23:37 UTC 2016
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
More information about the devel
mailing list