/* * Amazon FreeRTOS POSIX V1.1.0 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * http://aws.amazon.com/freertos * http://www.FreeRTOS.org */ /** * @file FreeRTOS_POSIX_clock.c * @brief Implementation of clock functions in time.h */ /* C standard library includes. */ #include #include /* FreeRTOS+POSIX includes. */ #include "FreeRTOS_POSIX.h" #include "FreeRTOS_POSIX/errno.h" #include "FreeRTOS_POSIX/time.h" #include "FreeRTOS_POSIX/utils.h" /* Declaration of snprintf. The header stdio.h is not included because it * includes conflicting symbols on some platforms. */ extern int snprintf( char * s, size_t n, const char * format, ... ); /*-----------------------------------------------------------*/ clock_t clock( void ) { /* This function is currently unsupported. It will always return -1. */ return ( clock_t ) -1; } /*-----------------------------------------------------------*/ int clock_getcpuclockid( pid_t pid, clockid_t * clock_id ) { /* Silence warnings about unused parameters. */ ( void ) pid; ( void ) clock_id; /* This function is currently unsupported. It will always return EPERM. */ return EPERM; } /*-----------------------------------------------------------*/ int clock_getres( clockid_t clock_id, struct timespec * res ) { /* Silence warnings about unused parameters. */ ( void ) clock_id; /* Convert FreeRTOS tick resolution as timespec. */ if( res != NULL ) { res->tv_sec = 0; res->tv_nsec = NANOSECONDS_PER_TICK; } return 0; } /*-----------------------------------------------------------*/ int clock_gettime( clockid_t clock_id, struct timespec * tp ) { TimeOut_t xCurrentTime = { 0 }; /* Intermediate variable used to convert TimeOut_t to struct timespec. * Also used to detect overflow issues. It must be unsigned because the * behavior of signed integer overflow is undefined. */ uint64_t ullTickCount = 0ULL; /* Silence warnings about unused parameters. */ ( void ) clock_id; /* Get the current tick count and overflow count. vTaskSetTimeOutState() * is used to get these values because they are both static in tasks.c. */ vTaskSetTimeOutState( &xCurrentTime ); /* Adjust the tick count for the number of times a TickType_t has overflowed. * portMAX_DELAY should be the maximum value of a TickType_t. */ ullTickCount = ( uint64_t ) ( xCurrentTime.xOverflowCount ) << ( sizeof( TickType_t ) * 8 ); /* Add the current tick count. */ ullTickCount += xCurrentTime.xTimeOnEntering; /* Convert ullTickCount to timespec. */ UTILS_NanosecondsToTimespec( ( int64_t ) ullTickCount * NANOSECONDS_PER_TICK, tp ); return 0; } /*-----------------------------------------------------------*/ int clock_nanosleep( clockid_t clock_id, int flags, const struct timespec * rqtp, struct timespec * rmtp ) { int iStatus = 0; TickType_t xSleepTime = 0; struct timespec xCurrentTime = { 0 }; /* Silence warnings about unused parameters. */ ( void ) clock_id; ( void ) rmtp; ( void ) flags; /* This is only ignored if INCLUDE_vTaskDelayUntil is 0. */ /* Check rqtp. */ if( UTILS_ValidateTimespec( rqtp ) == false ) { iStatus = EINVAL; } /* Get current time */ if( ( iStatus == 0 ) && ( clock_gettime( CLOCK_REALTIME, &xCurrentTime ) != 0 ) ) { iStatus = EINVAL; } if( iStatus == 0 ) { /* Check for absolute time sleep. */ if( ( flags & TIMER_ABSTIME ) == TIMER_ABSTIME ) { /* Get current time */ if( clock_gettime( CLOCK_REALTIME, &xCurrentTime ) != 0 ) { iStatus = EINVAL; } /* Get number of ticks until absolute time. */ if( ( iStatus == 0 ) && ( UTILS_AbsoluteTimespecToDeltaTicks( rqtp, &xCurrentTime, &xSleepTime ) == 0 ) ) { /* Delay until absolute time if vTaskDelayUntil is available. */ #if ( INCLUDE_vTaskDelayUntil == 1 ) /* Get the current tick count. This variable isn't declared * at the top of the function because it's only used and needed * if vTaskDelayUntil is available. */ TickType_t xCurrentTicks = xTaskGetTickCount(); /* Delay until absolute time. */ vTaskDelayUntil( &xCurrentTicks, xSleepTime ); #else /* If vTaskDelayUntil isn't available, ignore the TIMER_ABSTIME flag * and sleep for a relative time. */ vTaskDelay( xSleepTime ); #endif } } else { /* If TIMER_ABSTIME isn't specified, convert rqtp to ticks and * sleep for a relative time. */ if( UTILS_TimespecToTicks( rqtp, &xSleepTime ) == 0 ) { vTaskDelay( xSleepTime ); } } } return iStatus; } /*-----------------------------------------------------------*/ int clock_settime( clockid_t clock_id, const struct timespec * tp ) { /* Silence warnings about unused parameters. */ ( void ) clock_id; ( void ) tp; /* This function is currently unsupported. It will always return -1 and * set errno to EPERM. */ errno = EPERM; return -1; } /*-----------------------------------------------------------*/ int nanosleep( const struct timespec * rqtp, struct timespec * rmtp ) { int iStatus = 0; TickType_t xSleepTime = 0; /* Silence warnings about unused parameters. */ ( void ) rmtp; /* Check rqtp. */ if( UTILS_ValidateTimespec( rqtp ) == false ) { errno = EINVAL; iStatus = -1; } if( iStatus == 0 ) { /* Convert rqtp to ticks and delay. */ if( UTILS_TimespecToTicks( rqtp, &xSleepTime ) == 0 ) { vTaskDelay( xSleepTime ); } } return iStatus; } /*-----------------------------------------------------------*/