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( ¤t_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, ¤t_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( ¤t_time ); if ( _Timespec_Less_than( abstime, ¤t_time ) ) return POSIX_ABSOLUTE_TIMEOUT_IS_IN_PAST; /* * How long until the requested absolute time? */ _Timespec_Subtract( ¤t_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( ¤t_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 ); }
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; }