Exemple #1
0
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;
  Thread_blocking_operation_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;
  }

  /*
   *  Note what we are waiting for BEFORE we enter the critical section.
   *  The interrupt critical section management code needs this to be
   *  set properly when we are marked as in the event critical section.
   *
   *  NOTE: Since interrupts are disabled, this isn't that much of an
   *        issue but better safe than sorry.
   */
  executing->Wait.option            = (uint32_t) option_set;
  executing->Wait.count             = (uint32_t) event_in;
  executing->Wait.return_argument   = event_out;

  _Event_Sync_state = THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED;

  _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 = THREAD_BLOCKING_OPERATION_SYNCHRONIZED;
  if ( sync_state == THREAD_BLOCKING_OPERATION_NOTHING_HAPPENED ) {
    _ISR_Enable( level );
    return;
  }

  /*
   *  An interrupt completed the thread's blocking request.
   *  The blocking thread was satisfied by an ISR or timed out.
   *
   *  WARNING! Returning with interrupts disabled!
   */
  _Thread_blocking_operation_Cancel( sync_state, executing, level );
}
Exemple #2
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 );
}
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;
  }
}