in FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_timer.c [190:291]
int timer_settime( timer_t timerid,
int flags,
const struct itimerspec * value,
struct itimerspec * ovalue )
{
int iStatus = 0;
TimerHandle_t xTimerHandle = timerid;
timer_internal_t * pxTimer = ( timer_internal_t * ) pvTimerGetTimerID( xTimerHandle );
TickType_t xNextTimerExpiration = 0, xTimerExpirationPeriod = 0;
/* Validate the value argument, but only if the timer isn't being disarmed. */
if( TIMESPEC_IS_NOT_ZERO( value->it_value ) )
{
if( ( UTILS_ValidateTimespec( &value->it_interval ) == false ) ||
( UTILS_ValidateTimespec( &value->it_value ) == false ) )
{
errno = EINVAL;
iStatus = -1;
}
}
/* Set ovalue, if given. */
if( ovalue != NULL )
{
( void ) timer_gettime( timerid, ovalue );
}
/* Stop the timer if it's currently active. */
if( ( iStatus == 0 ) && xTimerIsTimerActive( xTimerHandle ) )
{
( void ) xTimerStop( xTimerHandle, portMAX_DELAY );
}
/* Only restart the timer if it_value is not zero. */
if( ( iStatus == 0 ) && TIMESPEC_IS_NOT_ZERO( value->it_value ) )
{
/* Convert it_interval to ticks, but only if it_interval is not 0. If
* it_interval is 0, then the timer is not periodic. */
if( TIMESPEC_IS_NOT_ZERO( value->it_interval ) )
{
( void ) UTILS_TimespecToTicks( &value->it_interval, &xTimerExpirationPeriod );
}
/* Set the new timer period. A non-periodic timer will have its period set
* to portMAX_DELAY. */
pxTimer->xTimerPeriod = xTimerExpirationPeriod;
/* Convert it_value to ticks, but only if it_value is not 0. If it_value
* is 0, then the timer will remain disarmed. */
if( TIMESPEC_IS_NOT_ZERO( value->it_value ) )
{
/* Absolute timeout. */
if( ( flags & TIMER_ABSTIME ) == TIMER_ABSTIME )
{
struct timespec xCurrentTime = { 0 };
/* Get current time */
if( clock_gettime( CLOCK_REALTIME, &xCurrentTime ) != 0 )
{
iStatus = EINVAL;
}
else
{
iStatus = UTILS_AbsoluteTimespecToDeltaTicks( &value->it_value, &xCurrentTime, &xNextTimerExpiration );
}
/* Make sure xNextTimerExpiration is zero in case we got negative time difference */
if( iStatus != 0 )
{
xNextTimerExpiration = 0;
if( iStatus == ETIMEDOUT )
{
/* Set Status to 0 as absolute time is past is treated as expiry but not an error */
iStatus = 0;
}
}
}
/* Relative timeout. */
else
{
( void ) UTILS_TimespecToTicks( &value->it_value, &xNextTimerExpiration );
}
}
/* If xNextTimerExpiration is still 0, that means that it_value specified
* an absolute timeout in the past. Per POSIX spec, a notification should be
* triggered immediately. */
if( xNextTimerExpiration == 0 )
{
prvTimerCallback( xTimerHandle );
}
else
{
/* Set the timer to expire at the it_value, then start it. */
( void ) xTimerChangePeriod( xTimerHandle, xNextTimerExpiration, portMAX_DELAY );
( void ) xTimerStart( xTimerHandle, xNextTimerExpiration );
}
}
return iStatus;
}