[PATCH 17/30] score: Yield support for new SMP helping protocol
Sebastian Huber
sebastian.huber at embedded-brains.de
Mon Oct 31 08:51:48 UTC 2016
Update #2556.
---
cpukit/score/include/rtems/score/schedulerimpl.h | 58 ++++++++++++++++++----
.../score/include/rtems/score/schedulersmpimpl.h | 11 ++--
testsuites/smptests/smpmutex01/init.c | 52 +++++++++++++++++++
3 files changed, 107 insertions(+), 14 deletions(-)
diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h
index dbb17a8..ea32e00 100644
--- a/cpukit/score/include/rtems/score/schedulerimpl.h
+++ b/cpukit/score/include/rtems/score/schedulerimpl.h
@@ -288,29 +288,65 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Ask_for_help_if_necessary(
*/
RTEMS_INLINE_ROUTINE void _Scheduler_Yield( Thread_Control *the_thread )
{
+#if defined(RTEMS_SMP)
+ Chain_Node *node;
+ const Chain_Node *tail;
+ Scheduler_Node *scheduler_node;
const Scheduler_Control *scheduler;
ISR_lock_Context lock_context;
-#if defined(RTEMS_SMP)
Thread_Control *needs_help;
-#endif
- scheduler = _Scheduler_Get( the_thread );
+ node = _Chain_First( &the_thread->Scheduler.Scheduler_nodes );
+ tail = _Chain_Immutable_tail( &the_thread->Scheduler.Scheduler_nodes );
+
+ scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
+ scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
+
_Scheduler_Acquire_critical( scheduler, &lock_context );
+ needs_help = ( *scheduler->Operations.yield )(
+ scheduler,
+ the_thread,
+ _Thread_Scheduler_get_home_node( the_thread )
+ );
+ _Scheduler_Ask_for_help_if_necessary( needs_help );
+ _Scheduler_Release_critical( scheduler, &lock_context );
-#if defined(RTEMS_SMP)
- needs_help =
-#endif
+ if ( needs_help != the_thread ) {
+ return;
+ }
+
+ node = _Chain_Next( node );
+
+ while ( node != tail ) {
+ bool success;
+
+ scheduler_node = SCHEDULER_NODE_OF_THREAD_SCHEDULER_NODE( node );
+ scheduler = _Scheduler_Node_get_scheduler( scheduler_node );
+
+ _Scheduler_Acquire_critical( scheduler, &lock_context );
+ success = ( *scheduler->Operations.ask_for_help )(
+ scheduler,
+ the_thread,
+ scheduler_node
+ );
+ _Scheduler_Release_critical( scheduler, &lock_context );
+
+ if ( success ) {
+ break;
+ }
+
+ node = _Chain_Next( node );
+ }
+#else
+ const Scheduler_Control *scheduler;
+
+ scheduler = _Scheduler_Get( the_thread );
( *scheduler->Operations.yield )(
scheduler,
the_thread,
_Thread_Scheduler_get_home_node( the_thread )
);
-
-#if defined(RTEMS_SMP)
- _Scheduler_Ask_for_help_if_necessary( needs_help );
#endif
-
- _Scheduler_Release_critical( scheduler, &lock_context );
}
/**
diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h
index 8f9bf2f..0e7d358 100644
--- a/cpukit/score/include/rtems/score/schedulersmpimpl.h
+++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h
@@ -1138,16 +1138,21 @@ static inline Thread_Control *_Scheduler_SMP_Yield(
Scheduler_SMP_Enqueue_scheduled enqueue_scheduled_fifo
)
{
- Thread_Control *needs_help;
+ Thread_Control *needs_help;
+ Scheduler_SMP_Node_state node_state;
+
+ node_state = _Scheduler_SMP_Node_state( node );
- if ( _Scheduler_SMP_Node_state( node ) == SCHEDULER_SMP_NODE_SCHEDULED ) {
+ if ( node_state == SCHEDULER_SMP_NODE_SCHEDULED ) {
_Scheduler_SMP_Extract_from_scheduled( node );
needs_help = ( *enqueue_scheduled_fifo )( context, node );
- } else {
+ } else if ( node_state == SCHEDULER_SMP_NODE_READY ) {
( *extract_from_ready )( context, node );
needs_help = ( *enqueue_fifo )( context, node, NULL );
+ } else {
+ needs_help = thread;
}
return needs_help;
diff --git a/testsuites/smptests/smpmutex01/init.c b/testsuites/smptests/smpmutex01/init.c
index 8e499b4..33b7e93 100644
--- a/testsuites/smptests/smpmutex01/init.c
+++ b/testsuites/smptests/smpmutex01/init.c
@@ -313,6 +313,14 @@ static void check_generations(test_context *ctx, task_id a, task_id b)
}
}
+static void yield(void)
+{
+ rtems_status_code sc;
+
+ sc = rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
+ rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
static void set_prio(test_context *ctx, task_id id, rtems_task_priority prio)
{
rtems_status_code sc;
@@ -858,6 +866,49 @@ static void test_omip_timeout(test_context *ctx)
release(ctx);
}
+static void test_omip_yield(test_context *ctx)
+{
+ assert_cpu(0);
+ obtain(ctx);
+ assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
+ assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
+
+ request(ctx, B_5_0, REQ_MTX_OBTAIN);
+ assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
+ assert_prio_by_scheduler(ctx, M, SCHED_B, 5);
+ check_generations(ctx, NONE, NONE);
+
+ clear_done(ctx);
+ send_event(ctx, H_A, REQ_SET_DONE);
+ yield();
+ assert_cpu(1);
+ wait_for_done(ctx);
+
+ clear_done(ctx);
+ send_event(ctx, H_B, REQ_SET_DONE);
+ set_prio(ctx, H_B, 5);
+ yield();
+ assert_cpu(1);
+ rtems_test_assert(!is_done(ctx));
+
+ set_prio(ctx, H_B, 4);
+ assert_cpu(0);
+
+ wait_for_done(ctx);
+ set_prio(ctx, H_B, 6);
+
+ release(ctx);
+ sync_with_helper(ctx);
+ assert_prio_by_scheduler(ctx, M, SCHED_A, 3);
+ assert_prio_by_scheduler(ctx, M, SCHED_B, PRIO_NONE);
+ check_generations(ctx, B_5_0, NONE);
+
+ request(ctx, B_5_0, REQ_MTX_RELEASE);
+ assert_prio_by_scheduler(ctx, B_5_0, SCHED_A, PRIO_NONE);
+ assert_prio_by_scheduler(ctx, B_5_0, SCHED_B, 5);
+ check_generations(ctx, B_5_0, NONE);
+}
+
static void test(void)
{
test_context *ctx = &test_instance;
@@ -874,6 +925,7 @@ static void test(void)
test_omip_pre_emption(ctx);
test_omip_rescue(ctx);
test_omip_timeout(ctx);
+ test_omip_yield(ctx);
}
static void Init(rtems_task_argument arg)
--
1.8.4.5
More information about the devel
mailing list