summaryrefslogblamecommitdiffstats
path: root/c/src/exec/posix/src/time.c
blob: 7397635786e453b6419a67a21a42e24fecc23a78 (plain) (tree)
1
2
3
4
5
6
7
8
9
  
        

   
                   
                 
                  

                         

                               











                                                                         






                                               








                                                               


  









                                               
                   
















                                                                           








                                        



























































                                                                             










                                        









































                                                                                










                                        






















                                                                                







































































                                                            





















                                                                            




































                                                                 
/*
 *  $Id$
 */

#include <assert.h>
#include <time.h>
#include <errno.h>

#include <rtems/system.h>
#include <rtems/score/isr.h>
#include <rtems/score/thread.h>
#include <rtems/score/tod.h>

/*
 *  Seconds from January 1, 1970 to January 1, 1988.  Used to account for
 *  differences between POSIX API and RTEMS core.
 */

#define POSIX_TIME_SECONDS_1970_THROUGH_1988 \
  (((1987 - 1970 + 1)  * TOD_SECONDS_PER_NON_LEAP_YEAR) + \
  (4 * TOD_SECONDS_PER_DAY))

/*
 *  _POSIX_Time_Spec_to_interval
 */

Watchdog_Interval _POSIX_Time_Spec_to_interval(
  const struct timespec *time
)
{
  Watchdog_Interval  ticks;

  ticks  = (time->tv_sec * TOD_MICROSECONDS_PER_SECOND) / 
             _TOD_Microseconds_per_tick;

  ticks += (time->tv_nsec / TOD_NANOSECONDS_PER_MICROSECOND) / 
             _TOD_Microseconds_per_tick;

  return ticks;
}

/*
 *  4.5.1 Get System Time, P1003.1b-1993, p. 91
 */

time_t time(
  time_t   *tloc
)
{
  time_t  seconds_since_epoch;

  if ( !_TOD_Is_set() ) {
    errno = EINVAL;
    return -1;
  }

  /*
   *  Internally the RTEMS epoch is 1988.  This must be taken into account.
   */

  seconds_since_epoch = _TOD_Seconds_since_epoch;
     
  seconds_since_epoch += POSIX_TIME_SECONDS_1970_THROUGH_1988;

  if ( tloc )
    *tloc = seconds_since_epoch;

  return seconds_since_epoch;
}

/*
 *  14.2.1 Clocks, P1003.1b-1993, p. 263
 */

int clock_settime(
  clockid_t              clock_id,
  const struct timespec *tp
)
{
  struct tm         split_time;
  TOD_Control       tod;
  Watchdog_Interval seconds;

  assert( tp );

  switch ( clock_id ) {
 
    case CLOCK_REALTIME:
      (void) gmtime_r( &tp->tv_sec, &split_time );
 
      /*
       *  Convert the tm structure format to that used by the TOD Handler
       *
       *  NOTE: TOD Handler does not honor leap seconds.
       */

      tod.year   = split_time.tm_year + 1900;  /* RHS is years since 1900 */
      tod.month  = split_time.tm_mon + 1;      /* RHS uses 0-11 */
      tod.day    = split_time.tm_mday;
      tod.hour   = split_time.tm_hour;
      tod.minute = split_time.tm_min;
      tod.second = split_time.tm_sec;  /* RHS allows 0-61 for leap seconds */

      tod.ticks  = (tp->tv_nsec / TOD_NANOSECONDS_PER_MICROSECOND) /
                      _TOD_Microseconds_per_tick;

      if ( !_TOD_Validate( &tod ) ) {
        errno = EINVAL;
        return -1;
      }
 
      /*
       *  We can't use the tp->tv_sec field because it is based on 
       *  a different EPOCH.
       */

      seconds = _TOD_To_seconds( &tod );
      _Thread_Disable_dispatch();
        _TOD_Set( &tod, seconds );
      _Thread_Enable_dispatch();
      break;
 
#ifdef _POSIX_CPUTIME
    case CLOCK_PROCESS_CPUTIME:
      return POSIX_NOT_IMPLEMENTED();
      break;
#endif
 
#ifdef _POSIX_THREAD_CPUTIME
    case CLOCK_THREAD_CPUTIME:
      return POSIX_NOT_IMPLEMENTED();
      break;
#endif
    default:
      errno = EINVAL;
      return -1;
 
  }
  return 0;
}

/*
 *  14.2.1 Clocks, P1003.1b-1993, p. 263
 */

