1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** POSIX wrapper for THREADX */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 /* Include necessary system files. */
22
23 #include "tx_api.h" /* Threadx API */
24 #include "pthread.h" /* Posix API */
25 #include "px_int.h" /* Posix helper functions */
26 #include <limits.h>
27
28 /**************************************************************************/
29 /* */
30 /* FUNCTION RELEASE */
31 /* */
32 /* nanosleep PORTABLE C */
33 /* 6.2.0 */
34 /* AUTHOR */
35 /* */
36 /* William E. Lamie, Microsoft Corporation */
37 /* */
38 /* DESCRIPTION */
39 /* */
40 /* This function shall cause the current thread to be suspended from */
41 /* execution until the time interval specified by the req argument has */
42 /* elapsed. */
43 /* */
44 /* INPUT */
45 /* */
46 /* req The number of real-time (as opposed */
47 /* to CPU-time) seconds and nanoseconds to */
48 /* suspend the calling thread. */
49 /* rem Points to a structure to receive the */
50 /* remaining time if the function is */
51 /* interrupted by a signal. This pointer */
52 /* may be NULL. */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* zero If the function returns because the */
57 /* requested time has elapsed. */
58 /* */
59 /* -1 If this functions fails if req argument */
60 /* specified a nanosecond value greater */
61 /* than or equal to 1 billion. */
62 /* */
63 /* */
64 /* CALLS */
65 /* */
66 /* tx_thread_sleep ThreadX thread sleep service */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Application Code */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 06-02-2021 William E. Lamie Initial Version 6.1.7 */
77 /* 10-31-2022 Scott Larson Fix bounds check, */
78 /* resulting in version 6.2.0 */
79 /* */
80 /**************************************************************************/
nanosleep(struct timespec * req,struct timespec * rem)81 INT nanosleep(struct timespec *req, struct timespec *rem)
82 {
83
84 ULONG timer_ticks;
85
86 /* Check for valid inputs - the nanosecond value must be less than 1 billion
87 and not roll over when converting to ThreadX timer ticks. */
88 if ( (!req) || (req->tv_nsec > 999999999) || ((timer_ticks = (req->tv_sec * CPU_TICKS_PER_SECOND + req->tv_nsec/NANOSECONDS_IN_CPU_TICK)) < req->tv_sec) )
89 {
90 posix_errno = EINVAL;
91 posix_set_pthread_errno(EINVAL);
92 return(ERROR);
93 }
94
95 /* Add padding of 1 so that the thread will sleep no less than the specified time,
96 except in the case that timer_ticks is ULONG_MAX */
97 if(timer_ticks != ULONG_MAX)
98 {
99 timer_ticks = timer_ticks + 1;
100 }
101
102 /* Now call ThreadX thread sleep service. */
103 tx_thread_sleep(timer_ticks);
104
105 /* Sleep completed. */
106 if (rem)
107 {
108 rem->tv_nsec = 0;
109 rem->tv_sec = 0;
110 }
111 return(OK);
112 }
113