Пример #1
0
static rtems_status_code _Rate_monotonic_Block_while_active(
  Rate_monotonic_Control *the_period,
  rtems_interval          length,
  Thread_Control         *executing,
  ISR_lock_Context       *lock_context
)
{
  Per_CPU_Control *cpu_self;
  bool             success;

  /*
   *  Update statistics from the concluding period.
   */
  _Rate_monotonic_Update_statistics( the_period );

  /*
   *  This tells the _Rate_monotonic_Timeout that this task is
   *  in the process of blocking on the period and that we
   *  may be changing the length of the next period.
   */
  the_period->next_length = length;
  executing->Wait.return_argument = the_period;
  _Thread_Wait_flags_set( executing, RATE_MONOTONIC_INTEND_TO_BLOCK );

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
  _Rate_monotonic_Release( the_period, lock_context );

  _Thread_Set_state( executing, STATES_WAITING_FOR_PERIOD );

  success = _Thread_Wait_flags_try_change_acquire(
    executing,
    RATE_MONOTONIC_INTEND_TO_BLOCK,
    RATE_MONOTONIC_BLOCKED
  );
  if ( !success ) {
    _Assert(
      _Thread_Wait_flags_get( executing ) == RATE_MONOTONIC_READY_AGAIN
    );
    _Thread_Unblock( executing );
  }

  _Thread_Dispatch_enable( cpu_self );
  return RTEMS_SUCCESSFUL;
}
Пример #2
0
void _Thread_queue_Enqueue(
    Thread_queue_Queue            *queue,
    const Thread_queue_Operations *operations,
    Thread_Control                *the_thread,
    Thread_queue_Context          *queue_context
)
{
    Per_CPU_Control *cpu_self;
    bool             success;

    _Assert( queue_context->enqueue_callout != NULL );
    _Assert( (uint8_t) queue_context->timeout_discipline != 0x7f );

#if defined(RTEMS_MULTIPROCESSING)
    if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) {
        the_thread = _Thread_MP_Allocate_proxy( queue_context->thread_state );
    }
