[RTEMS Project] #2310: Race condition in _Thread_Change_priority()

RTEMS trac trac at rtems.org
Tue Mar 17 14:29:00 UTC 2015


#2310: Race condition in _Thread_Change_priority()
-----------------------------+---------------------
 Reporter:  sebastian.huber  |       Owner:
     Type:  defect           |      Status:  new
 Priority:  normal           |   Milestone:  4.11.1
Component:  cpukit           |     Version:  4.11
 Severity:  critical         |  Resolution:
 Keywords:                   |
-----------------------------+---------------------
Description changed by sebastian.huber:

Old description:

> We have:
>
> void _Thread_Change_priority(
>   Thread_Control   *the_thread,
>   Priority_Control  new_priority,
>   bool              prepend_it
> )
> {
>   /*
>    *  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 );
>
>     the_thread->current_priority = new_priority;
>
>     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 );
>
> <-- Here we changed the the_thread->current_priority and provided the
> thread is in a priority queue (RB tree), then its position in the tree is
> wrong now. In case it is the first or last element in the tree, then
> extract operations may corrupt the tree (e.g. if a timeout happens now).
>
>     _Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
>   }
> }
>
> A potential solution is to set the_thread->current_priority and call
> _Thread_queue_Requeue() in one critical section.  The scheduler is more
> resilient to temporarily wrong priority values, since it maintains its
> own priority depending state.

New description:

 We have:

 {{{
 #!c
 void _Thread_Change_priority(
   Thread_Control   *the_thread,
   Priority_Control  new_priority,
   bool              prepend_it
 )
 {
   /*
    *  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 );

     the_thread->current_priority = new_priority;

     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 );
 }}}

 Here we changed the the_thread->current_priority and provided the thread
 is in a priority queue (RB tree), then its position in the tree is wrong
 now. In case it is the first or last element in the tree, then extract
 operations may corrupt the tree (e.g. if a timeout happens now).

 {{{
 #!c
     _Thread_queue_Requeue( the_thread->Wait.queue, the_thread );
   }
 }
 }}}

 A potential solution is to set the_thread->current_priority and call
 _Thread_queue_Requeue() in one critical section.  The scheduler is more
 resilient to temporarily wrong priority values, since it maintains its own
 priority depending state.

--

--
Ticket URL: <http://devel.rtems.org/ticket/2310#comment:1>
RTEMS Project <http://www.rtems.org/>
RTEMS Project


More information about the bugs mailing list