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