#endif

    _Thread_Wait_claim( the_thread, queue );

    if ( !_Thread_queue_Path_acquire_critical( queue, the_thread, queue_context ) ) {
        _Thread_queue_Path_release_critical( queue_context );
        _Thread_Wait_restore_default( the_thread );
        _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );
        _Thread_Wait_tranquilize( the_thread );
        _Assert( queue_context->deadlock_callout != NULL );
        ( *queue_context->deadlock_callout )( the_thread );
        return;
    }

    _Thread_queue_Context_clear_priority_updates( queue_context );
    _Thread_Wait_claim_finalize( the_thread, operations );
    ( *operations->enqueue )( queue, the_thread, queue_context );

    _Thread_queue_Path_release_critical( queue_context );

    the_thread->Wait.return_code = STATUS_SUCCESSFUL;
    _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK );
    cpu_self = _Thread_Dispatch_disable_critical(
                   &queue_context->Lock_context.Lock_context
               );
    _Thread_queue_Queue_release( queue, &queue_context->Lock_context.Lock_context );

    ( *queue_context->enqueue_callout )( queue, the_thread, queue_context );

    /*
     *  Set the blocking state for this thread queue in the thread.
     */
    _Thread_Set_state( the_thread, queue_context->thread_state );

    /*
     *  If the thread wants to timeout, then schedule its timer.
     */
    _Thread_queue_Timeout( the_thread, cpu_self, queue_context );

    /*
     * At this point thread dispatching is disabled, however, we already released
     * the thread queue lock.  Thus, interrupts or threads on other processors
     * may already changed our state with respect to the thread queue object.
     * The request could be satisfied or timed out.  This situation is indicated
     * by the thread wait flags.  Other parties must not modify our thread state
     * as long as we are in the THREAD_QUEUE_INTEND_TO_BLOCK thread wait state,
     * thus we have to cancel the blocking operation ourself if necessary.
     */
    success = _Thread_Wait_flags_try_change_acquire(
                  the_thread,
                  THREAD_QUEUE_INTEND_TO_BLOCK,
                  THREAD_QUEUE_BLOCKED
              );
    if ( !success ) {
        _Thread_Remove_timer_and_unblock( the_thread, queue );
    }

    _Thread_Priority_update( queue_context );
    _Thread_Dispatch_direct( cpu_self );
}
Пример #3
0
void _Thread_queue_Enqueue_critical(
  Thread_queue_Queue            *queue,
  const Thread_queue_Operations *operations,
  Thread_Control                *the_thread,
  States_Control                 state,
  Thread_queue_Context          *queue_context
)
{
  Thread_queue_Path  path;
  Per_CPU_Control   *cpu_self;
  bool               success;

#if defined(RTEMS_MULTIPROCESSING)
  if ( _Thread_MP_Is_receive( the_thread ) && the_thread->receive_packet ) {
    the_thread = _Thread_MP_Allocate_proxy( state );
  }
#endif

  _Thread_Wait_claim( the_thread, queue, operations );

  if ( !_Thread_queue_Path_acquire( the_thread, queue, &path ) ) {
    _Thread_Wait_restore_default( the_thread );
    _Thread_queue_Queue_release( queue, &queue_context->Lock_context );
    _Thread_Wait_tranquilize( the_thread );
    ( *queue_context->deadlock_callout )( the_thread );
    return;
  }

  ( *operations->enqueue )( queue, the_thread, &path );

  _Thread_queue_Path_release( &path );

  the_thread->Wait.return_code = STATUS_SUCCESSFUL;
  _Thread_Wait_flags_set( the_thread, THREAD_QUEUE_INTEND_TO_BLOCK );
  cpu_self = _Thread_Dispatch_disable_critical( &queue_context->Lock_context );
  _Thread_queue_Queue_release( queue, &queue_context->Lock_context );

  if (
    cpu_self->thread_dispatch_disable_level
      != queue_context->expected_thread_dispatch_disable_level
  ) {
    _Terminate(
      INTERNAL_ERROR_CORE,
      false,
      INTERNAL_ERROR_THREAD_QUEUE_ENQUEUE_FROM_BAD_STATE
    );
  }

  /*
   *  Set the blocking state for this thread queue in the thread.
   */
  _Thread_Set_state( the_thread, state );

  /*
   *  If the thread wants to timeout, then schedule its timer.
   */
  switch ( queue_context->timeout_discipline ) {
    case WATCHDOG_RELATIVE:
      /* A relative timeout of 0 is a special case indefinite (no) timeout */
      if ( queue_context->timeout != 0 ) {
        _Thread_Timer_insert_relative(
          the_thread,
          cpu_self,
          _Thread_Timeout,
          (Watchdog_Interval) queue_context->timeout
        );
      }
      break;
    case WATCHDOG_ABSOLUTE:
      _Thread_Timer_insert_absolute(
        the_thread,
        cpu_self,
        _Thread_Timeout,
        queue_context->timeout
      );
      break;
    default:
      break;
  }

  /*
   * At this point thread dispatching is disabled, however, we already released
   * the thread queue lock.  Thus, interrupts or threads on other processors
   * may already changed our state with respect to the thread queue object.
   * The request could be satisfied or timed out.  This situation is indicated
   * by the thread wait flags.  Other parties must not modify our thread state
   * as long as we are in the THREAD_QUEUE_INTEND_TO_BLOCK thread wait state,
   * thus we have to cancel the blocking operation ourself if necessary.
   */
  success = _Thread_Wait_flags_try_change_acquire(
    the_thread,
    THREAD_QUEUE_INTEND_TO_BLOCK,
    THREAD_QUEUE_BLOCKED
  );
  if ( !success ) {
    _Thread_Remove_timer_and_unblock( the_thread, queue );
  }

  _Thread_Update_priority( path.update_priority );
  _Thread_Dispatch_enable( cpu_self );
}