cpu_time_budget race condition

Joel Sherrill joel.sherrill at OARcorp.com
Wed Apr 14 13:51:00 UTC 2004


Thomas Rauscher wrote:

> Hi,
> 
> I've found a race condition between 
> _Thread_Dispatch (called from a task) and _Thread_Tickle_timeslice 
> (called from the tick ISR).
> 
> This is a topic for 4.5 and later (checked against cvs head revision).
> 
> Problem:
> 
> A task is using the classic RTEMS API. The thread control structure
> is called my_thread in advance. 
> 
> my_thread->budget_algorithm ==
> THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE
> my_thread->cpu_time_budget == 0 (or even uninitialized, I'm not sure)
> 
> is true at the beginning.
> 
> Now the task is started and rtems_task_create invokes _Thread_Dispatch.
> 
> threaddispatch.c
> 
>   ...
>   _ISR_Disable( level );
>   while ( _Context_Switch_necessary == TRUE ) {
>     heir = _Thread_Heir;
>     _Thread_Dispatch_disable_level = 1;
>     _Context_Switch_necessary = FALSE;
>     _Thread_Executing = heir;
>     executing->rtems_ada_self = rtems_ada_self;
>     rtems_ada_self = heir->rtems_ada_self;
>     _ISR_Enable( level );
>     ...
> 
> At this point, interrupts are enabled again and a tick interrupt occurs
> calling _Thread_Tickle_timeslice. _Thread_Executing is my_thread now.
> 
> threadtickletimeslice.c:
> 
>     ...
>     executing = _Thread_Executing;
>     ...
>     case THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE:
>     case THREAD_CPU_BUDGET_ALGORITHM_EXHAUST_TIMESLICE:
>       if ( --executing->cpu_time_budget == 0 ) {
>         _Thread_Reset_timeslice();
>         executing->cpu_time_budget = _Thread_Ticks_per_timeslice;
>       }
>       break;
>     ...
> 
> Now, thread->cpu_time_budget == 0xFFFFFFFF which means that
> the task won't stop until it preempts itself or its timeslice
> is exhausted (approx. 49 days using a 1 ms tick).
> 
> I think, there are two possible fixes:
> 
> 1) Move the cpu_time_budget initialization in _Thread_Dispatch
>    to the beginning where interrupts are locked.
> 2) Initialize cpu_time_budget to _Thread_Ticks_per_timeslice
>    in _Thread_Initialize().
> 
> I've successfully tried the first patch, but the second
> one seems to be a little better as the interrupt latency isn't
> increased.

The second idea won't work.  _Thread_Initialize is only called
at thread creation.  The idea with
THREAD_CPU_BUDGET_ALGORITHM_RESET_TIMESLICE is to reset the heir's
budget on each context switch.

Sounds like you hit the correct solution.  The only variany, I can
see is to just disable interrupts around those lines which only
adds to the execution time of this speed critical routine. In truth,
this isn't that large a critical section.  It is 5 stores and 3 reads
from memory with no math in the middle.  The disable time is longer
than that when you block the currently executing thread and have to
pick the heir.

> Any comments? If my observation is correct, I can file a PR and
> provide a patch.

Please file a PR.

> Best regards,
> Thomas
> 





More information about the users mailing list