コード例 #1
0
ファイル: timerserver.c プロジェクト: epicsdeb/rtems
static void _Timer_server_Insert_timer(
  Timer_server_Control *ts,
  Timer_Control *timer
)
{
  if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
    _Watchdog_Insert( &ts->Interval_watchdogs.Chain, &timer->Ticker );
  } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
    _Watchdog_Insert( &ts->TOD_watchdogs.Chain, &timer->Ticker );
  }
}
コード例 #2
0
ファイル: timerreset.c プロジェクト: gedare/rtems
rtems_status_code rtems_timer_reset(
  rtems_id id
)
{
  Timer_Control    *the_timer;
  ISR_lock_Context  lock_context;

  the_timer = _Timer_Get( id, &lock_context );
  if ( the_timer != NULL ) {
    Per_CPU_Control   *cpu;
    rtems_status_code  status;

    cpu = _Timer_Acquire_critical( the_timer, &lock_context );

    if ( _Timer_Is_interval_class( the_timer->the_class ) ) {
      _Timer_Cancel( cpu, the_timer );
      _Watchdog_Insert(
        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ],
        &the_timer->Ticker,
        cpu->Watchdog.ticks + the_timer->initial
      );
      status = RTEMS_SUCCESSFUL;
    } else {
      status = RTEMS_NOT_DEFINED;
    }

    _Timer_Release( cpu, &lock_context );
    return status;
  }

  return RTEMS_INVALID_ID;
}
コード例 #3
0
ファイル: timercreate.c プロジェクト: gedare/rtems
rtems_status_code _Timer_Fire(
  rtems_id                           id,
  rtems_interval                     interval,
  rtems_timer_service_routine_entry  routine,
  void                              *user_data,
  Timer_Classes                      the_class,
  Watchdog_Service_routine_entry     adaptor
)
{
  Timer_Control    *the_timer;
  ISR_lock_Context  lock_context;

  the_timer = _Timer_Get( id, &lock_context );
  if ( the_timer != NULL ) {
    Per_CPU_Control *cpu;

    cpu = _Timer_Acquire_critical( the_timer, &lock_context );
    _Timer_Cancel( cpu, the_timer );
    _Watchdog_Initialize( &the_timer->Ticker, adaptor );
    the_timer->the_class = the_class;
    the_timer->routine = routine;
    the_timer->user_data = user_data;
    the_timer->initial = interval;
    the_timer->start_time = _Timer_Get_CPU_ticks( cpu );

    if ( _Timer_Is_interval_class( the_class ) ) {
      _Watchdog_Insert(
        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_MONOTONIC ],
        &the_timer->Ticker,
        cpu->Watchdog.ticks + interval
      );
    } else {
      _Watchdog_Insert(
        &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_REALTIME ],
        &the_timer->Ticker,
        _Watchdog_Realtime_from_seconds( interval )
      );
    }

    _Timer_Release( cpu, &lock_context );
    return RTEMS_SUCCESSFUL;
  }

  return RTEMS_INVALID_ID;
}
コード例 #4
0
ファイル: timerreset.c プロジェクト: aniwang2013/leon-rtems
rtems_status_code rtems_timer_reset(
  rtems_id id
)
{
  Timer_Control     *the_timer;
  Objects_Locations  location;
  rtems_status_code  status = RTEMS_SUCCESSFUL;

  the_timer = _Timer_Get( id, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:
      if ( the_timer->the_class == TIMER_INTERVAL ) {
        _Watchdog_Remove( &the_timer->Ticker );
        _Watchdog_Insert( &_Watchdog_Ticks_chain, &the_timer->Ticker );
      } else if ( the_timer->the_class == TIMER_INTERVAL_ON_TASK ) {
        Timer_server_Control *timer_server = _Timer_server;

        /*
         *  There is no way for a timer to have this class unless
         *  it was scheduled as a server fire.  That requires that
         *  the Timer Server be initiated.  So this error cannot
         *  occur unless something is internally wrong.
         */
        #if defined(RTEMS_DEBUG)
          if ( !timer_server ) {
            _Thread_Enable_dispatch();
            return RTEMS_INCORRECT_STATE;
          }
        #endif
        _Watchdog_Remove( &the_timer->Ticker );
        (*timer_server->schedule_operation)( timer_server, the_timer );
      } else {
        /*
         *  Must be dormant or time of day timer (e.g. TIMER_DORMANT,
         *  TIMER_TIME_OF_DAY, or TIMER_TIME_OF_DAY_ON_TASK).  We
         *  can only reset active interval timers.
         */
        status = RTEMS_NOT_DEFINED;
      }
      _Thread_Enable_dispatch();
      return status;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:            /* should never return this */
#endif
    case OBJECTS_ERROR:
      break;
  }

  return RTEMS_INVALID_ID;
}
コード例 #5
0
ファイル: alarm.c プロジェクト: AoLaD/rtems
unsigned int alarm(
  unsigned int seconds
)
{
  unsigned int      remaining;
  Watchdog_Control *the_watchdog;
  ISR_lock_Context  lock_context;
  ISR_lock_Context  lock_context2;
  Per_CPU_Control  *cpu;
  uint64_t          now;
  uint32_t          ticks_per_second;
  uint32_t          ticks;

  the_watchdog = &_POSIX_signals_Alarm_watchdog;
  ticks_per_second = TOD_TICKS_PER_SECOND;
  ticks = seconds * ticks_per_second;

  _ISR_lock_ISR_disable_and_acquire(
    &_POSIX_signals_Alarm_lock,
    &lock_context
  );

  cpu = _Watchdog_Get_CPU( the_watchdog );
  _Watchdog_Per_CPU_acquire_critical( cpu, &lock_context2 );
  now = cpu->Watchdog.ticks;

  remaining = (unsigned long) _Watchdog_Cancel(
    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
    the_watchdog,
    now
  );

  if ( ticks != 0 ) {
    cpu = _Per_CPU_Get();
    _Watchdog_Set_CPU( the_watchdog, cpu );
    _Watchdog_Insert(
      &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
      the_watchdog,
      now + ticks
    );
  }

  _Watchdog_Per_CPU_release_critical( cpu, &lock_context2 );
  _ISR_lock_Release_and_ISR_enable(
    &_POSIX_signals_Alarm_lock,
    &lock_context
  );

  return ( remaining + ticks_per_second - 1 ) / ticks_per_second;
}
コード例 #6
0
ファイル: timersettime.c プロジェクト: AoLaD/rtems
static void _POSIX_Timer_Insert(
  POSIX_Timer_Control *ptimer,
  Per_CPU_Control     *cpu,
  Watchdog_Interval    ticks
)
{
  ptimer->ticks = ticks;

  /* The state really did not change but just to be safe */
  ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;

  /* Store the time when the timer was started again */
  _TOD_Get_as_timespec( &ptimer->time );

  _Watchdog_Insert(
    &cpu->Watchdog.Header[ PER_CPU_WATCHDOG_RELATIVE ],
    &ptimer->Timer,
    cpu->Watchdog.ticks + ticks
  );
}
コード例 #7
0
rtems_status_code rtems_timer_server_fire_after(
  Objects_Id                         id,
  rtems_interval                     ticks,
  rtems_timer_service_routine_entry  routine,
  void                              *user_data
)
{
  Timer_Control        *the_timer;
  Objects_Locations     location;
  ISR_Level             level;

  if ( !_Timer_Server )
    return RTEMS_INCORRECT_STATE;

  if ( !routine )
    return RTEMS_INVALID_ADDRESS;

  if ( ticks == 0 )
    return RTEMS_INVALID_NUMBER;

  the_timer = _Timer_Get( id, &location );
  switch ( location ) {
    case OBJECTS_REMOTE:            /* should never return this */
      return RTEMS_INTERNAL_ERROR;

    case OBJECTS_ERROR:
      return RTEMS_INVALID_ID;

    case OBJECTS_LOCAL:
      (void) _Watchdog_Remove( &the_timer->Ticker );

      _ISR_Disable( level );

        /*
         *  Check to see if the watchdog has just been inserted by a
         *  higher priority interrupt.  If so, abandon this insert.
         */

        if ( the_timer->Ticker.state != WATCHDOG_INACTIVE ) {
          _ISR_Enable( level );
          _Thread_Enable_dispatch();
          return RTEMS_SUCCESSFUL;
        }

        /*
         *  OK.  Now we now the timer was not rescheduled by an interrupt
         *  so we can atomically initialize it as in use.
         */

        the_timer->the_class = TIMER_INTERVAL_ON_TASK;
        _Watchdog_Initialize( &the_timer->Ticker, routine, id, user_data );
        the_timer->Ticker.initial = ticks;
      _ISR_Enable( level );

      _Timer_Server_stop_ticks_timer();
      _Timer_Server_process_ticks_chain();
      _Watchdog_Insert( &_Timer_Ticks_chain, &the_timer->Ticker );
       _Timer_Server_reset_ticks_timer();

      _Thread_Enable_dispatch();
      return RTEMS_SUCCESSFUL;
  }

  return RTEMS_INTERNAL_ERROR;   /* unreached - only to remove warnings */
}
コード例 #8
0
ファイル: timerserver.c プロジェクト: epicsdeb/rtems
static void _Timer_server_Insert_timer_and_make_snapshot(
  Timer_server_Control *ts,
  Timer_Control *timer
)
{
  Watchdog_Control *first_watchdog;
  Watchdog_Interval delta_interval;
  Watchdog_Interval last_snapshot;
  Watchdog_Interval snapshot;
  Watchdog_Interval delta;
  ISR_Level level;

  /*
   *  We have to update the time snapshots here, because otherwise we may have
   *  problems with the integer range of the delta values.  The time delta DT
   *  from the last snapshot to now may be arbitrarily long.  The last snapshot
   *  is the reference point for the delta chain.  Thus if we do not update the
   *  reference point we have to add DT to the initial delta of the watchdog
   *  being inserted.  This could result in an integer overflow.
   */

  _Thread_Disable_dispatch();

  if ( timer->the_class == TIMER_INTERVAL_ON_TASK ) {
    /*
     *  We have to advance the last known ticks value of the server and update
     *  the watchdog chain accordingly.
     */
    _ISR_Disable( level );
    snapshot = _Watchdog_Ticks_since_boot;
    last_snapshot = ts->Interval_watchdogs.last_snapshot;
    if ( !_Chain_Is_empty( &ts->Interval_watchdogs.Chain ) ) {
      first_watchdog = _Watchdog_First( &ts->Interval_watchdogs.Chain );

      /*
       *  We assume adequate unsigned arithmetic here.
       */
      delta = snapshot - last_snapshot;

      delta_interval = first_watchdog->delta_interval;
      if (delta_interval > delta) {
        delta_interval -= delta;
      } else {
        delta_interval = 0;
      }
      first_watchdog->delta_interval = delta_interval;
    }
    ts->Interval_watchdogs.last_snapshot = snapshot;
    _ISR_Enable( level );

    _Watchdog_Insert( &ts->Interval_watchdogs.Chain, &timer->Ticker );

    if ( !ts->active ) {
      _Timer_server_Reset_interval_system_watchdog( ts );
    }
  } else if ( timer->the_class == TIMER_TIME_OF_DAY_ON_TASK ) {
    /*
     *  We have to advance the last known seconds value of the server and update
     *  the watchdog chain accordingly.
     */
    _ISR_Disable( level );
    snapshot = (Watchdog_Interval) _TOD_Seconds_since_epoch();
    last_snapshot = ts->TOD_watchdogs.last_snapshot;
    if ( !_Chain_Is_empty( &ts->TOD_watchdogs.Chain ) ) {
      first_watchdog = _Watchdog_First( &ts->TOD_watchdogs.Chain );
      delta_interval = first_watchdog->delta_interval;
      if ( snapshot > last_snapshot ) {
        /*
         *  We advanced in time.
         */
        delta = snapshot - last_snapshot;
        if (delta_interval > delta) {
          delta_interval -= delta;
        } else {
          delta_interval = 0;
        }
      } else {
        /*
         *  Someone put us in the past.
         */
        delta = last_snapshot - snapshot;
        delta_interval += delta;
      }
      first_watchdog->delta_interval = delta_interval;
    }
    ts->TOD_watchdogs.last_snapshot = snapshot;
    _ISR_Enable( level );

    _Watchdog_Insert( &ts->TOD_watchdogs.Chain, &timer->Ticker );

    if ( !ts->active ) {
      _Timer_server_Reset_tod_system_watchdog( ts );
    }
  }

  _Thread_Enable_dispatch();
}