diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-03-17 16:24:44 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2015-03-20 08:49:33 +0100 |
commit | 6a941e3a9986d3cfb3e4ed0139e983b0455cc73b (patch) | |
tree | 9ad4114b0eea22a82ddc51274a1b6e550ff3f4dd /cpukit/score/src/threadchangepriority.c | |
parent | score: Delete unused _Timestamp_Is_valid() (diff) | |
download | rtems-6a941e3a9986d3cfb3e4ed0139e983b0455cc73b.tar.bz2 |
score: Fix _Thread_Change_priority()
Atomically update the current priority of a thread and the wait queue.
Serialize the scheduler update in a separate critical section with a
generation number.
New test sptests/spintrcritical23.
Close #2310.
Diffstat (limited to '')
-rw-r--r-- | cpukit/score/src/threadchangepriority.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/cpukit/score/src/threadchangepriority.c b/cpukit/score/src/threadchangepriority.c index d61dfb859a..6ee65f53cc 100644 --- a/cpukit/score/src/threadchangepriority.c +++ b/cpukit/score/src/threadchangepriority.c @@ -29,29 +29,36 @@ void _Thread_Change_priority( bool prepend_it ) { + ISR_Level level; + + _ISR_Disable( level ); + /* * Do not bother recomputing all the priority related information if * we are not REALLY changing priority. */ if ( the_thread->current_priority != new_priority ) { - ISR_Level level; - - _ISR_Disable( level ); + uint32_t my_generation = the_thread->priority_generation + 1; the_thread->current_priority = new_priority; + the_thread->priority_generation = my_generation; - if ( _States_Is_ready( the_thread->current_state ) ) { - _Scheduler_Change_priority( - the_thread, - new_priority, - prepend_it - ); - } else { - _Scheduler_Update_priority( the_thread, new_priority ); - } + _Thread_queue_Requeue( the_thread->Wait.queue, the_thread ); - _ISR_Enable( level ); + _ISR_Flash( level ); - _Thread_queue_Requeue( the_thread->Wait.queue, the_thread ); + if ( the_thread->priority_generation == my_generation ) { + if ( _States_Is_ready( the_thread->current_state ) ) { + _Scheduler_Change_priority( + the_thread, + new_priority, + prepend_it + ); + } else { + _Scheduler_Update_priority( the_thread, new_priority ); + } + } } + + _ISR_Enable( level ); } |