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 | |
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 'cpukit')
-rw-r--r-- | cpukit/score/include/rtems/score/thread.h | 9 | ||||
-rw-r--r-- | cpukit/score/src/threadchangepriority.c | 35 | ||||
-rw-r--r-- | cpukit/score/src/threadinitialize.c | 1 |
3 files changed, 31 insertions, 14 deletions
diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index cea88f4ab7..11f60f324b 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -582,6 +582,15 @@ struct Thread_Control_struct { Priority_Control current_priority; /** This field is the base priority of this thread. */ Priority_Control real_priority; + + /** + * @brief Generation of the current priority value. + * + * It is used in _Thread_Change_priority() to serialize the update of + * priority related data structures. + */ + uint32_t priority_generation; + /** This field is the number of mutexes currently held by this thread. */ uint32_t resource_count; /** This field is the blocking information for this thread. */ 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 ); } diff --git a/cpukit/score/src/threadinitialize.c b/cpukit/score/src/threadinitialize.c index 934fea9085..993d95fdb8 100644 --- a/cpukit/score/src/threadinitialize.c +++ b/cpukit/score/src/threadinitialize.c @@ -198,6 +198,7 @@ bool _Thread_Initialize( the_thread->Wait.queue = NULL; the_thread->resource_count = 0; the_thread->real_priority = priority; + the_thread->priority_generation = 0; the_thread->Start.initial_priority = priority; _Thread_Wait_flags_set( the_thread, THREAD_WAIT_FLAGS_INITIAL ); |