Changeset f8f1bdad in rtems


Ignore:
Timestamp:
Aug 23, 2013, 10:19:13 AM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
db0e05ff
Parents:
215ccce
git-author:
Sebastian Huber <sebastian.huber@…> (08/23/13 10:19:13)
git-committer:
Sebastian Huber <sebastian.huber@…> (08/26/13 08:02:53)
Message:

score: PR2140: Fix _Thread_queue_Process_timeout()

The _Thread_queue_Process_timeout() operation had several race
conditions in the event of nested interrupts. Protect the critical
sections via disabled interrupts.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/score/src/threadqprocesstimeout.c

    r215ccce rf8f1bdad  
    2626)
    2727{
    28   Thread_queue_Control *the_thread_queue = the_thread->Wait.queue;
     28  Thread_queue_Control *the_thread_queue;
     29  ISR_Level             level;
    2930
    3031  /*
     
    4041   */
    4142
    42   if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SYNCHRONIZED &&
    43        _Thread_Is_executing( the_thread ) ) {
    44     if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SATISFIED ) {
    45       the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
    46       the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
     43  _ISR_Disable( level );
     44  the_thread_queue = the_thread->Wait.queue;
     45  if ( the_thread_queue != NULL ) {
     46    if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SYNCHRONIZED &&
     47         _Thread_Is_executing( the_thread ) ) {
     48      if ( the_thread_queue->sync_state != THREAD_BLOCKING_OPERATION_SATISFIED ) {
     49        the_thread->Wait.return_code = the_thread_queue->timeout_status;
     50        the_thread_queue->sync_state = THREAD_BLOCKING_OPERATION_TIMEOUT;
     51      }
     52      _ISR_Enable( level );
     53    } else {
     54      bool we_did_it;
     55
     56      _ISR_Enable( level );
     57
     58      /*
     59       * After we enable interrupts here, a lot may happen in the meantime,
     60       * e.g. nested interrupts may release the resource that times out here.
     61       * So we enter _Thread_queue_Extract() speculatively.  Inside this
     62       * function we check the actual status under ISR disable protection.
     63       * This ensures that exactly one executing context performs the extract
     64       * operation (other parties may call _Thread_queue_Dequeue()).  If this
     65       * context won, then we have a timeout.
     66       *
     67       * We can use the_thread_queue pointer here even if
     68       * the_thread->Wait.queue is already set to NULL since the extract
     69       * operation will only use the thread queue discipline to select the
     70       * right extract operation.  The timeout status is set during thread
     71       * queue initialization.
     72       */
     73      we_did_it = _Thread_queue_Extract( the_thread_queue, the_thread );
     74      if ( we_did_it ) {
     75        the_thread->Wait.return_code = the_thread_queue->timeout_status;
     76      }
    4777    }
    4878  } else {
    49     the_thread->Wait.return_code = the_thread->Wait.queue->timeout_status;
    50     _Thread_queue_Extract( the_thread->Wait.queue, the_thread );
     79    _ISR_Enable( level );
    5180  }
    5281}
Note: See TracChangeset for help on using the changeset viewer.