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