From 6eba7c857b9e72bc4ed8e55f0c9538c45631484f Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 10 Jun 2013 16:15:46 +0200 Subject: scheduler: Specify thread of yield operation The yielding thread of the yield operation is now specified by a parameter. The tick operation may be performed for each executing thread in a SMP configuration. --- cpukit/posix/src/nanosleep.c | 21 ++++++++++++++------- cpukit/posix/src/sched_yield.c | 2 +- cpukit/rtems/src/taskwakeafter.c | 18 +++++++++++++----- cpukit/score/include/rtems/score/scheduler.h | 8 ++++++-- cpukit/score/include/rtems/score/scheduleredf.h | 8 +++++--- .../score/include/rtems/score/schedulerpriority.h | 8 +++++--- cpukit/score/include/rtems/score/schedulersimple.h | 8 +++++--- cpukit/score/inline/rtems/score/scheduler.inl | 16 +++++++++------- cpukit/score/src/scheduleredfyield.c | 13 ++++++------- cpukit/score/src/schedulerprioritytick.c | 2 +- cpukit/score/src/schedulerpriorityyield.c | 14 ++++++-------- cpukit/score/src/schedulersimpleyield.c | 8 +++----- 12 files changed, 74 insertions(+), 52 deletions(-) diff --git a/cpukit/posix/src/nanosleep.c b/cpukit/posix/src/nanosleep.c index b59b9934b0..7d37480218 100644 --- a/cpukit/posix/src/nanosleep.c +++ b/cpukit/posix/src/nanosleep.c @@ -39,6 +39,12 @@ int nanosleep( struct timespec *rmtp ) { + /* + * It is critical to obtain the executing thread after thread dispatching is + * disabled on SMP configurations. + */ + Thread_Control *executing; + Watchdog_Interval ticks; @@ -61,7 +67,8 @@ int nanosleep( if ( !ticks ) { _Thread_Disable_dispatch(); - _Scheduler_Yield(); + executing = _Thread_Executing; + _Scheduler_Yield( executing ); _Thread_Enable_dispatch(); if ( rmtp ) { rmtp->tv_sec = 0; @@ -74,24 +81,24 @@ int nanosleep( * Block for the desired amount of time */ _Thread_Disable_dispatch(); + executing = _Thread_Executing; _Thread_Set_state( - _Thread_Executing, + executing, STATES_DELAYING | STATES_INTERRUPTIBLE_BY_SIGNAL ); _Watchdog_Initialize( - &_Thread_Executing->Timer, + &executing->Timer, _Thread_Delay_ended, - _Thread_Executing->Object.id, + executing->Object.id, NULL ); - _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks ); + _Watchdog_Insert_ticks( &executing->Timer, ticks ); _Thread_Enable_dispatch(); /* calculate time remaining */ if ( rmtp ) { - ticks -= - _Thread_Executing->Timer.stop_time - _Thread_Executing->Timer.start_time; + ticks -= executing->Timer.stop_time - executing->Timer.start_time; _Timespec_From_ticks( ticks, rmtp ); diff --git a/cpukit/posix/src/sched_yield.c b/cpukit/posix/src/sched_yield.c index 207cbb286a..d9e5d9b852 100644 --- a/cpukit/posix/src/sched_yield.c +++ b/cpukit/posix/src/sched_yield.c @@ -32,7 +32,7 @@ int sched_yield( void ) { _Thread_Disable_dispatch(); - _Scheduler_Yield(); + _Scheduler_Yield( _Thread_Executing ); _Thread_Enable_dispatch(); return 0; } diff --git a/cpukit/rtems/src/taskwakeafter.c b/cpukit/rtems/src/taskwakeafter.c index 1df86553f8..665423409b 100644 --- a/cpukit/rtems/src/taskwakeafter.c +++ b/cpukit/rtems/src/taskwakeafter.c @@ -38,18 +38,26 @@ rtems_status_code rtems_task_wake_after( rtems_interval ticks ) { + /* + * It is critical to obtain the executing thread after thread dispatching is + * disabled on SMP configurations. + */ + Thread_Control *executing; + _Thread_Disable_dispatch(); + executing = _Thread_Executing; + if ( ticks == 0 ) { - _Scheduler_Yield(); + _Scheduler_Yield( executing ); } else { - _Thread_Set_state( _Thread_Executing, STATES_DELAYING ); + _Thread_Set_state( executing, STATES_DELAYING ); _Watchdog_Initialize( - &_Thread_Executing->Timer, + &executing->Timer, _Thread_Delay_ended, - _Thread_Executing->Object.id, + executing->Object.id, NULL ); - _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks ); + _Watchdog_Insert_ticks( &executing->Timer, ticks ); } _Thread_Enable_dispatch(); return RTEMS_SUCCESSFUL; diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h index 9e08b23e4f..aa40e9ba9f 100644 --- a/cpukit/score/include/rtems/score/scheduler.h +++ b/cpukit/score/include/rtems/score/scheduler.h @@ -49,8 +49,12 @@ typedef struct { /** Implements the scheduling decision logic (policy). */ void ( *schedule )(void); - /** Voluntarily yields the processor per the scheduling policy. */ - void ( *yield )(void); + /** + * @brief Voluntarily yields the processor per the scheduling policy. + * + * @see _Scheduler_Yield(). + */ + void ( *yield )( Thread_Control *thread ); /** Removes the given thread from scheduling decisions. */ void ( *block )(Thread_Control *); diff --git a/cpukit/score/include/rtems/score/scheduleredf.h b/cpukit/score/include/rtems/score/scheduleredf.h index e84b3f5909..7846067a7d 100644 --- a/cpukit/score/include/rtems/score/scheduleredf.h +++ b/cpukit/score/include/rtems/score/scheduleredf.h @@ -189,11 +189,13 @@ void _Scheduler_EDF_Unblock( * transfer control of the processor to another thread in the queue with * equal deadline. This does not have to happen very often. * - * This routine will remove the running THREAD from the ready queue - * and place back. The rbtree ready queue is responsible for FIFO ordering + * This routine will remove the specified THREAD from the ready queue + * and place it back. The rbtree ready queue is responsible for FIFO ordering * in such a case. + * + * @param[in/out] thread The yielding thread. */ -void _Scheduler_EDF_Yield( void ); +void _Scheduler_EDF_Yield( Thread_Control *thread ); /** * @brief Put @a the_thread to the rbtree ready queue. diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h index 81c3582e76..f0582c1315 100644 --- a/cpukit/score/include/rtems/score/schedulerpriority.h +++ b/cpukit/score/include/rtems/score/schedulerpriority.h @@ -145,12 +145,12 @@ void _Scheduler_priority_Unblock( ); /** - * @brief Remove the running THREAD to the rear of this chain. + * @brief The specified THREAD yields. * * This routine is invoked when a thread wishes to voluntarily * transfer control of the processor to another thread in the queue. * - * This routine will remove the running THREAD from the ready queue + * This routine will remove the specified THREAD from the ready queue * and place it immediately at the rear of this chain. Reset timeslice * and yield the processor functions both use this routine, therefore if * reset is true and this is the only thread on the queue then the @@ -160,8 +160,10 @@ void _Scheduler_priority_Unblock( * - INTERRUPT LATENCY: * + ready chain * + select heir + * + * @param[in/out] thread The yielding thread. */ -void _Scheduler_priority_Yield( void ); +void _Scheduler_priority_Yield( Thread_Control *thread ); /** * @brief Puts @a the_thread on to the priority-based ready queue. diff --git a/cpukit/score/include/rtems/score/schedulersimple.h b/cpukit/score/include/rtems/score/schedulersimple.h index 6682074b7c..47b74befbe 100644 --- a/cpukit/score/include/rtems/score/schedulersimple.h +++ b/cpukit/score/include/rtems/score/schedulersimple.h @@ -74,15 +74,17 @@ void _Scheduler_simple_Schedule( void ); * * This routine is invoked when a thread wishes to voluntarily * transfer control of the processor to another thread in the queue. - * It will remove the running THREAD from the scheduler.informaiton + * It will remove the specified THREAD from the scheduler.informaiton * (where the ready queue is stored) and place it immediately at the * between the last entry of its priority and the next priority thread. * Reset timeslice and yield the processor functions both use this routine, * therefore if reset is true and this is the only thread on the queue then * the timeslice counter is reset. The heir THREAD will be updated if the * running is also the currently the heir. -*/ -void _Scheduler_simple_Yield( void ); + * + * @param[in/out] thread The yielding thread. + */ +void _Scheduler_simple_Yield( Thread_Control *thread ); /** * @brief Remove a simple-priority-based thread from the queue. diff --git a/cpukit/score/inline/rtems/score/scheduler.inl b/cpukit/score/inline/rtems/score/scheduler.inl index 3201c23e99..dc5bdcc7d2 100644 --- a/cpukit/score/inline/rtems/score/scheduler.inl +++ b/cpukit/score/inline/rtems/score/scheduler.inl @@ -55,16 +55,18 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Schedule( void ) } /** - * @brief Scheduler yield. + * @brief Scheduler yield with a particular thread. * - * This routine is invoked when a thread wishes to voluntarily - * transfer control of the processor to another thread. This routine - * always operates on the scheduler that 'owns' the currently executing - * thread. + * This routine is invoked when a thread wishes to voluntarily transfer control + * of the processor to another thread. + * + * @param[in] thread The yielding thread. */ -RTEMS_INLINE_ROUTINE void _Scheduler_Yield( void ) +RTEMS_INLINE_ROUTINE void _Scheduler_Yield( + Thread_Control *thread +) { - _Scheduler.Operations.yield(); + ( *_Scheduler.Operations.yield )( thread ); } /** diff --git a/cpukit/score/src/scheduleredfyield.c b/cpukit/score/src/scheduleredfyield.c index d6862540a0..4ba9f79b77 100644 --- a/cpukit/score/src/scheduleredfyield.c +++ b/cpukit/score/src/scheduleredfyield.c @@ -25,14 +25,13 @@ #include #include -void _Scheduler_EDF_Yield(void) +void _Scheduler_EDF_Yield( Thread_Control *thread ) { ISR_Level level; - Thread_Control *executing = _Thread_Executing; - Scheduler_EDF_Per_thread *executing_info = - (Scheduler_EDF_Per_thread *) executing->scheduler_info; - RBTree_Node *executing_node = &(executing_info->Node); + Scheduler_EDF_Per_thread *thread_info = + (Scheduler_EDF_Per_thread *) thread->scheduler_info; + RBTree_Node *thread_node = &(thread_info->Node); _ISR_Disable( level ); @@ -40,8 +39,8 @@ void _Scheduler_EDF_Yield(void) * The RBTree has more than one node, enqueue behind the tasks * with the same priority in case there are such ones. */ - _RBTree_Extract( &_Scheduler_EDF_Ready_queue, executing_node ); - _RBTree_Insert( &_Scheduler_EDF_Ready_queue, executing_node ); + _RBTree_Extract( &_Scheduler_EDF_Ready_queue, thread_node ); + _RBTree_Insert( &_Scheduler_EDF_Ready_queue, thread_node ); _ISR_Flash( level ); diff --git a/cpukit/score/src/schedulerprioritytick.c b/cpukit/score/src/schedulerprioritytick.c index afe6c76d34..7ce3efdb3a 100644 --- a/cpukit/score/src/schedulerprioritytick.c +++ b/cpukit/score/src/schedulerprioritytick.c @@ -68,7 +68,7 @@ void _Scheduler_priority_Tick( void ) * currently executing thread is placed at the rear of the * FIFO for this priority and a new heir is selected. */ - _Scheduler_Yield(); + _Scheduler_Yield( executing ); executing->cpu_time_budget = _Thread_Ticks_per_timeslice; } break; diff --git a/cpukit/score/src/schedulerpriorityyield.c b/cpukit/score/src/schedulerpriorityyield.c index c000125daf..4c2b5996c1 100644 --- a/cpukit/score/src/schedulerpriorityyield.c +++ b/cpukit/score/src/schedulerpriorityyield.c @@ -24,28 +24,26 @@ #include #include -void _Scheduler_priority_Yield(void) +void _Scheduler_priority_Yield( Thread_Control *thread ) { Scheduler_priority_Per_thread *sched_info; ISR_Level level; - Thread_Control *executing; Chain_Control *ready; - executing = _Thread_Executing; - sched_info = (Scheduler_priority_Per_thread *) executing->scheduler_info; + sched_info = (Scheduler_priority_Per_thread *) thread->scheduler_info; ready = sched_info->ready_chain; _ISR_Disable( level ); if ( !_Chain_Has_only_one_node( ready ) ) { - _Chain_Extract_unprotected( &executing->Object.Node ); - _Chain_Append_unprotected( ready, &executing->Object.Node ); + _Chain_Extract_unprotected( &thread->Object.Node ); + _Chain_Append_unprotected( ready, &thread->Object.Node ); _ISR_Flash( level ); - if ( _Thread_Is_heir( executing ) ) + if ( _Thread_Is_heir( thread ) ) _Thread_Heir = (Thread_Control *) _Chain_First( ready ); _Thread_Dispatch_necessary = true; } - else if ( !_Thread_Is_heir( executing ) ) + else if ( !_Thread_Is_heir( thread ) ) _Thread_Dispatch_necessary = true; _ISR_Enable( level ); diff --git a/cpukit/score/src/schedulersimpleyield.c b/cpukit/score/src/schedulersimpleyield.c index 1d5d48c7e5..cfbe7a4cba 100644 --- a/cpukit/score/src/schedulersimpleyield.c +++ b/cpukit/score/src/schedulersimpleyield.c @@ -24,21 +24,19 @@ #include #include -void _Scheduler_simple_Yield( void ) +void _Scheduler_simple_Yield( Thread_Control *thread ) { ISR_Level level; - Thread_Control *executing; - executing = _Thread_Executing; _ISR_Disable( level ); - _Scheduler_simple_Ready_queue_requeue(&_Scheduler, executing); + _Scheduler_simple_Ready_queue_requeue( &_Scheduler, thread ); _ISR_Flash( level ); _Scheduler_simple_Schedule(); - if ( !_Thread_Is_heir( executing ) ) + if ( !_Thread_Is_heir( thread ) ) _Thread_Dispatch_necessary = true; _ISR_Enable( level ); -- cgit v1.2.3