mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-09-20 19:58:32 +08:00
@@ -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
|
||||
|
||||
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 ( 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_Acquire_critical( scheduler, &lock_context );
|
||||
|
||||
#if defined(RTEMS_SMP)
|
||||
needs_help =
|
||||
#endif
|
||||
( *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 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
if ( _Scheduler_SMP_Node_state( node ) == SCHEDULER_SMP_NODE_SCHEDULED ) {
|
||||
node_state = _Scheduler_SMP_Node_state( node );
|
||||
|
||||
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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user