Beispiel #1
0
static void _Rate_monotonic_Release_job(
  Rate_monotonic_Control *the_period,
  Thread_Control         *owner,
  rtems_interval          next_length,
  ISR_lock_Context       *lock_context
)
{
  Per_CPU_Control      *cpu_self;
  Thread_queue_Context  queue_context;
  uint64_t              deadline;

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );

  deadline = _Watchdog_Per_CPU_insert_ticks(
    &the_period->Timer,
    cpu_self,
    next_length
  );
  _Scheduler_Release_job(
    owner,
    &the_period->Priority,
    deadline,
    &queue_context
  );

  _Rate_monotonic_Release( the_period, lock_context );
  _Thread_Priority_update( &queue_context );
  _Thread_Dispatch_enable( cpu_self );
}
Beispiel #2
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;
}
Beispiel #3
0
rtems_status_code rtems_rate_monotonic_reset_statistics(
  rtems_id id
)
{
  Rate_monotonic_Control *the_period;
  ISR_lock_Context        lock_context;
  Thread_Control         *owner;

  the_period = _Rate_monotonic_Get( id, &lock_context );
  if ( the_period == NULL ) {
    return RTEMS_INVALID_ID;
  }

  owner = the_period->owner;
  _Rate_monotonic_Acquire_critical( owner, &lock_context );
  _Rate_monotonic_Reset_statistics( the_period );
  _Rate_monotonic_Release( owner, &lock_context );
  return RTEMS_SUCCESSFUL;
}
Beispiel #4
0
void _Rate_monotonic_Cancel(
  Rate_monotonic_Control *the_period,
  Thread_Control         *owner,
  ISR_lock_Context       *lock_context
)
{
  Per_CPU_Control *cpu_self;
  Thread_Control  *update_priority;

  _Rate_monotonic_Acquire_critical( the_period, lock_context );

  _Watchdog_Per_CPU_remove_relative( &the_period->Timer );
  the_period->state = RATE_MONOTONIC_INACTIVE;
  update_priority = _Scheduler_Cancel_job( the_period->owner );

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
  _Rate_monotonic_Release( the_period, lock_context );
  _Thread_Update_priority( update_priority );
  _Thread_Dispatch_enable( cpu_self );
}
Beispiel #5
0
static void _Rate_monotonic_Release_postponed_job(
  Rate_monotonic_Control *the_period,
  Thread_Control         *owner,
  rtems_interval          next_length,
  ISR_lock_Context       *lock_context
)
{
  Per_CPU_Control      *cpu_self;
  Thread_queue_Context  queue_context;

  --the_period->postponed_jobs;
  _Scheduler_Release_job(
    owner,
    &the_period->Priority,
    the_period->latest_deadline,
    &queue_context
  );

  cpu_self = _Thread_Dispatch_disable_critical( lock_context );
  _Rate_monotonic_Release( the_period, lock_context );
  _Thread_Priority_update( &queue_context );
  _Thread_Dispatch_enable( cpu_self );
}
Beispiel #6
0
static void _Rate_monotonic_Renew_deadline(
  Rate_monotonic_Control *the_period,
  ISR_lock_Context       *lock_context
)
{
  uint64_t deadline;

  /* stay at 0xffffffff if postponed_jobs is going to overflow */
  if ( the_period->postponed_jobs != UINT32_MAX ) {
    ++the_period->postponed_jobs;
  }

  the_period->state = RATE_MONOTONIC_EXPIRED;

  deadline = _Watchdog_Per_CPU_insert_ticks(
    &the_period->Timer,
    _Per_CPU_Get(),
    the_period->next_length
  );
  the_period->latest_deadline = deadline;

  _Rate_monotonic_Release( the_period, lock_context );
}
Beispiel #7
0
rtems_status_code rtems_rate_monotonic_period(
  rtems_id       id,
  rtems_interval length
)
{
  Rate_monotonic_Control            *the_period;
  ISR_lock_Context                   lock_context;
  Thread_Control                    *executing;
  rtems_status_code                  status;
  rtems_rate_monotonic_period_states state;

  the_period = _Rate_monotonic_Get( id, &lock_context );
  if ( the_period == NULL ) {
    return RTEMS_INVALID_ID;
  }

  executing = _Thread_Executing;
  if ( executing != the_period->owner ) {
    _ISR_lock_ISR_enable( &lock_context );
    return RTEMS_NOT_OWNER_OF_RESOURCE;
  }

  _Rate_monotonic_Acquire_critical( the_period, &lock_context );

  state = the_period->state;

  if ( length == RTEMS_PERIOD_STATUS ) {
    status = _Rate_monotonic_Get_status_for_state( state );
    _Rate_monotonic_Release( the_period, &lock_context );
  } else {
    switch ( state ) {
      case RATE_MONOTONIC_ACTIVE:

        if( the_period->postponed_jobs > 0 ){
          /*
           * If the number of postponed jobs is not 0, it means the
           * previous postponed instance is finished without exceeding
           * the current period deadline.
           *
           * Do nothing on the watchdog deadline assignment but release the
           * next remaining postponed job.
           */
          status = _Rate_monotonic_Block_while_expired(
            the_period,
            length,
            executing,
            &lock_context
          );
        }else{
          /*
           * Normal case that no postponed jobs and no expiration, so wait for
           * the period and update the deadline of watchdog accordingly.
           */
          status = _Rate_monotonic_Block_while_active(
            the_period,
            length,
            executing,
            &lock_context
          );
        }
        break;
      case RATE_MONOTONIC_INACTIVE:
        status = _Rate_monotonic_Activate(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
      default:
        /*
         * As now this period was already TIMEOUT, there must be at least one
         * postponed job recorded by the watchdog. The one which exceeded
         * the previous deadlines was just finished.
         *
         * Maybe there is more than one job postponed due to the preemption or
         * the previous finished job.
         */
        _Assert( state == RATE_MONOTONIC_EXPIRED );
        status = _Rate_monotonic_Block_while_expired(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
    }
  }

  return status;
}
Beispiel #8
0
rtems_status_code rtems_rate_monotonic_period(
  rtems_id       id,
  rtems_interval length
)
{
  Rate_monotonic_Control            *the_period;
  ISR_lock_Context                   lock_context;
  Thread_Control                    *executing;
  rtems_status_code                  status;
  rtems_rate_monotonic_period_states state;

  the_period = _Rate_monotonic_Get( id, &lock_context );
  if ( the_period == NULL ) {
    return RTEMS_INVALID_ID;
  }

  executing = _Thread_Executing;
  if ( executing != the_period->owner ) {
    _ISR_lock_ISR_enable( &lock_context );
    return RTEMS_NOT_OWNER_OF_RESOURCE;
  }

  _Rate_monotonic_Acquire_critical( the_period, &lock_context );

  state = the_period->state;

  if ( length == RTEMS_PERIOD_STATUS ) {
    status = _Rate_monotonic_Get_status_for_state( state );
    _Rate_monotonic_Release( the_period, &lock_context );
  } else {
    switch ( state ) {
      case RATE_MONOTONIC_ACTIVE:
        status = _Rate_monotonic_Block_while_active(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
      case RATE_MONOTONIC_INACTIVE:
        status = _Rate_monotonic_Activate(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
      default:
        _Assert( state == RATE_MONOTONIC_EXPIRED );
        status = _Rate_monotonic_Block_while_expired(
          the_period,
          length,
          executing,
          &lock_context
        );
        break;
    }
  }

  return status;
}