diff options
Diffstat (limited to 'lib/freertos-posix/FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_utils.c')
| -rwxr-xr-x | lib/freertos-posix/FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_utils.c | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/lib/freertos-posix/FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_utils.c b/lib/freertos-posix/FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_utils.c new file mode 100755 index 0000000..c121587 --- /dev/null +++ b/lib/freertos-posix/FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_utils.c @@ -0,0 +1,388 @@ +/* + * 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_utils.c + * @brief Implementation of utility functions in utils.h + */ + +/* C standard library includes. */ +#include <stddef.h> +#include <limits.h> + +/* FreeRTOS+POSIX includes. */ +#include "FreeRTOS_POSIX.h" +#include "FreeRTOS_POSIX/errno.h" +#include "FreeRTOS_POSIX/utils.h" + +/*-----------------------------------------------------------*/ + +size_t UTILS_strnlen( const char * const pcString, + size_t xMaxLength ) +{ + const char * pcCharPointer = pcString; + size_t xLength = 0; + + if( pcString != NULL ) + { + while( ( *pcCharPointer != '\0' ) && ( xLength < xMaxLength ) ) + { + xLength++; + pcCharPointer++; + } + } + + return xLength; +} + +/*-----------------------------------------------------------*/ + +int UTILS_AbsoluteTimespecToDeltaTicks( const struct timespec * const pxAbsoluteTime, + const struct timespec * const pxCurrentTime, + TickType_t * const pxResult ) +{ + int iStatus = 0; + struct timespec xDifference = { 0 }; + + /* Check parameters. */ + if( ( pxAbsoluteTime == NULL ) || ( pxCurrentTime == NULL ) || ( pxResult == NULL ) ) + { + iStatus = EINVAL; + } + + /* Calculate the difference between the current time and absolute time. */ + if( iStatus == 0 ) + { + iStatus = UTILS_TimespecSubtract( pxAbsoluteTime, pxCurrentTime, &xDifference ); + + if( iStatus == 1 ) + { + /* pxAbsoluteTime was in the past. */ + iStatus = ETIMEDOUT; + } + else if( iStatus == -1 ) + { + /* error */ + iStatus = EINVAL; + } + } + + /* Convert the time difference to ticks. */ + if( iStatus == 0 ) + { + iStatus = UTILS_TimespecToTicks( &xDifference, pxResult ); + } + + return iStatus; +} + +/*-----------------------------------------------------------*/ + +int UTILS_TimespecToTicks( const struct timespec * const pxTimespec, + TickType_t * const pxResult ) +{ + int iStatus = 0; + int64_t llTotalTicks = 0; + long lNanoseconds = 0; + + /* Check parameters. */ + if( ( pxTimespec == NULL ) || ( pxResult == NULL ) ) + { + iStatus = EINVAL; + } + else if( ( iStatus == 0 ) && ( UTILS_ValidateTimespec( pxTimespec ) == false ) ) + { + iStatus = EINVAL; + } + + if( iStatus == 0 ) + { + /* Convert timespec.tv_sec to ticks. */ + llTotalTicks = ( int64_t ) configTICK_RATE_HZ * ( pxTimespec->tv_sec ); + + /* Convert timespec.tv_nsec to ticks. This value does not have to be checked + * for overflow because a valid timespec has 0 <= tv_nsec < 1000000000 and + * NANOSECONDS_PER_TICK > 1. */ + lNanoseconds = pxTimespec->tv_nsec / ( long ) NANOSECONDS_PER_TICK + /* Whole nanoseconds. */ + ( long ) ( pxTimespec->tv_nsec % ( long ) NANOSECONDS_PER_TICK != 0 ); /* Add 1 to round up if needed. */ + + /* Add the nanoseconds to the total ticks. */ + llTotalTicks += ( int64_t ) lNanoseconds; + + /* Check for overflow */ + if( llTotalTicks < 0 ) + { + iStatus = EINVAL; + } + else + { + /* check if TickType_t is 32 bit or 64 bit */ + uint32_t ulTickTypeSize = sizeof( TickType_t ); + + /* check for downcast overflow */ + if( ulTickTypeSize == sizeof( uint32_t ) ) + { + if( llTotalTicks > UINT_MAX ) + { + iStatus = EINVAL; + } + } + } + + /* Write result. */ + *pxResult = ( TickType_t ) llTotalTicks; + } + + return iStatus; +} + +/*-----------------------------------------------------------*/ + +void UTILS_NanosecondsToTimespec( int64_t llSource, + struct timespec * const pxDestination ) +{ + long lCarrySec = 0; + + /* Convert to timespec. */ + pxDestination->tv_sec = ( time_t ) ( llSource / NANOSECONDS_PER_SECOND ); + pxDestination->tv_nsec = ( long ) ( llSource % NANOSECONDS_PER_SECOND ); + + /* Subtract from tv_sec if tv_nsec < 0. */ + if( pxDestination->tv_nsec < 0L ) + { + /* Compute the number of seconds to carry. */ + lCarrySec = ( pxDestination->tv_nsec / ( long ) NANOSECONDS_PER_SECOND ) + 1L; + + pxDestination->tv_sec -= ( time_t ) ( lCarrySec ); + pxDestination->tv_nsec += lCarrySec * ( long ) NANOSECONDS_PER_SECOND; + } +} + +/*-----------------------------------------------------------*/ + +int UTILS_TimespecAdd( const struct timespec * const x, + const struct timespec * const y, + struct timespec * const pxResult ) +{ + int64_t llPartialSec = 0; + int iStatus = 0; + + /* Check parameters. */ + if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) ) + { + iStatus = -1; + } + + if( iStatus == 0 ) + { + /* Perform addition. */ + pxResult->tv_nsec = x->tv_nsec + y->tv_nsec; + + /* check for overflow in case nsec value was invalid */ + if( pxResult->tv_nsec < 0 ) + { + iStatus = 1; + } + else + { + llPartialSec = ( pxResult->tv_nsec ) / NANOSECONDS_PER_SECOND; + pxResult->tv_nsec = ( pxResult->tv_nsec ) % NANOSECONDS_PER_SECOND; + pxResult->tv_sec = x->tv_sec + y->tv_sec + llPartialSec; + + /* check for overflow */ + if( pxResult->tv_sec < 0 ) + { + iStatus = 1; + } + } + } + + return iStatus; +} + +/*-----------------------------------------------------------*/ + +int UTILS_TimespecAddNanoseconds( const struct timespec * const x, + int64_t llNanoseconds, + struct timespec * const pxResult ) +{ + int64_t llTotalNSec = 0; + int iStatus = 0; + + /* Check parameters. */ + if( ( pxResult == NULL ) || ( x == NULL ) ) + { + iStatus = -1; + } + + if( iStatus == 0 ) + { + /* add nano seconds */ + llTotalNSec = x->tv_nsec + llNanoseconds; + + /* check for nano seconds overflow */ + if( llTotalNSec < 0 ) + { + iStatus = 1; + } + else + { + pxResult->tv_nsec = llTotalNSec % NANOSECONDS_PER_SECOND; + pxResult->tv_sec = x->tv_sec + ( llTotalNSec / NANOSECONDS_PER_SECOND ); + + /* check for seconds overflow */ + if( pxResult->tv_sec < 0 ) + { + iStatus = 1; + } + } + } + + return iStatus; +} + +/*-----------------------------------------------------------*/ + +int UTILS_TimespecSubtract( const struct timespec * const x, + const struct timespec * const y, + struct timespec * const pxResult ) +{ + int iCompareResult = 0; + int iStatus = 0; + + /* Check parameters. */ + if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) ) + { + iStatus = -1; + } + + if( iStatus == 0 ) + { + iCompareResult = UTILS_TimespecCompare( x, y ); + + /* if x < y then result would be negative, return 1 */ + if( iCompareResult == -1 ) + { + iStatus = 1; + } + else if( iCompareResult == 0 ) + { + /* if times are the same return zero */ + pxResult->tv_sec = 0; + pxResult->tv_nsec = 0; + } + else + { + /* If x > y Perform subtraction. */ + pxResult->tv_sec = x->tv_sec - y->tv_sec; + pxResult->tv_nsec = x->tv_nsec - y->tv_nsec; + + /* check if nano seconds value needs to borrow */ + if( pxResult->tv_nsec < 0 ) + { + /* Based on comparison, tv_sec > 0 */ + pxResult->tv_sec--; + pxResult->tv_nsec += ( long ) NANOSECONDS_PER_SECOND; + } + + /* if nano second is negative after borrow, it is an overflow error */ + if( pxResult->tv_nsec < 0 ) + { + iStatus = -1; + } + } + } + + return iStatus; +} + +/*-----------------------------------------------------------*/ + +int UTILS_TimespecCompare( const struct timespec * const x, + const struct timespec * const y ) +{ + int iStatus = 0; + + /* Check parameters */ + if( ( x == NULL ) && ( y == NULL ) ) + { + iStatus = 0; + } + else if( y == NULL ) + { + iStatus = 1; + } + else if( x == NULL ) + { + iStatus = -1; + } + else if( x->tv_sec > y->tv_sec ) + { + iStatus = 1; + } + else if( x->tv_sec < y->tv_sec ) + { + iStatus = -1; + } + else + { + /* seconds are equal compare nano seconds */ + if( x->tv_nsec > y->tv_nsec ) + { + iStatus = 1; + } + else if( x->tv_nsec < y->tv_nsec ) + { + iStatus = -1; + } + else + { + iStatus = 0; + } + } + + return iStatus; +} + +/*-----------------------------------------------------------*/ + +bool UTILS_ValidateTimespec( const struct timespec * const pxTimespec ) +{ + bool xReturn = false; + + if( pxTimespec != NULL ) + { + /* Verify 0 <= tv_nsec < 1000000000. */ + if( ( pxTimespec->tv_nsec >= 0 ) && + ( pxTimespec->tv_nsec < NANOSECONDS_PER_SECOND ) ) + { + xReturn = true; + } + } + + return xReturn; +} + +/*-----------------------------------------------------------*/ |
