Example #1
0
/**
 *  @brief Finalize a blocking operation.
 *
 *  This method is used to finalize a blocking operation that was
 *  satisfied. It may be used with thread queues or any other synchronization
 *  object that uses the blocking states and watchdog times for timeout.
 *
 *  This method will restore the previous ISR disable level during the cancel
 *  operation.  Thus it is an implicit _ISR_Enable().
 *
 *  @param[in] the_thread is the thread whose blocking is canceled
 *  @param[in] lock_context is the previous ISR disable level
 */
static void _Thread_blocking_operation_Finalize(
  Thread_Control   *the_thread,
  ISR_lock_Context *lock_context
)
{
  /*
   * The thread is not waiting on anything after this completes.
   */
  the_thread->Wait.queue = NULL;

  /*
   *  If the sync state is timed out, this is very likely not needed.
   *  But better safe than sorry when it comes to critical sections.
   */
  if ( _Watchdog_Is_active( &the_thread->Timer ) ) {
    _Watchdog_Deactivate( &the_thread->Timer );
    _Thread_queue_Release( lock_context );
    (void) _Watchdog_Remove( &the_thread->Timer );
  } else
    _Thread_queue_Release( lock_context );

  /*
   *  Global objects with thread queue's should not be operated on from an
   *  ISR.  But the sync code still must allow short timeouts to be processed
   *  correctly.
   */

  _Thread_Unblock( the_thread );

#if defined(RTEMS_MULTIPROCESSING)
  if ( !_Objects_Is_local_id( the_thread->Object.id ) )
    _Thread_MP_Free_proxy( the_thread );
#endif
}
Thread_Control *_Thread_queue_Dequeue_fifo(
  Thread_queue_Control *the_thread_queue
)
{
  ISR_Level              level;
  Thread_Control *the_thread;

  _ISR_Disable( level );
  if ( !_Chain_Is_empty( &the_thread_queue->Queues.Fifo ) ) {

    the_thread = (Thread_Control *)
       _Chain_Get_first_unprotected( &the_thread_queue->Queues.Fifo );

    the_thread->Wait.queue = NULL;
    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
      _ISR_Enable( level );
      _Thread_Unblock( the_thread );
    } else {
      _Watchdog_Deactivate( &the_thread->Timer );
      _ISR_Enable( level );
      (void) _Watchdog_Remove( &the_thread->Timer );
      _Thread_Unblock( the_thread );
    }

#if defined(RTEMS_MULTIPROCESSING)
    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
      _Thread_MP_Free_proxy( the_thread );
#endif

    return the_thread;
  }

  _ISR_Enable( level );
  return NULL;
}
Example #3
0
void _Event_Surrender(
  Thread_Control *the_thread
)
{
  ISR_Level           level;
  rtems_event_set     pending_events;
  rtems_event_set     event_condition;
  rtems_event_set     seized_events;
  rtems_option        option_set;
  RTEMS_API_Control  *api;

  api = the_thread->API_Extensions[ THREAD_API_RTEMS ];

  option_set = (rtems_option) the_thread->Wait.option;

  _ISR_Disable( level );
  pending_events  = api->pending_events;
  event_condition = (rtems_event_set) the_thread->Wait.count;

  seized_events = _Event_sets_Get( pending_events, event_condition );

  /*
   *  No events were seized in this operation
   */
  if ( _Event_sets_Is_empty( seized_events ) ) {
    _ISR_Enable( level );
    return;
  }

  /*
   *  If we are in an ISR and sending to the current thread, then
   *  we have a critical section issue to deal with.
   */
  if ( _ISR_Is_in_progress() &&
       _Thread_Is_executing( the_thread ) &&
       ((_Event_Sync_state == THREAD_BLOCKING_OPERATION_TIMEOUT) ||
        (_Event_Sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED)) ) {
    if ( seized_events == event_condition || _Options_Is_any(option_set) ) {
      api->pending_events = _Event_sets_Clear( pending_events,seized_events );
      the_thread->Wait.count = 0;
      *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;
      _Event_Sync_state = THREAD_BLOCKING_OPERATION_SATISFIED;
    }
    _ISR_Enable( level );
    return;
  }

  /*
   *  Otherwise, this is a normal send to another thread
   */
  if ( _States_Is_waiting_for_event( the_thread->current_state ) ) {
    if ( seized_events == event_condition || _Options_Is_any( option_set ) ) {
      api->pending_events = _Event_sets_Clear( pending_events, seized_events );
      the_thread->Wait.count = 0;
      *(rtems_event_set *)the_thread->Wait.return_argument = seized_events;

      _ISR_Flash( level );

      if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
        _ISR_Enable( level );
        _Thread_Unblock( the_thread );
      } else {
        _Watchdog_Deactivate( &the_thread->Timer );
        _ISR_Enable( level );
        (void) _Watchdog_Remove( &the_thread->Timer );
        _Thread_Unblock( the_thread );
      }
      return;
    }
  }
  _ISR_Enable( level );
}
Example #4
0
Thread_Control *_Thread_queue_Dequeue_priority(
    Thread_queue_Control *the_thread_queue
)
{
    uint32_t        index;
    ISR_Level       level;
    Thread_Control *the_thread = NULL;  /* just to remove warnings */
    Thread_Control *new_first_thread;
    Chain_Node     *head;
    Chain_Node     *tail;
    Chain_Node     *new_first_node;
    Chain_Node     *new_second_node;
    Chain_Node     *last_node;
    Chain_Node     *next_node;
    Chain_Node     *previous_node;

    _ISR_Disable( level );
    for( index=0 ;
            index < TASK_QUEUE_DATA_NUMBER_OF_PRIORITY_HEADERS ;
            index++ ) {
        if ( !_Chain_Is_empty( &the_thread_queue->Queues.Priority[ index ] ) ) {
            the_thread = (Thread_Control *) _Chain_First(
                             &the_thread_queue->Queues.Priority[ index ]
                         );
            goto dequeue;
        }
    }

    /*
     * We did not find a thread to unblock.
     */
    _ISR_Enable( level );
    return NULL;

dequeue:
    the_thread->Wait.queue = NULL;
    new_first_node   = _Chain_First( &the_thread->Wait.Block2n );
    new_first_thread = (Thread_Control *) new_first_node;
    next_node        = the_thread->Object.Node.next;
    previous_node    = the_thread->Object.Node.previous;

    if ( !_Chain_Is_empty( &the_thread->Wait.Block2n ) ) {
        last_node       = _Chain_Last( &the_thread->Wait.Block2n );
        new_second_node = new_first_node->next;

        previous_node->next      = new_first_node;
        next_node->previous      = new_first_node;
        new_first_node->next     = next_node;
        new_first_node->previous = previous_node;

        if ( !_Chain_Has_only_one_node( &the_thread->Wait.Block2n ) ) {
            /* > two threads on 2-n */
            head = _Chain_Head( &new_first_thread->Wait.Block2n );
            tail = _Chain_Tail( &new_first_thread->Wait.Block2n );

            new_second_node->previous = head;
            head->next = new_second_node;
            tail->previous = last_node;
            last_node->next = tail;
        }
    } else {
        previous_node->next = next_node;
        next_node->previous = previous_node;
    }

    if ( !_Watchdog_Is_active( &the_thread->Timer ) ) {
        _ISR_Enable( level );
        _Thread_Unblock( the_thread );
    } else {
        _Watchdog_Deactivate( &the_thread->Timer );
        _ISR_Enable( level );
        (void) _Watchdog_Remove( &the_thread->Timer );
        _Thread_Unblock( the_thread );
    }

#if defined(RTEMS_MULTIPROCESSING)
    if ( !_Objects_Is_local_id( the_thread->Object.id ) )
        _Thread_MP_Free_proxy( the_thread );
#endif
    return( the_thread );
}
void _Event_Seize(
  rtems_event_set  event_in,
  rtems_option     option_set,
  rtems_interval   ticks,
  rtems_event_set *event_out
)
{
  Thread_Control    *executing;
  rtems_event_set    seized_events;
  rtems_event_set    pending_events;
  ISR_Level          level;
  RTEMS_API_Control  *api;
  Event_Sync_states   sync_state;

  executing = _Thread_Executing;
  executing->Wait.return_code = RTEMS_SUCCESSFUL;

  api = executing->API_Extensions[ THREAD_API_RTEMS ];

  _ISR_Disable( level );
  pending_events = api->pending_events;
  seized_events  = _Event_sets_Get( pending_events, event_in );

  if ( !_Event_sets_Is_empty( seized_events ) &&
       (seized_events == event_in || _Options_Is_any( option_set )) ) {
    api->pending_events =
      _Event_sets_Clear( pending_events, seized_events );
    _ISR_Enable( level );
    *event_out = seized_events;
    return;
  }

  if ( _Options_Is_no_wait( option_set ) ) {
    _ISR_Enable( level );
    executing->Wait.return_code = RTEMS_UNSATISFIED;
    *event_out = seized_events;
    return;
  }

  _Event_Sync_state = EVENT_SYNC_NOTHING_HAPPENED;

  executing->Wait.option            = (uint32_t  ) option_set;
  executing->Wait.count             = (uint32_t  ) event_in;
  executing->Wait.return_argument   = event_out;

  _ISR_Enable( level );

  if ( ticks ) {
    _Watchdog_Initialize(
      &executing->Timer,
      _Event_Timeout,
      executing->Object.id,
      NULL
    );
    _Watchdog_Insert_ticks( &executing->Timer, ticks );
  }

  _Thread_Set_state( executing, STATES_WAITING_FOR_EVENT );

  _ISR_Disable( level );

  sync_state = _Event_Sync_state;
  _Event_Sync_state = EVENT_SYNC_SYNCHRONIZED;

  switch ( sync_state ) {
    case EVENT_SYNC_SYNCHRONIZED:
      /*
       *  This cannot happen.  It indicates that this routine did not
       *  enter the synchronization states above.
       */
      return;

    case EVENT_SYNC_NOTHING_HAPPENED:
      _ISR_Enable( level );
      return;

    case EVENT_SYNC_TIMEOUT:
      executing->Wait.return_code = RTEMS_TIMEOUT;
      _ISR_Enable( level );
      _Thread_Unblock( executing );
      return;

    case EVENT_SYNC_SATISFIED:
      if ( _Watchdog_Is_active( &executing->Timer ) ) {
        _Watchdog_Deactivate( &executing->Timer );
        _ISR_Enable( level );
        (void) _Watchdog_Remove( &executing->Timer );
      } else
        _ISR_Enable( level );
      _Thread_Unblock( executing );
      return;
  }
}