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