Exemple #1
0
int clock_gettime(
  clockid_t        clock_id,
  struct timespec *tp
)
{
  if ( !tp )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( clock_id == CLOCK_REALTIME ) {
    _TOD_Get(tp);
    return 0;
  }
#ifdef CLOCK_MONOTONIC
  if ( clock_id == CLOCK_MONOTONIC ) {
    _TOD_Get_uptime_as_timespec( tp );
    return 0;
  }
#endif

#ifdef _POSIX_CPUTIME
  if ( clock_id == CLOCK_PROCESS_CPUTIME_ID ) {
    _TOD_Get_uptime_as_timespec( tp );
    return 0;
  }
#endif

#ifdef _POSIX_THREAD_CPUTIME
  if ( clock_id == CLOCK_THREAD_CPUTIME_ID )
    rtems_set_errno_and_return_minus_one( ENOSYS );
#endif

  rtems_set_errno_and_return_minus_one( EINVAL );

  return 0;
}
int timer_gettime(
  timer_t            timerid,
  struct itimerspec *value
)
{

 /*
  * IDEA:  This function does not use functions of RTEMS to the handle
  *        of timers. It uses some functions for managing the time.
  *
  *        A possible form to do this is the following:
  *
  *          - When a timer is initialized, the value of the time in
  *            that moment is stored.
  *          - When this function is called, it returns the difference
  *            between the current time and the initialization time.
  */

  POSIX_Timer_Control *ptimer;
  Objects_Locations    location;
  struct timespec      current_time;

  /* Reads the current time */
  _TOD_Get( &current_time );

  ptimer = _POSIX_Timer_Get( timerid, &location );
  switch ( location ) {
    case OBJECTS_REMOTE:
#if defined(RTEMS_MULTIPROCESSING)
      _Thread_Dispatch();
      rtems_set_errno_and_return_minus_one( EINVAL );
#endif

    case OBJECTS_ERROR:
      rtems_set_errno_and_return_minus_one( EINVAL );

    case OBJECTS_LOCAL:

      /* Calculates the time left before the timer finishes */

      _Timespec_Subtract(
        &ptimer->timer_data.it_value,
        &current_time,
        &value->it_value
      );

      value->it_interval  = ptimer->timer_data.it_interval;

      _Thread_Enable_dispatch();
      return 0;
  }
  return -1;   /* unreached - only to remove warnings */
}
/*
 *  The abstime is a walltime.  We turn it into an interval.
 */
