diff options
Diffstat (limited to 'cpukit/score/src/threadchangepriority.c')
-rw-r--r-- | cpukit/score/src/threadchangepriority.c | 97 |
1 files changed, 29 insertions, 68 deletions
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c index 68eb3e89fa..4480b536d0 100644 --- a/cpukit/score/src/threadchangepriority.c +++ b/cpukit/score/src/threadchangepriority.c @@ -29,79 +29,40 @@ void _Thread_Change_priority( bool prepend_it ) { - const Scheduler_Control *scheduler = _Scheduler_Get( the_thread ); - ISR_Level level; - States_Control state, original_state; - - /* - * Save original state - */ - original_state = the_thread->current_state; - - /* - * Set a transient state for the thread so it is pulled off the Ready chains. - * This will prevent it from being scheduled no matter what happens in an - * ISR. - */ - _Thread_Set_transient( the_thread ); - /* * Do not bother recomputing all the priority related information if * we are not REALLY changing priority. */ - if ( the_thread->current_priority != new_priority ) - _Thread_Set_priority( the_thread, new_priority ); - - _ISR_Disable( level ); - - /* - * If the thread has more than STATES_TRANSIENT set, then it is blocked, - * If it is blocked on a thread queue, then we need to requeue it. - */ - state = the_thread->current_state; - if ( state != STATES_TRANSIENT ) { - /* Only clear the transient state if it wasn't set already */ - if ( ! _States_Is_transient( original_state ) ) - the_thread->current_state = _States_Clear( STATES_TRANSIENT, state ); - - /* - * The thread may have new blocking states added by interrupt service - * routines after the change into the transient state. This will not - * result in a _Scheduler_Block() operation. Make sure we select an heir - * now. - */ - _Scheduler_Schedule( scheduler, the_thread ); - - _ISR_Enable( level ); - if ( _States_Is_waiting_on_thread_queue( state ) ) { - _Thread_queue_Requeue( the_thread->Wait.queue, the_thread ); + if ( the_thread->current_priority != new_priority ) { + ISR_Level level; + const Scheduler_Control *scheduler; + + _ISR_Disable( level ); + + scheduler = _Scheduler_Get( the_thread ); + the_thread->current_priority = new_priority; + + if ( _States_Is_ready( the_thread->current_state ) ) { + _Scheduler_Change_priority( + scheduler, + the_thread, + new_priority, + prepend_it + ); + + _ISR_Flash( level ); + + /* + * We altered the set of thread priorities. So let's figure out + * who is the heir and if we need to switch to them. + */ + scheduler = _Scheduler_Get( the_thread ); + _Scheduler_Schedule( scheduler, the_thread ); + } else { + _Scheduler_Update( scheduler, the_thread ); } - return; - } - - /* Only clear the transient state if it wasn't set already */ - if ( ! _States_Is_transient( original_state ) ) { - /* - * Interrupts are STILL disabled. - * We now know the thread will be in the READY state when we remove - * the TRANSIENT state. So we have to place it on the appropriate - * Ready Queue with interrupts off. - */ - the_thread->current_state = _States_Clear( STATES_TRANSIENT, state ); + _ISR_Enable( level ); - if ( prepend_it ) - _Scheduler_Enqueue_first( scheduler, the_thread ); - else - _Scheduler_Enqueue( scheduler, the_thread ); + _Thread_queue_Requeue( the_thread->Wait.queue, the_thread ); } - - _ISR_Flash( level ); - - /* - * We altered the set of thread priorities. So let's figure out - * who is the heir and if we need to switch to them. - */ - _Scheduler_Schedule( scheduler, the_thread ); - - _ISR_Enable( level ); } |