/* * $Id$ */ #include #include #include #include #include #include #include /* * 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; if ( rqtp->tv_nsec < 0 || rqtp->tv_nsec >= TOD_NANOSECONDS_PER_SECOND ) { errno = EINVAL; return -1; } /* XXX this is interruptible by a posix signal */ /* XXX rmtp is the time remaining on the timer -- we do not support this */ 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(); if ( rmtp ) { /* XXX calculate time remaining */ } return 0; /* XXX should account for signal */ } /* * 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(); }