POSIX_Absolute_timeout_conversion_results_t _POSIX_Absolute_timeout_to_ticks(
  const struct timespec *abstime,
  Watchdog_Interval     *ticks_out
)
{
  struct timespec current_time;
  struct timespec difference;


  /*
   *  Make sure there is always a value returned.
   */
  *ticks_out = 0;

  /*
   *  Is the absolute time even valid?
   */
  if ( !_Timespec_Is_valid(abstime) )
    return POSIX_ABSOLUTE_TIMEOUT_INVALID;

  /*
   *  Is the absolute time in the past?
   */
  _TOD_Get( &current_time );

  if ( _Timespec_Less_than( abstime, &current_time ) )
    return POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST;

  /*
   *  How long until the requested absolute time?
   */
  _Timespec_Subtract( &current_time, abstime, &difference );

  /*
   *  Internally the SuperCore uses ticks, so convert to them.
   */
  *ticks_out = _Timespec_To_ticks( &difference );

  /*
   *  If the difference was 0, then the future is now.  It is so bright
   *  we better wear shades.
   */
  if ( !*ticks_out )
    return POSIX_ABSOLUTE_TIMEOUT_IS_NOW;

  /*
   *  This is the case we were expecting and it took this long to
   *  get here.
   */
  return POSIX_ABSOLUTE_TIMEOUT_IS_IN_FUTURE;
}
void _POSIX_Timer_TSR(Objects_Id timer, void *data)
{
  POSIX_Timer_Control *ptimer;
  boolean              activated;

  ptimer = (POSIX_Timer_Control *)data;

  /* Increment the number of expirations. */
  ptimer->overrun = ptimer->overrun + 1;
  /* The timer must be reprogrammed */
  if ( ( ptimer->timer_data.it_interval.tv_sec  != 0 ) ||
       ( ptimer->timer_data.it_interval.tv_nsec != 0 ) ) {
#if 0
    status = rtems_timer_fire_after(
         ptimer->timer_id, ptimer->ticks, _POSIX_Timer_TSR, ptimer );
#endif
    activated = _Watchdog_Insert_ticks_helper(
      &ptimer->Timer,
      ptimer->ticks,
      ptimer->Object.id,
      _POSIX_Timer_TSR,
      ptimer
    );
    if ( !activated )
      return;

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

    /* The state really did not change but just to be safe */
    ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
  } else {
   /* Indicates that the timer is stopped */
   ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
  }

  /*
   * The sending of the signal to the process running the handling function
   * specified for that signal is simulated
   */

  if ( pthread_kill ( ptimer->thread_id, ptimer->inf.sigev_signo ) ) {
    /* XXX error handling */
  }

  /* After the signal handler returns, the count of expirations of the
   * timer must be set to 0.
   */
  ptimer->overrun = 0;
}
int timer_gettime(
  timer_t            timerid,
  struct itimerspec *value
)
{
  POSIX_Timer_Control *ptimer;
  Objects_Locations    location;
  struct timespec      current_time;
  Watchdog_Interval    left;

  if ( !value )
    rtems_set_errno_and_return_minus_one( EINVAL );

  /* Reads the current time */
  _TOD_Get( &current_time );

  ptimer = _POSIX_Timer_Get( timerid, &location );
  switch ( location ) {

    case OBJECTS_LOCAL:

      /* Calculates the time left before the timer finishes */

      left =
        (ptimer->Timer.start_time + ptimer->Timer.initial) - /* expire */
        _Watchdog_Ticks_since_boot;                          /* now */

      _Timespec_From_ticks( left, &value->it_value );

      value->it_interval  = ptimer->timer_data.it_interval;

      _Thread_Enable_dispatch();
      return 0;

#if defined(RTEMS_MULTIPROCESSING)
    case OBJECTS_REMOTE:
#endif
    case OBJECTS_ERROR:
      break;
  }

  rtems_set_errno_and_return_minus_one( EINVAL );
}
Exemple #6
0
rtems_task Init(
  rtems_task_argument argument
)
{
  rtems_status_code status;
  rtems_time_of_day time;
  int index;

  puts( "\n\n*** NANOSECOND CLOCK TEST ***" );

  time.year   = 2007;
  time.month  = 03;
  time.day    = 24;
  time.hour   = 11;
  time.minute = 15;
  time.second = 0;
  time.ticks  = 0;

  status = rtems_clock_set( &time );
  directive_failed( status, "clock set" ); 

  /*
   *  Iterate 10 times showing difference in TOD
   */
  printf( "10 iterations of getting TOD\n" );
  for (index=0 ; index <10 ; index++ ) {
    struct timespec start, stop;
    struct timespec diff;
#if 0
    clock_gettime( CLOCK_REALTIME, &start );
    clock_gettime( CLOCK_REALTIME, &stop );
#else
    _TOD_Get( &start );
    _TOD_Get( &stop );
#endif

    subtract_em( &start, &stop, &diff );
    printf( "Start: %s:%ld\nStop : %s:%ld",
      my_ctime(start.tv_sec), start.tv_nsec,
      my_ctime(stop.tv_sec), stop.tv_nsec
    );

    printf( " --> %" PRIdtime_t ":%ld\n", diff.tv_sec, diff.tv_nsec );
  }

  /*
   *  Iterate 10 times showing difference in Uptime
   */
  printf( "\n10 iterations of getting Uptime\n" );
  for (index=0 ; index <10 ; index++ ) {
    struct timespec start, stop;
    struct timespec diff;
    rtems_clock_get_uptime( &start );
    rtems_clock_get_uptime( &stop );

    subtract_em( &start, &stop, &diff );
    printf( "%" PRIdtime_t ":%ld %" PRIdtime_t ":%ld --> %" PRIdtime_t ":%ld\n",
      start.tv_sec, start.tv_nsec,
      stop.tv_sec, stop.tv_nsec,
      diff.tv_sec, diff.tv_nsec
   );
  }

  /*
   *  Iterate 10 times showing difference in Uptime with different counts
   */
  printf( "\n10 iterations of getting Uptime with different loop values\n" );
  for (index=1 ; index <=10 ; index++ ) {
    struct timespec start, stop;
    struct timespec diff;
    int j, max = (index * 10000);
    rtems_clock_get_uptime( &start );
      for (j=0 ; j<max ; j++ )
        dummy_function_empty_body_to_force_call();
    rtems_clock_get_uptime( &stop );

    subtract_em( &start, &stop, &diff );
    printf( "loop of %d %" PRIdtime_t ":%ld %" PRIdtime_t ":%ld --> %" PRIdtime_t ":%ld\n",
      max,
      start.tv_sec, start.tv_nsec,
      stop.tv_sec, stop.tv_nsec,
      diff.tv_sec, diff.tv_nsec
   );
  }

  sleep(1);

  puts( "*** END OF NANOSECOND CLOCK TEST ***" );
  exit(0);
}
int timer_settime(
  timer_t                  timerid,
  int                      flags,
  const struct itimerspec *value,
  struct itimerspec       *ovalue
)
{
  POSIX_Timer_Control *ptimer;
  Objects_Locations    location;
  boolean              activated;

  if ( value == NULL ) {
    rtems_set_errno_and_return_minus_one( EINVAL );
  }

  /* First, it verifies if the structure "value" is correct */
  if ( ( value->it_value.tv_nsec > TOD_NANOSECONDS_PER_SECOND ) ||
       ( value->it_value.tv_nsec < 0 ) ) {
    /* The number of nanoseconds is not correct */
    rtems_set_errno_and_return_minus_one( EINVAL );
  }
  
  /* XXX check for seconds in the past */

  if ( flags != TIMER_ABSTIME && flags != POSIX_TIMER_RELATIVE ) {
    rtems_set_errno_and_return_minus_one( EINVAL );
  }

  /* If the function reaches this point, then it will be necessary to do
   * something with the structure of times of the timer: to stop, start
   * or start it again
   */

  ptimer = _POSIX_Timer_Get( timerid, &location );
  switch ( location ) {
    case OBJECTS_REMOTE:
#if defined(RTEMS_MULTIPROCESSING)
      _Thread_Dispatch();
      return -1;
     rtems_set_errno_and_return_minus_one( EINVAL );
#endif

    case OBJECTS_ERROR:
      return -1;

    case OBJECTS_LOCAL:
      /* First, it verifies if the timer must be stopped */
      if ( value->it_value.tv_sec == 0 && value->it_value.tv_nsec == 0 ) {
         /* Stop the timer */
         (void) _Watchdog_Remove( &ptimer->Timer );
         /* The old data of the timer are returned */
         if ( ovalue )
           *ovalue = ptimer->timer_data;
         /* The new data are set */
         ptimer->timer_data = *value;
         /* Indicates that the timer is created and stopped */
         ptimer->state = POSIX_TIMER_STATE_CREATE_STOP;
         /* Returns with success */
        _Thread_Enable_dispatch();
        return 0;
       }

       /* absolute or relative? */
       switch (flags) {
         case TIMER_ABSTIME:

           /* The fire time is absolute: use "rtems_time_fire_when" */
           /* First, it converts from struct itimerspec to rtems_time_of_day */

           _Watchdog_Initialize(
             &ptimer->Timer, _POSIX_Timer_TSR, ptimer->Object.id, ptimer );

           _Watchdog_Insert_seconds(
              &ptimer->Timer,
              value->it_value.tv_sec - _TOD_Seconds_since_epoch
           );

           /* Returns the old ones in "ovalue" */
           if ( ovalue )
             *ovalue = ptimer->timer_data;
           ptimer->timer_data = *value;

           /* Indicate that the time is running */
           ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;

           /* Stores the time in which the timer was started again */
           _TOD_Get( &ptimer->time );
           _Thread_Enable_dispatch();
           return 0;
           break;

         /* The fire time is relative: use "rtems_time_fire_after" */
         case POSIX_TIMER_RELATIVE:
           /* First, convert from seconds and nanoseconds to ticks */
           ptimer->ticks = _Timespec_To_ticks( &value->it_value );

           activated = _Watchdog_Insert_ticks_helper(
             &ptimer->Timer,
             ptimer->ticks,
             ptimer->Object.id,
             _POSIX_Timer_TSR,
             ptimer
           );
           if ( !activated ) {
             _Thread_Enable_dispatch();
             return 0;
           }

           /* The timer has been started and is running */
           /* return the old ones in "ovalue" */
           if ( ovalue )
             *ovalue = ptimer->timer_data;
           ptimer->timer_data = *value;

           /* Indicate that the time is running */
           ptimer->state = POSIX_TIMER_STATE_CREATE_RUN;
           _TOD_Get( &ptimer->time );
            _Thread_Enable_dispatch();
           return 0;
      }
      _Thread_Enable_dispatch();
      rtems_set_errno_and_return_minus_one( EINVAL );
  }
  return -1;   /* unreached - only to remove warnings */
}
int  adjtime(
  struct timeval *delta,
  struct timeval *olddelta
)
{
  struct timespec ts;
  long   adjustment;

  /*
   * Simple validations
   */
  if ( !delta )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( delta->tv_usec >= TOD_MICROSECONDS_PER_SECOND )
    rtems_set_errno_and_return_minus_one( EINVAL );

  if ( olddelta ) {
    olddelta->tv_sec  = 0;
    olddelta->tv_usec = 0;
  }

  /* convert delta to microseconds */
  adjustment  = (delta->tv_sec * TOD_MICROSECONDS_PER_SECOND);
  adjustment += delta->tv_usec;

  /* too small to account for */
  if ( adjustment < rtems_configuration_get_microseconds_per_tick() )
    return 0;

  /*
   * This prevents context switches while we are adjusting the TOD
   */

  _Thread_Disable_dispatch();

    _TOD_Get( &ts );

    ts.tv_sec  += delta->tv_sec;
    ts.tv_nsec += delta->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;

    /* if adjustment is too much positive */
    while ( ts.tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) {
      ts.tv_nsec -= TOD_NANOSECONDS_PER_SECOND;
      ts.tv_sec++;
    }

    /* if adjustment is too much negative */
    while ( ts.tv_nsec <= (-1 * TOD_NANOSECONDS_PER_SECOND) ) {
      ts.tv_nsec += TOD_NANOSECONDS_PER_SECOND;
      ts.tv_sec--;
    }

    _TOD_Set( &ts );

  _Thread_Enable_dispatch();

  /* set the user's output */
  if ( olddelta )
    *olddelta = *delta;

  return 0;
}