From f39f667a69cf5c4bc0dd4555537615022767f0f9 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 14 May 2014 13:50:48 +0200 Subject: score: Simplify _Thread_Change_priority() The function to change a thread priority was too complex. Simplify it with a new scheduler operation. This increases the average case performance due to the simplified logic. The interrupt disabled critical section is a bit prolonged since now the extract, update and enqueue steps are executed atomically. This should however not impact the worst-case interrupt latency since at least for the Deterministic Priority Scheduler this sequence can be carried out with a wee bit of instructions and no loops. Add _Scheduler_Change_priority() to replace the sequence of - _Thread_Set_transient(), - _Scheduler_Extract(), - _Scheduler_Enqueue(), and - _Scheduler_Enqueue_first(). Delete STATES_TRANSIENT, _States_Is_transient() and _Thread_Set_transient() since this state is now superfluous. With this change it is possible to get rid of the SCHEDULER_SMP_NODE_IN_THE_AIR state. This considerably simplifies the implementation of the new SMP locking protocols. --- cpukit/score/include/rtems/score/scheduler.h | 17 +- cpukit/score/include/rtems/score/schedulercbs.h | 4 +- cpukit/score/include/rtems/score/scheduleredf.h | 50 +----- .../score/include/rtems/score/scheduleredfimpl.h | 25 +++ cpukit/score/include/rtems/score/schedulerimpl.h | 70 ++++---- .../score/include/rtems/score/schedulerpriority.h | 54 ++----- .../rtems/score/schedulerpriorityaffinitysmp.h | 6 +- .../include/rtems/score/schedulerpriorityimpl.h | 13 +- .../include/rtems/score/schedulerprioritysmp.h | 23 ++- cpukit/score/include/rtems/score/schedulersimple.h | 71 +------- .../include/rtems/score/schedulersimpleimpl.h | 28 ++-- .../score/include/rtems/score/schedulersimplesmp.h | 19 +-- cpukit/score/include/rtems/score/schedulersmp.h | 21 +-- .../score/include/rtems/score/schedulersmpimpl.h | 180 +++++++++------------ cpukit/score/include/rtems/score/statesimpl.h | 17 -- 15 files changed, 198 insertions(+), 400 deletions(-) (limited to 'cpukit/score/include') diff --git a/cpukit/score/include/rtems/score/scheduler.h b/cpukit/score/include/rtems/score/scheduler.h index 7f0b43ae52..b1e8f8ac4f 100644 --- a/cpukit/score/include/rtems/score/scheduler.h +++ b/cpukit/score/include/rtems/score/scheduler.h @@ -63,6 +63,14 @@ typedef struct { /** @see _Scheduler_Unblock() */ void ( *unblock )( const Scheduler_Control *, Thread_Control * ); + /** @see _Scheduler_Change_priority() */ + void ( *change_priority )( + const Scheduler_Control *, + Thread_Control *, + Priority_Control, + bool + ); + /** @see _Scheduler_Allocate() */ bool ( *allocate )( const Scheduler_Control *, Thread_Control * ); @@ -72,15 +80,6 @@ typedef struct { /** @see _Scheduler_Update() */ void ( *update )( const Scheduler_Control *, Thread_Control * ); - /** @see _Scheduler_Enqueue() */ - void ( *enqueue )( const Scheduler_Control *, Thread_Control * ); - - /** @see _Scheduler_Enqueue_first() */ - void ( *enqueue_first )( const Scheduler_Control *, Thread_Control * ); - - /** @see _Scheduler_Extract() */ - void ( *extract )( const Scheduler_Control *, Thread_Control * ); - /** @see _Scheduler_Priority_compare() */ int ( *priority_compare )( Priority_Control, diff --git a/cpukit/score/include/rtems/score/schedulercbs.h b/cpukit/score/include/rtems/score/schedulercbs.h index 6cfdfbe959..46db8e5609 100644 --- a/cpukit/score/include/rtems/score/schedulercbs.h +++ b/cpukit/score/include/rtems/score/schedulercbs.h @@ -52,12 +52,10 @@ extern "C" { _Scheduler_EDF_Yield, /* yield entry point */ \ _Scheduler_EDF_Block, /* block entry point */ \ _Scheduler_CBS_Unblock, /* unblock entry point */ \ + _Scheduler_EDF_Change_priority, /* change priority entry point */ \ _Scheduler_CBS_Allocate, /* allocate entry point */ \ _Scheduler_default_Free, /* free entry point */ \ _Scheduler_EDF_Update, /* update entry point */ \ - _Scheduler_EDF_Enqueue, /* enqueue entry point */ \ - _Scheduler_EDF_Enqueue_first, /* enqueue_first entry point */ \ - _Scheduler_EDF_Extract, /* extract entry point */ \ _Scheduler_EDF_Priority_compare, /* compares two priorities */ \ _Scheduler_CBS_Release_job, /* new period of task */ \ _Scheduler_default_Tick, /* tick entry point */ \ diff --git a/cpukit/score/include/rtems/score/scheduleredf.h b/cpukit/score/include/rtems/score/scheduleredf.h index 95be94c802..301940c91d 100644 --- a/cpukit/score/include/rtems/score/scheduleredf.h +++ b/cpukit/score/include/rtems/score/scheduleredf.h @@ -45,12 +45,10 @@ extern "C" { _Scheduler_EDF_Yield, /* yield entry point */ \ _Scheduler_EDF_Block, /* block entry point */ \ _Scheduler_EDF_Unblock, /* unblock entry point */ \ + _Scheduler_EDF_Change_priority, /* change priority entry point */ \ _Scheduler_EDF_Allocate, /* allocate entry point */ \ _Scheduler_default_Free, /* free entry point */ \ _Scheduler_EDF_Update, /* update entry point */ \ - _Scheduler_EDF_Enqueue, /* enqueue entry point */ \ - _Scheduler_EDF_Enqueue_first, /* enqueue_first entry point */ \ - _Scheduler_EDF_Extract, /* extract entry point */ \ _Scheduler_EDF_Priority_compare, /* compares two priorities */ \ _Scheduler_EDF_Release_job, /* new period of task */ \ _Scheduler_default_Tick, /* tick entry point */ \ @@ -187,6 +185,13 @@ void _Scheduler_EDF_Unblock( Thread_Control *the_thread ); +void _Scheduler_EDF_Change_priority( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Priority_Control new_priority, + bool prepend_it +); + /** * @brief invoked when a thread wishes to voluntarily * transfer control of the processor to another thread @@ -207,45 +212,6 @@ void _Scheduler_EDF_Yield( Thread_Control *the_thread ); -/** - * @brief Put @a the_thread to the rbtree ready queue. - * - * This routine puts @a the_thread to the rbtree ready queue. - * - * @param[in] the_thread will be enqueued to the ready queue. - */ -void _Scheduler_EDF_Enqueue( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - -/** - * @brief Enqueue a thread to the ready queue. - * - * This routine puts @a the_thread to the rbtree ready queue. - * For the EDF scheduler this is the same as @a _Scheduler_EDF_Enqueue. - * - * @param[in] the_thread will be enqueued to the ready queue. - */ -void _Scheduler_EDF_Enqueue_first( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - -/** - * @brief Remove a specific thread from the scheduler's set - * of ready threads. - * - * This routine removes a specific thread from the scheduler's set - * of ready threads. - * - * @param[in] the_thread will be extracted from the ready set. - */ -void _Scheduler_EDF_Extract( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - /** * @brief Explicitly compare absolute dedlines (priorities) of threads. * diff --git a/cpukit/score/include/rtems/score/scheduleredfimpl.h b/cpukit/score/include/rtems/score/scheduleredfimpl.h index 8c4cd2c4bd..d424370a45 100644 --- a/cpukit/score/include/rtems/score/scheduleredfimpl.h +++ b/cpukit/score/include/rtems/score/scheduleredfimpl.h @@ -44,6 +44,31 @@ RTEMS_INLINE_ROUTINE Scheduler_EDF_Node *_Scheduler_EDF_Node_get( return (Scheduler_EDF_Node *) _Scheduler_Node_get( the_thread ); } +RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Enqueue( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +) +{ + Scheduler_EDF_Context *context = + _Scheduler_EDF_Get_context( scheduler ); + Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread ); + + _RBTree_Insert( &context->Ready, &node->Node ); + node->queue_state = SCHEDULER_EDF_QUEUE_STATE_YES; +} + +RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Extract( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +) +{ + Scheduler_EDF_Context *context = + _Scheduler_EDF_Get_context( scheduler ); + Scheduler_EDF_Node *node = _Scheduler_EDF_Node_get( the_thread ); + + _RBTree_Extract( &context->Ready, &node->Node ); +} + RTEMS_INLINE_ROUTINE void _Scheduler_EDF_Schedule_body( const Scheduler_Control *scheduler, Thread_Control *the_thread, diff --git a/cpukit/score/include/rtems/score/schedulerimpl.h b/cpukit/score/include/rtems/score/schedulerimpl.h index 2129493b0a..f37a3553ff 100644 --- a/cpukit/score/include/rtems/score/schedulerimpl.h +++ b/cpukit/score/include/rtems/score/schedulerimpl.h @@ -143,6 +143,35 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Unblock( ( *scheduler->Operations.unblock )( scheduler, the_thread ); } +/** + * @brief Propagates a priority change of a thread to the scheduler. + * + * The caller must ensure that the thread is in the ready state. The caller + * must ensure that the priority value actually changed and is not equal to the + * current priority value. + * + * @param[in] scheduler The scheduler instance. + * @param[in] the_thread The thread changing its priority. + * @param[in] new_priority The new thread priority. + * @param[in] prepend_it In case this is true, then enqueue the thread as the + * first of its priority group, otherwise enqueue the thread as the last of its + * priority group. + */ +RTEMS_INLINE_ROUTINE void _Scheduler_Change_priority( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Priority_Control new_priority, + bool prepend_it +) +{ + ( *scheduler->Operations.change_priority )( + scheduler, + the_thread, + new_priority, + prepend_it + ); +} + /** * @brief Scheduler allocate. * @@ -182,47 +211,6 @@ RTEMS_INLINE_ROUTINE void _Scheduler_Update( ( *scheduler->Operations.update )( scheduler, the_thread ); } -/** - * @brief Enqueues a thread as the last of its priority group. - * - * @param[in] scheduler The scheduler instance. - * @param[in] the_thread The thread to enqueue. - */ -RTEMS_INLINE_ROUTINE void _Scheduler_Enqueue( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -) -{ - ( *scheduler->Operations.enqueue )( scheduler, the_thread ); -} - -/** - * @brief Enqueues a thread as the first of its priority group. - * - * @param[in] scheduler The scheduler instance. - * @param[in] the_thread The thread to enqueue. - */ -RTEMS_INLINE_ROUTINE void _Scheduler_Enqueue_first( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -) -{ - ( *scheduler->Operations.enqueue_first )( scheduler, the_thread ); -} - -/** - * @brief Scheduler extract. - * - * This routine extract @a the_thread->scheduler - */ -RTEMS_INLINE_ROUTINE void _Scheduler_Extract( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -) -{ - ( *scheduler->Operations.extract )( scheduler, the_thread ); -} - /** * @brief Compares two priority values. * diff --git a/cpukit/score/include/rtems/score/schedulerpriority.h b/cpukit/score/include/rtems/score/schedulerpriority.h index 134dcd715b..b3c1466066 100644 --- a/cpukit/score/include/rtems/score/schedulerpriority.h +++ b/cpukit/score/include/rtems/score/schedulerpriority.h @@ -52,12 +52,10 @@ extern "C" { _Scheduler_priority_Yield, /* yield entry point */ \ _Scheduler_priority_Block, /* block entry point */ \ _Scheduler_priority_Unblock, /* unblock entry point */ \ - _Scheduler_default_Allocate, /* allocate entry point */ \ - _Scheduler_default_Free, /* free entry point */ \ + _Scheduler_priority_Change_priority, /* change priority entry point */ \ + _Scheduler_default_Allocate, /* allocate entry point */ \ + _Scheduler_default_Free, /* free entry point */ \ _Scheduler_priority_Update, /* update entry point */ \ - _Scheduler_priority_Enqueue, /* enqueue entry point */ \ - _Scheduler_priority_Enqueue_first, /* enqueue_first entry point */ \ - _Scheduler_priority_Extract, /* extract entry point */ \ _Scheduler_priority_Priority_compare, /* compares two priorities */ \ _Scheduler_default_Release_job, /* new period of task */ \ _Scheduler_default_Tick, /* tick entry point */ \ @@ -167,6 +165,13 @@ void _Scheduler_priority_Unblock( Thread_Control *the_thread ); +void _Scheduler_priority_Change_priority( + const Scheduler_Control *scheduler, + Thread_Control *the_thread, + Priority_Control new_priority, + bool prepend_it +); + /** * @brief The specified THREAD yields. * @@ -191,45 +196,6 @@ void _Scheduler_priority_Yield( Thread_Control *the_thread ); -/** - * @brief Puts @a the_thread on to the priority-based ready queue. - * - * This routine puts @a the_thread on to the priority-based ready queue. - * - * @param[in] the_thread will be enqueued at the TAIL of its priority. - */ -void _Scheduler_priority_Enqueue( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - -/** - * @brief Puts @a the_thread to the head of the ready queue. - * - * This routine puts @a the_thread to the head of the ready queue. - * For priority-based ready queues, the thread will be the first thread - * at its priority level. - * - * @param[in] the_thread will be enqueued at the HEAD of its priority. - */ -void _Scheduler_priority_Enqueue_first( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - -/** - * @brief Remove a specific thread from scheduler. - * - * This routine removes a specific thread from the scheduler's set - * of ready threads. - * - * @param[in] the_thread will be extracted from the ready set. - */ -void _Scheduler_priority_Extract( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - /** * @brief Compare two priorities. * diff --git a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h index e86fd35c6f..c21d066f5b 100644 --- a/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h +++ b/cpukit/score/include/rtems/score/schedulerpriorityaffinitysmp.h @@ -53,13 +53,11 @@ extern "C" { _Scheduler_priority_SMP_Schedule, \ _Scheduler_priority_SMP_Yield, \ _Scheduler_priority_SMP_Block, \ - _Scheduler_priority_SMP_Enqueue_fifo, \ + _Scheduler_priority_SMP_Unblock, \ + _Scheduler_priority_SMP_Change_priority, \ _Scheduler_priority_affinity_SMP_Allocate, \ _Scheduler_default_Free, \ _Scheduler_priority_SMP_Update, \ - _Scheduler_priority_SMP_Enqueue_fifo, \ - _Scheduler_priority_SMP_Enqueue_lifo, \ - _Scheduler_priority_SMP_Extract, \ _Scheduler_priority_Priority_compare, \ _Scheduler_default_Release_job, \ _Scheduler_default_Tick, \ diff --git a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h index ae0cd1ad9b..95d8e6ae34 100644 --- a/cpukit/score/include/rtems/score/schedulerpriorityimpl.h +++ b/cpukit/score/include/rtems/score/schedulerpriorityimpl.h @@ -196,28 +196,27 @@ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Schedule_body( } /** - * @brief Updates the specified ready queue data according to the current - * priority of the thread. + * @brief Updates the specified ready queue data according to the new priority + * value. * - * @param[in] the_thread The thread. * @param[in] ready_queue The ready queue. + * @param[in] new_priority The new priority. * @param[in] bit_map The priority bit map of the scheduler instance. * @param[in] ready_queues The ready queues of the scheduler instance. */ RTEMS_INLINE_ROUTINE void _Scheduler_priority_Ready_queue_update( - Thread_Control *the_thread, Scheduler_priority_Ready_queue *ready_queue, + Priority_Control new_priority, Priority_bit_map_Control *bit_map, Chain_Control *ready_queues ) { - Priority_Control priority = the_thread->current_priority; - ready_queue->ready_chain = &ready_queues[ priority ]; + ready_queue->ready_chain = &ready_queues[ new_priority ]; _Priority_bit_map_Initialize_information( bit_map, &ready_queue->Priority_map, - priority + new_priority ); } diff --git a/cpukit/score/include/rtems/score/schedulerprioritysmp.h b/cpukit/score/include/rtems/score/schedulerprioritysmp.h index 3e7d22f81d..a22b323e93 100644 --- a/cpukit/score/include/rtems/score/schedulerprioritysmp.h +++ b/cpukit/score/include/rtems/score/schedulerprioritysmp.h @@ -7,7 +7,7 @@ */ /* - * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 @@ -82,13 +82,11 @@ typedef struct { _Scheduler_priority_SMP_Schedule, \ _Scheduler_priority_SMP_Yield, \ _Scheduler_priority_SMP_Block, \ - _Scheduler_priority_SMP_Enqueue_fifo, \ + _Scheduler_priority_SMP_Unblock, \ + _Scheduler_priority_SMP_Change_priority, \ _Scheduler_priority_SMP_Allocate, \ _Scheduler_default_Free, \ _Scheduler_priority_SMP_Update, \ - _Scheduler_priority_SMP_Enqueue_fifo, \ - _Scheduler_priority_SMP_Enqueue_lifo, \ - _Scheduler_priority_SMP_Extract, \ _Scheduler_priority_Priority_compare, \ _Scheduler_default_Release_job, \ _Scheduler_default_Tick, \ @@ -114,22 +112,19 @@ void _Scheduler_priority_SMP_Block( Thread_Control *thread ); -void _Scheduler_priority_SMP_Update( +void _Scheduler_priority_SMP_Unblock( const Scheduler_Control *scheduler, Thread_Control *thread ); -void _Scheduler_priority_SMP_Enqueue_fifo( +void _Scheduler_priority_SMP_Change_priority( const Scheduler_Control *scheduler, - Thread_Control *thread + Thread_Control *the_thread, + Priority_Control new_priority, + bool prepend_it ); -void _Scheduler_priority_SMP_Enqueue_lifo( - const Scheduler_Control *scheduler, - Thread_Control *thread -); - -void _Scheduler_priority_SMP_Extract( +void _Scheduler_priority_SMP_Update( const Scheduler_Control *scheduler, Thread_Control *thread ); diff --git a/cpukit/score/include/rtems/score/schedulersimple.h b/cpukit/score/include/rtems/score/schedulersimple.h index 213bbb2709..6b59a0ab9e 100644 --- a/cpukit/score/include/rtems/score/schedulersimple.h +++ b/cpukit/score/include/rtems/score/schedulersimple.h @@ -42,12 +42,10 @@ extern "C" { _Scheduler_simple_Yield, /* yield entry point */ \ _Scheduler_simple_Block, /* block entry point */ \ _Scheduler_simple_Unblock, /* unblock entry point */ \ + _Scheduler_simple_Change_priority, /* change priority entry point */ \ _Scheduler_default_Allocate, /* allocate entry point */ \ _Scheduler_default_Free, /* free entry point */ \ _Scheduler_default_Update, /* update entry point */ \ - _Scheduler_simple_Enqueue, /* enqueue entry point */ \ - _Scheduler_simple_Enqueue_first, /* enqueue_first entry point */ \ - _Scheduler_simple_Extract, /* extract entry point */ \ _Scheduler_priority_Priority_compare, /* compares two priorities */ \ _Scheduler_default_Release_job, /* new period of task */ \ _Scheduler_default_Tick, /* tick entry point */ \ @@ -136,70 +134,11 @@ void _Scheduler_simple_Unblock( Thread_Control *the_thread ); -/** - * @brief Removes a simple-priority-based thread from a simple queue. - * - * This routine removes a specific thread from the specified - * simple-based ready queue. - * - * @param[in] the_thread is the thread to be blocked - */ -void _Scheduler_simple_Extract( +void _Scheduler_simple_Change_priority( const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - -/** - * @brief Puts simple-priority-based thread onto the ready queue. - * - * This routine puts @a the_thread on to the ready queue. - * - * @param[in] the_thread is the thread to be enqueued - */ -void _Scheduler_simple_Enqueue( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - -/** - * @brief Put simple-priority-based @a the_thread to - * the head of the ready queue. - * - * This routine puts @a the_thread to the head of the ready queue. - * The thread will be the first thread at its priority level. - * - * @param[in] the_thread is the thread to be blocked - */ -void _Scheduler_simple_Enqueue_first( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - -/** - * _Scheduler_simple_Ready_queue_enqueue - * - * This routine puts @a the_thread on the ready queue - * at the end of its priority group. - * - * @param[in] the_thread - pointer to a thread control block - */ -void _Scheduler_simple_Ready_queue_enqueue( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -); - -/** - * @brief Puts simple-priority-based @a the_thread on to the ready queue - * at the beginning of its priority group. - * - * This routine puts @a the_thread on to the ready queue - * at the beginning of its priority group. - * - * @param[in] the_thread - pointer to a thread control block - */ -void _Scheduler_simple_Ready_queue_enqueue_first( - const Scheduler_Control *scheduler, - Thread_Control *the_thread + Thread_Control *the_thread, + Priority_Control new_priority, + bool prepend_it ); /**@}*/ diff --git a/cpukit/score/include/rtems/score/schedulersimpleimpl.h b/cpukit/score/include/rtems/score/schedulersimpleimpl.h index c256071a8f..b73a1b2c78 100644 --- a/cpukit/score/include/rtems/score/schedulersimpleimpl.h +++ b/cpukit/score/include/rtems/score/schedulersimpleimpl.h @@ -38,24 +38,6 @@ RTEMS_INLINE_ROUTINE Scheduler_simple_Context * return (Scheduler_simple_Context *) _Scheduler_Get_context( scheduler ); } -/** - * This routine puts @a the_thread on to the ready queue. - * - * @param[in] the_ready_queue is a pointer to the ready queue head - * @param[in] the_thread is the thread to be blocked - */ -RTEMS_INLINE_ROUTINE void _Scheduler_simple_Ready_queue_requeue( - const Scheduler_Control *scheduler, - Thread_Control *the_thread -) -{ - /* extract */ - _Chain_Extract_unprotected( &the_thread->Object.Node ); - - /* enqueue */ - _Scheduler_simple_Ready_queue_enqueue( scheduler, the_thread ); -} - RTEMS_INLINE_ROUTINE bool _Scheduler_simple_Insert_priority_lifo_order( const Chain_Node *to_insert, const Chain_Node *next @@ -102,6 +84,16 @@ RTEMS_INLINE_ROUTINE void _Scheduler_simple_Insert_priority_fifo( ); } +RTEMS_INLINE_ROUTINE void _Scheduler_simple_Extract( + const Scheduler_Control *scheduler, + Thread_Control *the_thread +) +{ + (void) scheduler; + + _Chain_Extract_unprotected( &the_thread->Object.Node ); +} + RTEMS_INLINE_ROUTINE void _Scheduler_simple_Schedule_body( const Scheduler_Control *scheduler, Thread_Control *the_thread, diff --git a/cpukit/score/include/rtems/score/schedulersimplesmp.h b/cpukit/score/include/rtems/score/schedulersimplesmp.h index 1e712251c8..32e998d59a 100644 --- a/cpukit/score/include/rtems/score/schedulersimplesmp.h +++ b/cpukit/score/include/rtems/score/schedulersimplesmp.h @@ -63,13 +63,11 @@ typedef struct { _Scheduler_simple_SMP_Schedule, \ _Scheduler_simple_SMP_Yield, \ _Scheduler_simple_SMP_Block, \ - _Scheduler_simple_SMP_Enqueue_priority_fifo, \ + _Scheduler_simple_SMP_Unblock, \ + _Scheduler_simple_SMP_Change_priority, \ _Scheduler_simple_SMP_Allocate, \ _Scheduler_default_Free, \ _Scheduler_default_Update, \ - _Scheduler_simple_SMP_Enqueue_priority_fifo, \ - _Scheduler_simple_SMP_Enqueue_priority_lifo, \ - _Scheduler_simple_SMP_Extract, \ _Scheduler_priority_Priority_compare, \ _Scheduler_default_Release_job, \ _Scheduler_default_Tick, \ @@ -90,19 +88,16 @@ void _Scheduler_simple_SMP_Block( Thread_Control *thread ); -void _Scheduler_simple_SMP_Enqueue_priority_fifo( +void _Scheduler_simple_SMP_Unblock( const Scheduler_Control *scheduler, Thread_Control *thread ); -void _Scheduler_simple_SMP_Enqueue_priority_lifo( +void _Scheduler_simple_SMP_Change_priority( const Scheduler_Control *scheduler, - Thread_Control *thread -); - -void _Scheduler_simple_SMP_Extract( - const Scheduler_Control *scheduler, - Thread_Control *thread + Thread_Control *the_thread, + Priority_Control new_priority, + bool prepend_it ); void _Scheduler_simple_SMP_Yield( diff --git a/cpukit/score/include/rtems/score/schedulersmp.h b/cpukit/score/include/rtems/score/schedulersmp.h index ee1b087ff8..db8798dcd0 100644 --- a/cpukit/score/include/rtems/score/schedulersmp.h +++ b/cpukit/score/include/rtems/score/schedulersmp.h @@ -69,8 +69,8 @@ typedef enum { * * A scheduler node is scheduled if the corresponding thread is ready and the * scheduler allocated a processor for it. A scheduled node is assigned to - * exactly one processor. The sum of scheduled and in the air nodes equals - * the processor count owned by a scheduler instance. + * exactly one processor. The count of scheduled nodes in this scheduler + * instance equals the processor count owned by the scheduler instance. */ SCHEDULER_SMP_NODE_SCHEDULED, @@ -80,22 +80,7 @@ typedef enum { * A scheduler node is ready if the corresponding thread is ready and the * scheduler did not allocate a processor for it. */ - SCHEDULER_SMP_NODE_READY, - - /** - * @brief This scheduler node is in the air. - * - * A scheduled node is in the air if it has an allocated processor and the - * corresponding thread is in a transient state. Such a node is not an - * element of the set of scheduled nodes. The extract operation on a - * scheduled node will produce a scheduler node in the air (see also - * _Thread_Set_transient()). The next enqueue or schedule operation will - * decide what to do based on this state indication. It can either place the - * scheduler node back on the set of scheduled nodes and the thread can keep - * its allocated processor, or it can take the processor away from the thread - * and give the processor to another thread of higher priority. - */ - SCHEDULER_SMP_NODE_IN_THE_AIR + SCHEDULER_SMP_NODE_READY } Scheduler_SMP_Node_state; /** diff --git a/cpukit/score/include/rtems/score/schedulersmpimpl.h b/cpukit/score/include/rtems/score/schedulersmpimpl.h index 161f742d18..365edbb845 100644 --- a/cpukit/score/include/rtems/score/schedulersmpimpl.h +++ b/cpukit/score/include/rtems/score/schedulersmpimpl.h @@ -37,14 +37,12 @@ extern "C" { * * The scheduler nodes can be in four states * - @ref SCHEDULER_SMP_NODE_BLOCKED, - * - @ref SCHEDULER_SMP_NODE_SCHEDULED, - * - @ref SCHEDULER_SMP_NODE_READY, and - * - @ref SCHEDULER_SMP_NODE_IN_THE_AIR. + * - @ref SCHEDULER_SMP_NODE_SCHEDULED, and + * - @ref SCHEDULER_SMP_NODE_READY. * - * State transitions are triggered via basic three operations - * - _Scheduler_SMP_Enqueue_ordered(), - * - _Scheduler_SMP_Extract(), and - * - _Scheduler_SMP_Schedule(). + * State transitions are triggered via basic operations + * - _Scheduler_SMP_Enqueue_ordered(), and + * - _Scheduler_SMP_Block(). * * @dot * digraph { @@ -53,39 +51,26 @@ extern "C" { * bs [label="BLOCKED"]; * ss [label="SCHEDULED", fillcolor="green"]; * rs [label="READY", fillcolor="red"]; - * as [label="IN THE AIR", fillcolor="orange"]; * * edge [label="enqueue"]; * edge [fontcolor="darkgreen", color="darkgreen"]; * * bs -> ss; - * as -> ss; * - * edge [label="enqueue"]; * edge [fontcolor="red", color="red"]; * * bs -> rs; - * as -> rs; * * edge [label="enqueue other"]; * * ss -> rs; * - * edge [label="schedule"]; - * edge [fontcolor="black", color="black"]; - * - * as -> bs; - * - * edge [label="extract"]; - * edge [fontcolor="brown", color="brown"]; - * - * ss -> as; - * + * edge [label="block"]; * edge [fontcolor="black", color="black"]; * * rs -> bs; * - * edge [label="enqueue other\nschedule other"]; + * edge [label="block other"]; * edge [fontcolor="darkgreen", color="darkgreen"]; * * rs -> ss; @@ -216,38 +201,7 @@ extern "C" { * } * @enddot * - * Lets do something with A. This can be a blocking operation or a priority - * change. For this an extract operation is performed first. - * - * @dot - * digraph { - * node [style="filled"]; - * edge [dir="none"]; - * - * subgraph { - * rank = same; - * - * b [label="B (2)", fillcolor="green"]; - * a [label="A (1)", fillcolor="orange"]; - * c [label="C (3)", fillcolor="red"]; - * i [label="I (5)", fillcolor="red"]; - * j [label="J (5)", fillcolor="red"]; - * c -> i -> j; - * } - * - * subgraph { - * rank = same; - * - * p0 [label="PROCESSOR 0", shape="box"]; - * p1 [label="PROCESSOR 1", shape="box"]; - * } - * - * b -> p0; - * a -> p1; - * } - * @enddot - * - * Lets change the priority of thread A to 4 and enqueue it. + * Lets change the priority of thread A to 4. * * @dot * digraph { @@ -278,8 +232,9 @@ extern "C" { * } * @enddot * - * Alternatively we can also do a blocking operation with thread A. In this - * case schedule will be called. + * Now perform a blocking operation with thread B. Please note that thread A + * migrated now from processor 0 to processor 1 and thread C still executes on + * processor 1. * * @dot * digraph { @@ -289,12 +244,12 @@ extern "C" { * subgraph { * rank = same; * - * b [label="B (2)", fillcolor="green"]; * c [label="C (3)", fillcolor="green"]; + * a [label="A (4)", fillcolor="green"]; * i [label="I (5)", fillcolor="red"]; * j [label="J (5)", fillcolor="red"]; - * a [label="A (1)"]; - * b -> c; + * b [label="B (2)"]; + * c -> a; * i -> j; * } * @@ -305,7 +260,7 @@ extern "C" { * p1 [label="PROCESSOR 1", shape="box"]; * } * - * b -> p0; + * a -> p0; * c -> p1; * } * @enddot @@ -332,6 +287,18 @@ typedef void ( *Scheduler_SMP_Move )( Thread_Control *thread_to_move ); +typedef void ( *Scheduler_SMP_Update )( + Scheduler_Context *context, + Scheduler_Node *node, + Priority_Control new_priority +); + +typedef void ( *Scheduler_SMP_Enqueue )( + Scheduler_Context *context, + Thread_Control *thread_to_enqueue, + bool has_processor_allocated +); + static inline Scheduler_SMP_Context *_Scheduler_SMP_Get_self( Scheduler_Context *context ) @@ -360,7 +327,7 @@ static inline void _Scheduler_SMP_Node_initialize( node->state = SCHEDULER_SMP_NODE_BLOCKED; } -extern const bool _Scheduler_SMP_Node_valid_state_changes[ 4 ][ 4 ]; +extern const bool _Scheduler_SMP_Node_valid_state_changes[ 3 ][ 3 ]; static inline void _Scheduler_SMP_Node_change_state( Scheduler_SMP_Node *node, @@ -467,6 +434,7 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled( * * @param[in] context The scheduler instance context. * @param[in] thread The thread to enqueue. + * @param[in] has_processor_allocated The thread has a processor allocated. * @param[in] order The order function. * @param[in] get_highest_ready Function to get the highest ready node. * @param[in] insert_ready Function to insert a node into the set of ready @@ -481,6 +449,7 @@ static inline Thread_Control *_Scheduler_SMP_Get_lowest_scheduled( static inline void _Scheduler_SMP_Enqueue_ordered( Scheduler_Context *context, Thread_Control *thread, + bool has_processor_allocated, Chain_Node_order order, Scheduler_SMP_Get_highest_ready get_highest_ready, Scheduler_SMP_Insert insert_ready, @@ -492,19 +461,18 @@ static inline void _Scheduler_SMP_Enqueue_ordered( Scheduler_SMP_Context *self = _Scheduler_SMP_Get_self( context ); Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); - if ( node->state == SCHEDULER_SMP_NODE_IN_THE_AIR ) { + if ( has_processor_allocated) { Thread_Control *highest_ready = ( *get_highest_ready )( &self->Base ); + _Assert( highest_ready != NULL); + /* * The thread has been extracted from the scheduled chain. We have to * place it now on the scheduled or ready chain. * * NOTE: Do not exchange parameters to do the negation of the order check. */ - if ( - highest_ready != NULL - && !( *order )( &thread->Object.Node, &highest_ready->Object.Node ) - ) { + if ( !( *order )( &thread->Object.Node, &highest_ready->Object.Node ) ) { _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_READY ); _Scheduler_SMP_Allocate_processor( self, highest_ready, thread ); ( *insert_ready )( &self->Base, thread ); @@ -517,14 +485,9 @@ static inline void _Scheduler_SMP_Enqueue_ordered( Thread_Control *lowest_scheduled = _Scheduler_SMP_Get_lowest_scheduled( self ); - /* - * The scheduled chain is empty if nested interrupts change the priority of - * all scheduled threads. These threads are in the air. - */ - if ( - lowest_scheduled != NULL - && ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) - ) { + _Assert( lowest_scheduled != NULL); + + if ( ( *order )( &thread->Object.Node, &lowest_scheduled->Object.Node ) ) { Scheduler_SMP_Node *lowest_scheduled_node = _Scheduler_SMP_Node_get( lowest_scheduled ); @@ -542,6 +505,11 @@ static inline void _Scheduler_SMP_Enqueue_ordered( } } +static inline void _Scheduler_SMP_Extract_from_scheduled( Thread_Control *thread ) +{ + _Chain_Extract_unprotected( &thread->Object.Node ); +} + static inline void _Scheduler_SMP_Schedule_highest_ready( Scheduler_Context *context, Thread_Control *victim, @@ -558,25 +526,31 @@ static inline void _Scheduler_SMP_Schedule_highest_ready( } /** - * @brief Finalize a scheduling operation. + * @brief Blocks a thread. * * @param[in] context The scheduler instance context. * @param[in] thread The thread of the scheduling operation. + * @param[in] extract_from_ready Function to extract a node from the set of + * ready nodes. * @param[in] get_highest_ready Function to get the highest ready node. * @param[in] move_from_ready_to_scheduled Function to move a node from the set * of ready nodes to the set of scheduled nodes. */ -static inline void _Scheduler_SMP_Schedule( +static inline void _Scheduler_SMP_Block( Scheduler_Context *context, Thread_Control *thread, + Scheduler_SMP_Extract extract_from_ready, Scheduler_SMP_Get_highest_ready get_highest_ready, Scheduler_SMP_Move move_from_ready_to_scheduled ) { Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); + bool is_scheduled = node->state == SCHEDULER_SMP_NODE_SCHEDULED; + + _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED ); - if ( node->state == SCHEDULER_SMP_NODE_IN_THE_AIR ) { - _Scheduler_SMP_Node_change_state( node, SCHEDULER_SMP_NODE_BLOCKED ); + if ( is_scheduled ) { + _Scheduler_SMP_Extract_from_scheduled( thread ); _Scheduler_SMP_Schedule_highest_ready( context, @@ -584,42 +558,38 @@ static inline void _Scheduler_SMP_Schedule( get_highest_ready, move_from_ready_to_scheduled ); + } else { + ( *extract_from_ready )( context, thread ); } } -static inline void _Scheduler_SMP_Block( +static inline void _Scheduler_SMP_Change_priority( Scheduler_Context *context, Thread_Control *thread, - Scheduler_SMP_Extract extract, - Scheduler_SMP_Get_highest_ready get_highest_ready, - Scheduler_SMP_Move move_from_ready_to_scheduled + Priority_Control new_priority, + bool prepend_it, + Scheduler_SMP_Extract extract_from_ready, + Scheduler_SMP_Update update, + Scheduler_SMP_Enqueue enqueue_fifo, + Scheduler_SMP_Enqueue enqueue_lifo ) { - ( *extract )( context, thread ); + Scheduler_SMP_Node *node = _Scheduler_SMP_Node_get( thread ); + bool has_processor_allocated = node->state == SCHEDULER_SMP_NODE_SCHEDULED; - _Scheduler_SMP_Schedule( - context, - thread, - get_highest_ready, - move_from_ready_to_scheduled - ); -} + if ( has_processor_allocated ) { + _Scheduler_SMP_Extract_from_scheduled( thread ); + } else { + ( *extract_from_ready )( context, thread ); + } -/** - * @brief Extracts a thread from the set of scheduled or ready nodes. - * - * @param[in] context The scheduler instance context. - * @param[in] thread The thread to extract. - * @param[in] extract Function to extract a node from the set of scheduled or - * ready nodes. - */ -static inline void _Scheduler_SMP_Extract( - Scheduler_Context *context, - Thread_Control *thread, - Scheduler_SMP_Extract extract -) -{ - ( *extract )( context, thread ); + ( *update )( context, &node->Base, new_priority ); + + if ( prepend_it ) { + ( *enqueue_lifo )( context, thread, has_processor_allocated ); + } else { + ( *enqueue_fifo )( context, thread, has_processor_allocated ); + } } static inline void _Scheduler_SMP_Insert_scheduled_lifo( diff --git a/cpukit/score/include/rtems/score/statesimpl.h b/cpukit/score/include/rtems/score/statesimpl.h index 00d1092dfb..4251b3c84d 100644 --- a/cpukit/score/include/rtems/score/statesimpl.h +++ b/cpukit/score/include/rtems/score/statesimpl.h @@ -42,8 +42,6 @@ extern "C" { #define STATES_DORMANT 0x00001 /** This macro corresponds to a task being suspended. */ #define STATES_SUSPENDED 0x00002 -/** This macro corresponds to a task being in an internal state transition. */ -#define STATES_TRANSIENT 0x00004 /** This macro corresponds to a task which is waiting for a timeout. */ #define STATES_DELAYING 0x00008 /** This macro corresponds to a task waiting until a specific TOD. */ @@ -214,21 +212,6 @@ RTEMS_INLINE_ROUTINE bool _States_Is_suspended ( return (the_states & STATES_SUSPENDED); } -/** - * This function returns true if the TRANSIENT state is set in - * the_states, and false otherwise. - * - * @param[in] the_states is the task state set to test - * - * @return This method returns true if the desired state condition is set. - */ -RTEMS_INLINE_ROUTINE bool _States_Is_transient ( - States_Control the_states -) -{ - return (the_states & STATES_TRANSIENT); -} - /** * This function returns true if the DELAYING state is set in * the_states, and false otherwise. -- cgit v1.2.3