2 * Amazon FreeRTOS POSIX V1.1.0
\r
3 * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
27 * @file FreeRTOS_POSIX_utils.c
\r
28 * @brief Implementation of utility functions in utils.h
\r
31 /* C standard library includes. */
\r
35 /* FreeRTOS+POSIX includes. */
\r
36 #include "FreeRTOS_POSIX.h"
\r
37 #include "FreeRTOS_POSIX/errno.h"
\r
38 #include "FreeRTOS_POSIX/utils.h"
\r
40 /*-----------------------------------------------------------*/
\r
42 size_t UTILS_strnlen( const char * const pcString,
\r
45 const char * pcCharPointer = pcString;
\r
48 if( pcString != NULL )
\r
50 while( ( *pcCharPointer != '\0' ) && ( xLength < xMaxLength ) )
\r
60 /*-----------------------------------------------------------*/
\r
62 int UTILS_AbsoluteTimespecToDeltaTicks( const struct timespec * const pxAbsoluteTime,
\r
63 const struct timespec * const pxCurrentTime,
\r
64 TickType_t * const pxResult )
\r
67 struct timespec xDifference = { 0 };
\r
69 /* Check parameters. */
\r
70 if( ( pxAbsoluteTime == NULL ) || ( pxCurrentTime == NULL ) || ( pxResult == NULL ) )
\r
75 /* Calculate the difference between the current time and absolute time. */
\r
78 iStatus = UTILS_TimespecSubtract( pxAbsoluteTime, pxCurrentTime, &xDifference );
\r
82 /* pxAbsoluteTime was in the past. */
\r
83 iStatus = ETIMEDOUT;
\r
85 else if( iStatus == -1 )
\r
92 /* Convert the time difference to ticks. */
\r
95 iStatus = UTILS_TimespecToTicks( &xDifference, pxResult );
\r
101 /*-----------------------------------------------------------*/
\r
103 int UTILS_TimespecToTicks( const struct timespec * const pxTimespec,
\r
104 TickType_t * const pxResult )
\r
107 int64_t llTotalTicks = 0;
\r
108 long lNanoseconds = 0;
\r
110 /* Check parameters. */
\r
111 if( ( pxTimespec == NULL ) || ( pxResult == NULL ) )
\r
115 else if( ( iStatus == 0 ) && ( UTILS_ValidateTimespec( pxTimespec ) == false ) )
\r
122 /* Convert timespec.tv_sec to ticks. */
\r
123 llTotalTicks = ( int64_t ) configTICK_RATE_HZ * ( pxTimespec->tv_sec );
\r
125 /* Convert timespec.tv_nsec to ticks. This value does not have to be checked
\r
126 * for overflow because a valid timespec has 0 <= tv_nsec < 1000000000 and
\r
127 * NANOSECONDS_PER_TICK > 1. */
\r
128 lNanoseconds = pxTimespec->tv_nsec / ( long ) NANOSECONDS_PER_TICK + /* Whole nanoseconds. */
\r
129 ( long ) ( pxTimespec->tv_nsec % ( long ) NANOSECONDS_PER_TICK != 0 ); /* Add 1 to round up if needed. */
\r
131 /* Add the nanoseconds to the total ticks. */
\r
132 llTotalTicks += ( int64_t ) lNanoseconds;
\r
134 /* Check for overflow */
\r
135 if( llTotalTicks < 0 )
\r
141 /* check if TickType_t is 32 bit or 64 bit */
\r
142 uint32_t ulTickTypeSize = sizeof( TickType_t );
\r
144 /* check for downcast overflow */
\r
145 if( ulTickTypeSize == sizeof( uint32_t ) )
\r
147 if( llTotalTicks > UINT_MAX )
\r
154 /* Write result. */
\r
155 *pxResult = ( TickType_t ) llTotalTicks;
\r
161 /*-----------------------------------------------------------*/
\r
163 void UTILS_NanosecondsToTimespec( int64_t llSource,
\r
164 struct timespec * const pxDestination )
\r
166 long lCarrySec = 0;
\r
168 /* Convert to timespec. */
\r
169 pxDestination->tv_sec = ( time_t ) ( llSource / NANOSECONDS_PER_SECOND );
\r
170 pxDestination->tv_nsec = ( long ) ( llSource % NANOSECONDS_PER_SECOND );
\r
172 /* Subtract from tv_sec if tv_nsec < 0. */
\r
173 if( pxDestination->tv_nsec < 0L )
\r
175 /* Compute the number of seconds to carry. */
\r
176 lCarrySec = ( pxDestination->tv_nsec / ( long ) NANOSECONDS_PER_SECOND ) + 1L;
\r
178 pxDestination->tv_sec -= ( time_t ) ( lCarrySec );
\r
179 pxDestination->tv_nsec += lCarrySec * ( long ) NANOSECONDS_PER_SECOND;
\r
183 /*-----------------------------------------------------------*/
\r
185 int UTILS_TimespecAdd( const struct timespec * const x,
\r
186 const struct timespec * const y,
\r
187 struct timespec * const pxResult )
\r
189 int64_t llPartialSec = 0;
\r
192 /* Check parameters. */
\r
193 if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) )
\r
200 /* Perform addition. */
\r
201 pxResult->tv_nsec = x->tv_nsec + y->tv_nsec;
\r
203 /* check for overflow in case nsec value was invalid */
\r
204 if( pxResult->tv_nsec < 0 )
\r
210 llPartialSec = ( pxResult->tv_nsec ) / NANOSECONDS_PER_SECOND;
\r
211 pxResult->tv_nsec = ( pxResult->tv_nsec ) % NANOSECONDS_PER_SECOND;
\r
212 pxResult->tv_sec = x->tv_sec + y->tv_sec + llPartialSec;
\r
214 /* check for overflow */
\r
215 if( pxResult->tv_sec < 0 )
\r
225 /*-----------------------------------------------------------*/
\r
227 int UTILS_TimespecAddNanoseconds( const struct timespec * const x,
\r
228 int64_t llNanoseconds,
\r
229 struct timespec * const pxResult )
\r
231 int64_t llTotalNSec = 0;
\r
234 /* Check parameters. */
\r
235 if( ( pxResult == NULL ) || ( x == NULL ) )
\r
242 /* add nano seconds */
\r
243 llTotalNSec = x->tv_nsec + llNanoseconds;
\r
245 /* check for nano seconds overflow */
\r
246 if( llTotalNSec < 0 )
\r
252 pxResult->tv_nsec = llTotalNSec % NANOSECONDS_PER_SECOND;
\r
253 pxResult->tv_sec = x->tv_sec + ( llTotalNSec / NANOSECONDS_PER_SECOND );
\r
255 /* check for seconds overflow */
\r
256 if( pxResult->tv_sec < 0 )
\r
266 /*-----------------------------------------------------------*/
\r
268 int UTILS_TimespecSubtract( const struct timespec * const x,
\r
269 const struct timespec * const y,
\r
270 struct timespec * const pxResult )
\r
272 int iCompareResult = 0;
\r
275 /* Check parameters. */
\r
276 if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) )
\r
283 iCompareResult = UTILS_TimespecCompare( x, y );
\r
285 /* if x < y then result would be negative, return 1 */
\r
286 if( iCompareResult == -1 )
\r
290 else if( iCompareResult == 0 )
\r
292 /* if times are the same return zero */
\r
293 pxResult->tv_sec = 0;
\r
294 pxResult->tv_nsec = 0;
\r
298 /* If x > y Perform subtraction. */
\r
299 pxResult->tv_sec = x->tv_sec - y->tv_sec;
\r
300 pxResult->tv_nsec = x->tv_nsec - y->tv_nsec;
\r
302 /* check if nano seconds value needs to borrow */
\r
303 if( pxResult->tv_nsec < 0 )
\r
305 /* Based on comparison, tv_sec > 0 */
\r
306 pxResult->tv_sec--;
\r
307 pxResult->tv_nsec += ( long ) NANOSECONDS_PER_SECOND;
\r
310 /* if nano second is negative after borrow, it is an overflow error */
\r
311 if( pxResult->tv_nsec < 0 )
\r
321 /*-----------------------------------------------------------*/
\r
323 int UTILS_TimespecCompare( const struct timespec * const x,
\r
324 const struct timespec * const y )
\r
328 /* Check parameters */
\r
329 if( ( x == NULL ) && ( y == NULL ) )
\r
333 else if( y == NULL )
\r
337 else if( x == NULL )
\r
341 else if( x->tv_sec > y->tv_sec )
\r
345 else if( x->tv_sec < y->tv_sec )
\r
351 /* seconds are equal compare nano seconds */
\r
352 if( x->tv_nsec > y->tv_nsec )
\r
356 else if( x->tv_nsec < y->tv_nsec )
\r
369 /*-----------------------------------------------------------*/
\r
371 bool UTILS_ValidateTimespec( const struct timespec * const pxTimespec )
\r
373 bool xReturn = false;
\r
375 if( pxTimespec != NULL )
\r
377 /* Verify 0 <= tv_nsec < 1000000000. */
\r
378 if( ( pxTimespec->tv_nsec >= 0 ) &&
\r
379 ( pxTimespec->tv_nsec < NANOSECONDS_PER_SECOND ) )
\r
388 /*-----------------------------------------------------------*/
\r