]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Demo/FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator/lib/FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_utils.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Demo / FreeRTOS_Plus_POSIX_with_actor_Windows_Simulator / lib / FreeRTOS-Plus-POSIX / source / FreeRTOS_POSIX_utils.c
1 /*\r
2  * Amazon FreeRTOS POSIX V1.1.0\r
3  * Copyright (C) 2018 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\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
11  *\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
14  *\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
21  *\r
22  * http://aws.amazon.com/freertos\r
23  * http://www.FreeRTOS.org\r
24  */\r
25 \r
26 /**\r
27  * @file FreeRTOS_POSIX_utils.c\r
28  * @brief Implementation of utility functions in utils.h\r
29  */\r
30 \r
31 /* C standard library includes. */\r
32 #include <stddef.h>\r
33 #include <limits.h>\r
34 \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
39 \r
40 /*-----------------------------------------------------------*/\r
41 \r
42 size_t UTILS_strnlen( const char * const pcString,\r
43                       size_t xMaxLength )\r
44 {\r
45     const char * pcCharPointer = pcString;\r
46     size_t xLength = 0;\r
47 \r
48     if( pcString != NULL )\r
49     {\r
50         while( ( *pcCharPointer != '\0' ) && ( xLength < xMaxLength ) )\r
51         {\r
52             xLength++;\r
53             pcCharPointer++;\r
54         }\r
55     }\r
56 \r
57     return xLength;\r
58 }\r
59 \r
60 /*-----------------------------------------------------------*/\r
61 \r
62 int UTILS_AbsoluteTimespecToDeltaTicks( const struct timespec * const pxAbsoluteTime,\r
63                                         const struct timespec * const pxCurrentTime,\r
64                                         TickType_t * const pxResult )\r
65 {\r
66     int iStatus = 0;\r
67     struct timespec xDifference = { 0 };\r
68 \r
69     /* Check parameters. */\r
70     if( ( pxAbsoluteTime == NULL ) || ( pxCurrentTime == NULL ) || ( pxResult == NULL ) )\r
71     {\r
72         iStatus = EINVAL;\r
73     }\r
74 \r
75     /* Calculate the difference between the current time and absolute time. */\r
76     if( iStatus == 0 )\r
77     {\r
78         iStatus = UTILS_TimespecSubtract( pxAbsoluteTime, pxCurrentTime, &xDifference );\r
79 \r
80         if( iStatus == 1 )\r
81         {\r
82             /* pxAbsoluteTime was in the past. */\r
83             iStatus = ETIMEDOUT;\r
84         }\r
85         else if( iStatus == -1 )\r
86         {\r
87             /* error */\r
88             iStatus = EINVAL;\r
89         }\r
90     }\r
91 \r
92     /* Convert the time difference to ticks. */\r
93     if( iStatus == 0 )\r
94     {\r
95         iStatus = UTILS_TimespecToTicks( &xDifference, pxResult );\r
96     }\r
97 \r
98     return iStatus;\r
99 }\r
100 \r
101 /*-----------------------------------------------------------*/\r
102 \r
103 int UTILS_TimespecToTicks( const struct timespec * const pxTimespec,\r
104                            TickType_t * const pxResult )\r
105 {\r
106     int iStatus = 0;\r
107     int64_t llTotalTicks = 0;\r
108     long lNanoseconds = 0;\r
109 \r
110     /* Check parameters. */\r
111     if( ( pxTimespec == NULL ) || ( pxResult == NULL ) )\r
112     {\r
113         iStatus = EINVAL;\r
114     }\r
115     else if( ( iStatus == 0 ) && ( UTILS_ValidateTimespec( pxTimespec ) == false ) )\r
116     {\r
117         iStatus = EINVAL;\r
118     }\r
119 \r
120     if( iStatus == 0 )\r
121     {\r
122         /* Convert timespec.tv_sec to ticks. */\r
123         llTotalTicks = ( int64_t ) configTICK_RATE_HZ * ( pxTimespec->tv_sec );\r
124 \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
130 \r
131         /* Add the nanoseconds to the total ticks. */\r
132         llTotalTicks += ( int64_t ) lNanoseconds;\r
133 \r
134         /* Check for overflow */\r
135         if( llTotalTicks < 0 )\r
136         {\r
137             iStatus = EINVAL;\r
138         }\r
139         else\r
140         {\r
141             /* check if TickType_t is 32 bit or 64 bit */\r
142             uint32_t ulTickTypeSize = sizeof( TickType_t );\r
143 \r
144             /* check for downcast overflow */\r
145             if( ulTickTypeSize == sizeof( uint32_t ) )\r
146             {\r
147                 if( llTotalTicks > UINT_MAX )\r
148                 {\r
149                     iStatus = EINVAL;\r
150                 }\r
151             }\r
152         }\r
153 \r
154         /* Write result. */\r
155         *pxResult = ( TickType_t ) llTotalTicks;\r
156     }\r
157 \r
158     return iStatus;\r
159 }\r
160 \r
161 /*-----------------------------------------------------------*/\r
162 \r
163 void UTILS_NanosecondsToTimespec( int64_t llSource,\r
164                                   struct timespec * const pxDestination )\r
165 {\r
166     long lCarrySec = 0;\r
167 \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
171 \r
172     /* Subtract from tv_sec if tv_nsec < 0. */\r
173     if( pxDestination->tv_nsec < 0L )\r
174     {\r
175         /* Compute the number of seconds to carry. */\r
176         lCarrySec = ( pxDestination->tv_nsec / ( long ) NANOSECONDS_PER_SECOND ) + 1L;\r
177 \r
178         pxDestination->tv_sec -= ( time_t ) ( lCarrySec );\r
179         pxDestination->tv_nsec += lCarrySec * ( long ) NANOSECONDS_PER_SECOND;\r
180     }\r
181 }\r
182 \r
183 /*-----------------------------------------------------------*/\r
184 \r
185 int UTILS_TimespecAdd( const struct timespec * const x,\r
186                        const struct timespec * const y,\r
187                        struct timespec * const pxResult )\r
188 {\r
189     int64_t llPartialSec = 0;\r
190     int iStatus = 0;\r
191 \r
192     /* Check parameters. */\r
193     if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) )\r
194     {\r
195         iStatus = -1;\r
196     }\r
197 \r
198     if( iStatus == 0 )\r
199     {\r
200         /* Perform addition. */\r
201         pxResult->tv_nsec = x->tv_nsec + y->tv_nsec;\r
202 \r
203         /* check for overflow in case nsec value was invalid */\r
204         if( pxResult->tv_nsec < 0 )\r
205         {\r
206             iStatus = 1;\r
207         }\r
208         else\r
209         {\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
213 \r
214             /* check for overflow */\r
215             if( pxResult->tv_sec < 0 )\r
216             {\r
217                 iStatus = 1;\r
218             }\r
219         }\r
220     }\r
221 \r
222     return iStatus;\r
223 }\r
224 \r
225 /*-----------------------------------------------------------*/\r
226 \r
227 int UTILS_TimespecAddNanoseconds( const struct timespec * const x,\r
228                                   int64_t llNanoseconds,\r
229                                   struct timespec * const pxResult )\r
230 {\r
231     int64_t llTotalNSec = 0;\r
232     int iStatus = 0;\r
233 \r
234     /* Check parameters. */\r
235     if( ( pxResult == NULL ) || ( x == NULL ) )\r
236     {\r
237         iStatus = -1;\r
238     }\r
239 \r
240     if( iStatus == 0 )\r
241     {\r
242         /* add nano seconds */\r
243         llTotalNSec = x->tv_nsec + llNanoseconds;\r
244 \r
245         /* check for nano seconds overflow */\r
246         if( llTotalNSec < 0 )\r
247         {\r
248             iStatus = 1;\r
249         }\r
250         else\r
251         {\r
252             pxResult->tv_nsec = llTotalNSec % NANOSECONDS_PER_SECOND;\r
253             pxResult->tv_sec = x->tv_sec + ( llTotalNSec / NANOSECONDS_PER_SECOND );\r
254 \r
255             /* check for seconds overflow */\r
256             if( pxResult->tv_sec < 0 )\r
257             {\r
258                 iStatus = 1;\r
259             }\r
260         }\r
261     }\r
262 \r
263     return iStatus;\r
264 }\r
265 \r
266 /*-----------------------------------------------------------*/\r
267 \r
268 int UTILS_TimespecSubtract( const struct timespec * const x,\r
269                             const struct timespec * const y,\r
270                             struct timespec * const pxResult )\r
271 {\r
272     int iCompareResult = 0;\r
273     int iStatus = 0;\r
274 \r
275     /* Check parameters. */\r
276     if( ( pxResult == NULL ) || ( x == NULL ) || ( y == NULL ) )\r
277     {\r
278         iStatus = -1;\r
279     }\r
280 \r
281     if( iStatus == 0 )\r
282     {\r
283         iCompareResult = UTILS_TimespecCompare( x, y );\r
284 \r
285         /* if x < y then result would be negative, return 1 */\r
286         if( iCompareResult == -1 )\r
287         {\r
288             iStatus = 1;\r
289         }\r
290         else if( iCompareResult == 0 )\r
291         {\r
292             /* if times are the same return zero */\r
293             pxResult->tv_sec = 0;\r
294             pxResult->tv_nsec = 0;\r
295         }\r
296         else\r
297         {\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
301 \r
302             /* check if nano seconds value needs to borrow */\r
303             if( pxResult->tv_nsec < 0 )\r
304             {\r
305                 /* Based on comparison, tv_sec > 0 */\r
306                 pxResult->tv_sec--;\r
307                 pxResult->tv_nsec += ( long ) NANOSECONDS_PER_SECOND;\r
308             }\r
309 \r
310             /* if nano second is negative after borrow, it is an overflow error */\r
311             if( pxResult->tv_nsec < 0 )\r
312             {\r
313                 iStatus = -1;\r
314             }\r
315         }\r
316     }\r
317 \r
318     return iStatus;\r
319 }\r
320 \r
321 /*-----------------------------------------------------------*/\r
322 \r
323 int UTILS_TimespecCompare( const struct timespec * const x,\r
324                            const struct timespec * const y )\r
325 {\r
326     int iStatus = 0;\r
327 \r
328     /* Check parameters */\r
329     if( ( x == NULL ) && ( y == NULL ) )\r
330     {\r
331         iStatus = 0;\r
332     }\r
333     else if( y == NULL )\r
334     {\r
335         iStatus = 1;\r
336     }\r
337     else if( x == NULL )\r
338     {\r
339         iStatus = -1;\r
340     }\r
341     else if( x->tv_sec > y->tv_sec )\r
342     {\r
343         iStatus = 1;\r
344     }\r
345     else if( x->tv_sec < y->tv_sec )\r
346     {\r
347         iStatus = -1;\r
348     }\r
349     else\r
350     {\r
351         /* seconds are equal compare nano seconds */\r
352         if( x->tv_nsec > y->tv_nsec )\r
353         {\r
354             iStatus = 1;\r
355         }\r
356         else if( x->tv_nsec < y->tv_nsec )\r
357         {\r
358             iStatus = -1;\r
359         }\r
360         else\r
361         {\r
362             iStatus = 0;\r
363         }\r
364     }\r
365 \r
366     return iStatus;\r
367 }\r
368 \r
369 /*-----------------------------------------------------------*/\r
370 \r
371 bool UTILS_ValidateTimespec( const struct timespec * const pxTimespec )\r
372 {\r
373     bool xReturn = false;\r
374 \r
375     if( pxTimespec != NULL )\r
376     {\r
377         /* Verify 0 <= tv_nsec < 1000000000. */\r
378         if( ( pxTimespec->tv_nsec >= 0 ) &&\r
379             ( pxTimespec->tv_nsec < NANOSECONDS_PER_SECOND ) )\r
380         {\r
381             xReturn = true;\r
382         }\r
383     }\r
384 \r
385     return xReturn;\r
386 }\r
387 \r
388 /*-----------------------------------------------------------*/\r