int clock_gettime(
  clockid_t        clock_id,
  struct timespec *tp
)
{
  ISR_Level      level;
  time_t         seconds;
  long           ticks;

  assert( tp );

  switch ( clock_id ) {

    case CLOCK_REALTIME:
      if ( !_TOD_Is_set() ) {  /* XXX does posix allow it to not be set? */
        errno = EINVAL;
        return -1;
      }
 
      _ISR_Disable( level );
        seconds = _TOD_Seconds_since_epoch;
        ticks   = _TOD_Current.ticks;
      _ISR_Enable( level );
 
      tp->tv_sec  = seconds + POSIX_TIME_SECONDS_1970_THROUGH_1988;
      tp->tv_nsec = ticks * _TOD_Microseconds_per_tick * 
                      TOD_NANOSECONDS_PER_MICROSECOND; 
      break;

#ifdef _POSIX_CPUTIME
    case CLOCK_PROCESS_CPUTIME:
      /* could base this on _TOD_Ticks_since_boot -- must make set work though*/
      return POSIX_NOT_IMPLEMENTED();
      break;
#endif

#ifdef _POSIX_THREAD_CPUTIME
    case CLOCK_THREAD_CPUTIME:
      return POSIX_NOT_IMPLEMENTED();
      break;
#endif
    default:
      errno = EINVAL;
      return -1;

  }
  return 0;
}

/*
 *  14.2.1 Clocks, P1003.1b-1993, p. 263
 */

int clock_getres(
  clockid_t        clock_id,
  struct timespec *res
)
{
  switch ( clock_id ) {
 
    /*
     *  All time in rtems is based on the same clock tick.
     */

    case CLOCK_REALTIME:
    case CLOCK_PROCESS_CPUTIME:
    case CLOCK_THREAD_CPUTIME:
      if ( res ) {
        res->tv_sec  = _TOD_Microseconds_per_tick / TOD_MICROSECONDS_PER_SECOND;
        res->tv_nsec = 
          (_TOD_Microseconds_per_tick % TOD_MICROSECONDS_PER_SECOND) *
            TOD_NANOSECONDS_PER_MICROSECOND;
      }
      break;
 
    default:
      errno = EINVAL;
      return -1;
 
  }
  return 0;
}

/*
 *  14.2.2 Create a Per-Process Timer, P1003.1b-1993, p. 264
 */

int timer_create(
  clockid_t        clock_id,
  struct sigevent *evp,
  timer_t         *timerid
)
{
  return POSIX_NOT_IMPLEMENTED();
}

/*
 *  14.2.3 Delete a Per_process Timer, P1003.1b-1993, p. 266
 */

int timer_delete(
  timer_t timerid
)
{
  return POSIX_NOT_IMPLEMENTED();
}

/*
 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
 */

int timer_settime(
  timer_t                  timerid,
  int                      flags,
  const struct itimerspec *value,
  struct itimerspec       *ovalue
)
{
  return POSIX_NOT_IMPLEMENTED();
}

/*
 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
 */

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

/*
 *  14.2.4 Per-Process Timers, P1003.1b-1993, p. 267
 */

int timer_getoverrun(
  timer_t   timerid
)
{
  return POSIX_NOT_IMPLEMENTED();
}

/*
 *  14.2.5 High Resolution Sleep, P1003.1b-1993, p. 269
 */

int nanosleep(
  const struct timespec  *rqtp,
  struct timespec        *rmtp
)
{
  Watchdog_Interval ticks;

/* XXX this is interruptible by a posix signal */

/* XXX rmtp is the time remaining on the timer -- we do not support this */

/* XXX rmtp may be NULL */

  ticks = _POSIX_Time_Spec_to_interval( rqtp );
  
  _Thread_Disable_dispatch();
    _Thread_Set_state( _Thread_Executing, STATES_WAITING_FOR_TIME );
    _Watchdog_Initialize(
      &_Thread_Executing->Timer,
      _Thread_Delay_ended,          /* XXX may need to be POSIX specific */
      _Thread_Executing->Object.id,
      NULL
    );
    _Watchdog_Insert_ticks( &_Thread_Executing->Timer, ticks );
  _Thread_Enable_dispatch();
  return 0;                    /* XXX should account for signal/remaining */

}

/*
 *  20.1.3 Accessing a Process CPU-time CLock, P1003.4b/D8, p. 55
 */

int clock_getcpuclockid(
  pid_t      pid,
  clockid_t *clock_id
)
{
  return POSIX_NOT_IMPLEMENTED();
}

/*
 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
 */

int clock_setenable_attr(
  clockid_t    clock_id,
  int          attr
)
{
  return POSIX_NOT_IMPLEMENTED();
}

/*
 *  20.1.5 CPU-time Clock Attribute Access, P1003.4b/D8, p. 58
 */

int clock_getenable_attr(
  clockid_t    clock_id,
  int         *attr
)
{
  return POSIX_NOT_IMPLEMENTED();
}