1 /*
2  * Copyright (c) 2018 Intel Corporation
3  * Copyright (c) 2018 Friedt Professional Engineering Services, Inc
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <errno.h>
9 #include <time.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/posix/sys/time.h>
13 #include <zephyr/posix/unistd.h>
14 #include <zephyr/sys/clock.h>
15 
clock_gettime(clockid_t clock_id,struct timespec * ts)16 int clock_gettime(clockid_t clock_id, struct timespec *ts)
17 {
18 	int ret;
19 
20 	ret = sys_clock_gettime(sys_clock_from_clockid((int)clock_id), ts);
21 	if (ret < 0) {
22 		errno = -ret;
23 		return -1;
24 	}
25 
26 	return 0;
27 }
28 
clock_getres(clockid_t clock_id,struct timespec * res)29 int clock_getres(clockid_t clock_id, struct timespec *res)
30 {
31 	BUILD_ASSERT(CONFIG_SYS_CLOCK_TICKS_PER_SEC > 0 &&
32 			     CONFIG_SYS_CLOCK_TICKS_PER_SEC <= NSEC_PER_SEC,
33 		     "CONFIG_SYS_CLOCK_TICKS_PER_SEC must be > 0 and <= NSEC_PER_SEC");
34 
35 	if (!(clock_id == CLOCK_MONOTONIC || clock_id == CLOCK_REALTIME ||
36 	      clock_id == CLOCK_PROCESS_CPUTIME_ID)) {
37 		errno = EINVAL;
38 		return -1;
39 	}
40 
41 	if (res != NULL) {
42 		*res = (struct timespec){
43 			.tv_sec = 0,
44 			.tv_nsec = NSEC_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC,
45 		};
46 	}
47 
48 	return 0;
49 }
50 
51 /**
52  * @brief Set the time of the specified clock.
53  *
54  * See IEEE 1003.1.
55  *
56  * Note that only the `CLOCK_REALTIME` clock can be set using this
57  * call.
58  */
clock_settime(clockid_t clock_id,const struct timespec * tp)59 int clock_settime(clockid_t clock_id, const struct timespec *tp)
60 {
61 	int ret;
62 
63 	ret = sys_clock_settime(sys_clock_from_clockid((int)clock_id), tp);
64 	if (ret < 0) {
65 		errno = -ret;
66 		return -1;
67 	}
68 
69 	return 0;
70 }
71 
72 /*
73  * Note: usleep() was removed in Issue 7.
74  *
75  * It is kept here for compatibility purposes.
76  *
77  * For more information, please see
78  * https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap01.html
79  * https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap03.html
80  */
usleep(useconds_t useconds)81 int usleep(useconds_t useconds)
82 {
83 	int32_t rem;
84 
85 	if (useconds >= USEC_PER_SEC) {
86 		errno = EINVAL;
87 		return -1;
88 	}
89 
90 	rem = k_usleep(useconds);
91 	__ASSERT_NO_MSG(rem >= 0);
92 	if (rem > 0) {
93 		/* sleep was interrupted by a call to k_wakeup() */
94 		errno = EINTR;
95 		return -1;
96 	}
97 
98 	return 0;
99 }
100 
nanosleep(const struct timespec * rqtp,struct timespec * rmtp)101 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
102 {
103 	int ret;
104 
105 	if (rqtp == NULL) {
106 		errno = EFAULT;
107 		return -1;
108 	}
109 
110 	ret = sys_clock_nanosleep(SYS_CLOCK_REALTIME, 0, rqtp, rmtp);
111 	if (ret < 0) {
112 		errno = -ret;
113 		return -1;
114 	}
115 
116 	return 0;
117 }
118 
clock_getcpuclockid(pid_t pid,clockid_t * clock_id)119 int clock_getcpuclockid(pid_t pid, clockid_t *clock_id)
120 {
121 	/* We don't allow any process ID but our own.  */
122 	if (pid != 0 && pid != getpid()) {
123 		return EPERM;
124 	}
125 
126 	*clock_id = CLOCK_PROCESS_CPUTIME_ID;
127 
128 	return 0;
129 }
130