xref: /freebsd/sys/compat/linux/linux_time.c (revision 685dc743)
1ad2056f2SAlexander Leidinger /*	$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */
2ad2056f2SAlexander Leidinger 
3ad2056f2SAlexander Leidinger /*-
4b61a5730SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
57f2d13d6SPedro F. Giffuni  *
6ad2056f2SAlexander Leidinger  * Copyright (c) 2001 The NetBSD Foundation, Inc.
7ad2056f2SAlexander Leidinger  * All rights reserved.
8ad2056f2SAlexander Leidinger  *
9ad2056f2SAlexander Leidinger  * This code is derived from software contributed to The NetBSD Foundation
10ad2056f2SAlexander Leidinger  * by Emmanuel Dreyfus.
11ad2056f2SAlexander Leidinger  *
12ad2056f2SAlexander Leidinger  * Redistribution and use in source and binary forms, with or without
13ad2056f2SAlexander Leidinger  * modification, are permitted provided that the following conditions
14ad2056f2SAlexander Leidinger  * are met:
15ad2056f2SAlexander Leidinger  * 1. Redistributions of source code must retain the above copyright
16ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer.
17ad2056f2SAlexander Leidinger  * 2. Redistributions in binary form must reproduce the above copyright
18ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer in the
19ad2056f2SAlexander Leidinger  *    documentation and/or other materials provided with the distribution.
20ad2056f2SAlexander Leidinger  *
21ad2056f2SAlexander Leidinger  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22ad2056f2SAlexander Leidinger  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23ad2056f2SAlexander Leidinger  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24ad2056f2SAlexander Leidinger  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25ad2056f2SAlexander Leidinger  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26ad2056f2SAlexander Leidinger  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27ad2056f2SAlexander Leidinger  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28ad2056f2SAlexander Leidinger  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29ad2056f2SAlexander Leidinger  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30ad2056f2SAlexander Leidinger  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31ad2056f2SAlexander Leidinger  * POSSIBILITY OF SUCH DAMAGE.
32ad2056f2SAlexander Leidinger  */
33ad2056f2SAlexander Leidinger 
34ad2056f2SAlexander Leidinger #include <sys/cdefs.h>
35ad2056f2SAlexander Leidinger #if 0
36ad2056f2SAlexander Leidinger __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $");
37ad2056f2SAlexander Leidinger #endif
38ad2056f2SAlexander Leidinger 
39ad2056f2SAlexander Leidinger #include <sys/param.h>
400670e972SDmitry Chagin #include <sys/limits.h>
41d8e53d94SDmitry Chagin #include <sys/lock.h>
422711aba9SDmitry Chagin #include <sys/mutex.h>
43ad2056f2SAlexander Leidinger #include <sys/proc.h>
44d8e53d94SDmitry Chagin #include <sys/resourcevar.h>
45d8e53d94SDmitry Chagin #include <sys/syscallsubr.h>
46d8e53d94SDmitry Chagin #include <sys/time.h>
47ad2056f2SAlexander Leidinger 
48ad2056f2SAlexander Leidinger #ifdef COMPAT_LINUX32
49ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h>
50ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h>
51ad2056f2SAlexander Leidinger #else
52ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h>
53ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h>
54ad2056f2SAlexander Leidinger #endif
55ad2056f2SAlexander Leidinger 
5619e252baSAlexander Leidinger #include <compat/linux/linux_dtrace.h>
577bc05ae6SDmitry Chagin #include <compat/linux/linux_misc.h>
58c8a79231SDmitry Chagin #include <compat/linux/linux_time.h>
594afe4faeSEdward Tomasz Napierala #include <compat/linux/linux_util.h>
6019e252baSAlexander Leidinger 
6119e252baSAlexander Leidinger /* DTrace init */
6219e252baSAlexander Leidinger LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
6319e252baSAlexander Leidinger 
6419e252baSAlexander Leidinger /**
6519e252baSAlexander Leidinger  * DTrace probes in this module.
6619e252baSAlexander Leidinger  */
6719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
6819e252baSAlexander Leidinger     "clockid_t");
6919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
7019e252baSAlexander Leidinger     "clockid_t");
7199b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_gettime, conversion_error, "int");
7219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
7319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
7499b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
7599b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, gettime_error, "int");
7699b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, copyout_error, "int");
7799b6f430SDmitry Chagin #endif
7819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
7919f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, settime_error, "int");
8019f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, conversion_error, "int");
8119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
8219f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
8319f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, conversion_error, "int");
8419f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, copyin_error, "int");
8519f9a0e4SDmitry Chagin #endif
86187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE0(time, linux_common_clock_getres, nullcall);
87187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, conversion_error, "int");
88187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, getres_error, "int");
8919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
90187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
91187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres_time64, copyout_error, "int");
92187715a4SDmitry Chagin #endif
9319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
9419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
9519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
9619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
976501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int");
986501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int");
996501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1006501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int");
1016501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int");
1026501370aSDmitry Chagin #endif
10319e252baSAlexander Leidinger 
10499b6f430SDmitry Chagin static int	linux_common_clock_gettime(struct thread *, clockid_t,
10599b6f430SDmitry Chagin 		    struct timespec *);
10619f9a0e4SDmitry Chagin static int	linux_common_clock_settime(struct thread *, clockid_t,
10719f9a0e4SDmitry Chagin 		    struct timespec *);
108187715a4SDmitry Chagin static int	linux_common_clock_getres(struct thread *, clockid_t,
109187715a4SDmitry Chagin 		    struct timespec *);
1106501370aSDmitry Chagin static int	linux_common_clock_nanosleep(struct thread *, clockid_t,
1116501370aSDmitry Chagin 		    l_int, struct timespec *, struct timespec *);
11299b6f430SDmitry Chagin 
1130670e972SDmitry Chagin int
native_to_linux_timespec(struct l_timespec * ltp,struct timespec * ntp)114ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
115ad2056f2SAlexander Leidinger {
11619e252baSAlexander Leidinger 
1170670e972SDmitry Chagin #ifdef COMPAT_LINUX32
11871b50d08SDmitry Chagin 	if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN)
1190670e972SDmitry Chagin 		return (EOVERFLOW);
1200670e972SDmitry Chagin #endif
121ad2056f2SAlexander Leidinger 	ltp->tv_sec = ntp->tv_sec;
122ad2056f2SAlexander Leidinger 	ltp->tv_nsec = ntp->tv_nsec;
12319e252baSAlexander Leidinger 
1240670e972SDmitry Chagin 	return (0);
125ad2056f2SAlexander Leidinger }
126ad2056f2SAlexander Leidinger 
12768098228SDmitry Chagin int
linux_to_native_timespec(struct timespec * ntp,struct l_timespec * ltp)128ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
129ad2056f2SAlexander Leidinger {
13019e252baSAlexander Leidinger 
13191e7bdcdSDmitry Chagin 	if (!timespecvalid_interval(ltp))
13277424f41SJung-uk Kim 		return (EINVAL);
133ad2056f2SAlexander Leidinger 	ntp->tv_sec = ltp->tv_sec;
134ad2056f2SAlexander Leidinger 	ntp->tv_nsec = ltp->tv_nsec;
13577424f41SJung-uk Kim 
13677424f41SJung-uk Kim 	return (0);
137ad2056f2SAlexander Leidinger }
138ad2056f2SAlexander Leidinger 
1399a9482f8SDmitry Chagin int
linux_put_timespec(struct timespec * ntp,struct l_timespec * ltp)1409a9482f8SDmitry Chagin linux_put_timespec(struct timespec *ntp, struct l_timespec *ltp)
1419a9482f8SDmitry Chagin {
1429a9482f8SDmitry Chagin 	struct l_timespec lts;
1439a9482f8SDmitry Chagin 	int error;
1449a9482f8SDmitry Chagin 
1459a9482f8SDmitry Chagin 	error = native_to_linux_timespec(&lts, ntp);
1469a9482f8SDmitry Chagin 	if (error != 0)
1479a9482f8SDmitry Chagin 		return (error);
1489a9482f8SDmitry Chagin 	return (copyout(&lts, ltp, sizeof(lts)));
1499a9482f8SDmitry Chagin }
1509a9482f8SDmitry Chagin 
151707e567aSDmitry Chagin int
linux_get_timespec(struct timespec * ntp,const struct l_timespec * ultp)152707e567aSDmitry Chagin linux_get_timespec(struct timespec *ntp, const struct l_timespec *ultp)
153707e567aSDmitry Chagin {
154707e567aSDmitry Chagin 	struct l_timespec lts;
155707e567aSDmitry Chagin 	int error;
156707e567aSDmitry Chagin 
157707e567aSDmitry Chagin 	error = copyin(ultp, &lts, sizeof(lts));
158707e567aSDmitry Chagin 	if (error != 0)
159707e567aSDmitry Chagin 		return (error);
160707e567aSDmitry Chagin 	return (linux_to_native_timespec(ntp, &lts));
161707e567aSDmitry Chagin }
162707e567aSDmitry Chagin 
163bfcce1a9SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
164bfcce1a9SDmitry Chagin int
native_to_linux_timespec64(struct l_timespec64 * ltp64,struct timespec * ntp)165bfcce1a9SDmitry Chagin native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
166bfcce1a9SDmitry Chagin {
167bfcce1a9SDmitry Chagin 
168bfcce1a9SDmitry Chagin 	ltp64->tv_sec = ntp->tv_sec;
169bfcce1a9SDmitry Chagin 	ltp64->tv_nsec = ntp->tv_nsec;
170bfcce1a9SDmitry Chagin 
171bfcce1a9SDmitry Chagin 	return (0);
172bfcce1a9SDmitry Chagin }
173bfcce1a9SDmitry Chagin 
174bfcce1a9SDmitry Chagin int
linux_to_native_timespec64(struct timespec * ntp,struct l_timespec64 * ltp64)175bfcce1a9SDmitry Chagin linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64)
176bfcce1a9SDmitry Chagin {
177bfcce1a9SDmitry Chagin 
1783dc2a067SDmitry Chagin #if defined(__i386__)
1793dc2a067SDmitry Chagin 	/* i386 time_t is still 32-bit */
1803dc2a067SDmitry Chagin 	if (ltp64->tv_sec > INT_MAX || ltp64->tv_sec < INT_MIN)
1813dc2a067SDmitry Chagin 		return (EOVERFLOW);
1823dc2a067SDmitry Chagin #endif
1831579b320SDmitry Chagin 	/* Zero out the padding in compat mode. */
1841579b320SDmitry Chagin 	ntp->tv_nsec = ltp64->tv_nsec & 0xFFFFFFFFUL;
185bfcce1a9SDmitry Chagin 	ntp->tv_sec = ltp64->tv_sec;
1861579b320SDmitry Chagin 
1871579b320SDmitry Chagin 	if (!timespecvalid_interval(ntp))
1881579b320SDmitry Chagin 		return (EINVAL);
189bfcce1a9SDmitry Chagin 
190bfcce1a9SDmitry Chagin 	return (0);
191bfcce1a9SDmitry Chagin }
1929a9482f8SDmitry Chagin 
1939a9482f8SDmitry Chagin int
linux_put_timespec64(struct timespec * ntp,struct l_timespec64 * ltp)1949a9482f8SDmitry Chagin linux_put_timespec64(struct timespec *ntp, struct l_timespec64 *ltp)
1959a9482f8SDmitry Chagin {
1969a9482f8SDmitry Chagin 	struct l_timespec64 lts;
1979a9482f8SDmitry Chagin 	int error;
1989a9482f8SDmitry Chagin 
1999a9482f8SDmitry Chagin 	error = native_to_linux_timespec64(&lts, ntp);
2009a9482f8SDmitry Chagin 	if (error != 0)
2019a9482f8SDmitry Chagin 		return (error);
2029a9482f8SDmitry Chagin 	return (copyout(&lts, ltp, sizeof(lts)));
2039a9482f8SDmitry Chagin }
204707e567aSDmitry Chagin 
205707e567aSDmitry Chagin int
linux_get_timespec64(struct timespec * ntp,const struct l_timespec64 * ultp)206707e567aSDmitry Chagin linux_get_timespec64(struct timespec *ntp, const struct l_timespec64 *ultp)
207707e567aSDmitry Chagin {
208707e567aSDmitry Chagin 	struct l_timespec64 lts;
209707e567aSDmitry Chagin 	int error;
210707e567aSDmitry Chagin 
211707e567aSDmitry Chagin 	error = copyin(ultp, &lts, sizeof(lts));
212707e567aSDmitry Chagin 	if (error != 0)
213707e567aSDmitry Chagin 		return (error);
214707e567aSDmitry Chagin 	return (linux_to_native_timespec64(ntp, &lts));
215707e567aSDmitry Chagin }
216bfcce1a9SDmitry Chagin #endif
217bfcce1a9SDmitry Chagin 
21816ac71bcSDmitry Chagin int
native_to_linux_itimerspec(struct l_itimerspec * ltp,struct itimerspec * ntp)219dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
220dd93b628SDmitry Chagin {
221dd93b628SDmitry Chagin 	int error;
222dd93b628SDmitry Chagin 
223dd93b628SDmitry Chagin 	error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
224dd93b628SDmitry Chagin 	if (error == 0)
2250938d04aSDmitry Chagin 		error = native_to_linux_timespec(&ltp->it_value, &ntp->it_value);
226dd93b628SDmitry Chagin 	return (error);
227dd93b628SDmitry Chagin }
228dd93b628SDmitry Chagin 
229dd93b628SDmitry Chagin int
linux_to_native_itimerspec(struct itimerspec * ntp,struct l_itimerspec * ltp)230dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
231dd93b628SDmitry Chagin {
232dd93b628SDmitry Chagin 	int error;
233dd93b628SDmitry Chagin 
234dd93b628SDmitry Chagin 	error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
235dd93b628SDmitry Chagin 	if (error == 0)
236dd93b628SDmitry Chagin 		error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
237dd93b628SDmitry Chagin 	return (error);
238dd93b628SDmitry Chagin }
239dd93b628SDmitry Chagin 
240783c1bd8SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
241783c1bd8SDmitry Chagin int
linux_to_native_itimerspec64(struct itimerspec * ntp,struct l_itimerspec64 * ltp)242783c1bd8SDmitry Chagin linux_to_native_itimerspec64(struct itimerspec *ntp, struct l_itimerspec64 *ltp)
243783c1bd8SDmitry Chagin {
244783c1bd8SDmitry Chagin 	int error;
245783c1bd8SDmitry Chagin 
246783c1bd8SDmitry Chagin 	error = linux_to_native_timespec64(&ntp->it_interval, &ltp->it_interval);
247783c1bd8SDmitry Chagin 	if (error == 0)
248783c1bd8SDmitry Chagin 		error = linux_to_native_timespec64(&ntp->it_value, &ltp->it_value);
249783c1bd8SDmitry Chagin 	return (error);
250783c1bd8SDmitry Chagin }
251783c1bd8SDmitry Chagin 
252783c1bd8SDmitry Chagin int
native_to_linux_itimerspec64(struct l_itimerspec64 * ltp,struct itimerspec * ntp)253783c1bd8SDmitry Chagin native_to_linux_itimerspec64(struct l_itimerspec64 *ltp, struct itimerspec *ntp)
254783c1bd8SDmitry Chagin {
255783c1bd8SDmitry Chagin 	int error;
256783c1bd8SDmitry Chagin 
257783c1bd8SDmitry Chagin 	error = native_to_linux_timespec64(&ltp->it_interval, &ntp->it_interval);
258783c1bd8SDmitry Chagin 	if (error == 0)
259783c1bd8SDmitry Chagin 		error = native_to_linux_timespec64(&ltp->it_value, &ntp->it_value);
260783c1bd8SDmitry Chagin 	return (error);
261783c1bd8SDmitry Chagin }
262783c1bd8SDmitry Chagin #endif
263783c1bd8SDmitry Chagin 
264dd93b628SDmitry Chagin int
linux_to_native_clockid(clockid_t * n,clockid_t l)265ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l)
266ad2056f2SAlexander Leidinger {
26719e252baSAlexander Leidinger 
2682711aba9SDmitry Chagin 	if (l < 0) {
2692711aba9SDmitry Chagin 		/* cpu-clock */
270452f4636SDmitry Chagin 		if (LINUX_CPUCLOCK_WHICH(l) == LINUX_CLOCKFD) {
271452f4636SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_to_native_clockid,
272452f4636SDmitry Chagin 			    unsupported_clockid, l);
273452f4636SDmitry Chagin 			return (ENOTSUP);
274452f4636SDmitry Chagin 		}
275539fadb4SDmitry Chagin 		if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD_MASK)
2762711aba9SDmitry Chagin 			return (EINVAL);
2772711aba9SDmitry Chagin 
2782711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_PERTHREAD(l))
2792711aba9SDmitry Chagin 			*n = CLOCK_THREAD_CPUTIME_ID;
2802711aba9SDmitry Chagin 		else
2812711aba9SDmitry Chagin 			*n = CLOCK_PROCESS_CPUTIME_ID;
2822711aba9SDmitry Chagin 		return (0);
2832711aba9SDmitry Chagin 	}
2842711aba9SDmitry Chagin 
285ad2056f2SAlexander Leidinger 	switch (l) {
286ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_REALTIME:
287ad2056f2SAlexander Leidinger 		*n = CLOCK_REALTIME;
288ad2056f2SAlexander Leidinger 		break;
289ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC:
290ad2056f2SAlexander Leidinger 		*n = CLOCK_MONOTONIC;
291ad2056f2SAlexander Leidinger 		break;
2927bc05ae6SDmitry Chagin 	case LINUX_CLOCK_PROCESS_CPUTIME_ID:
2937bc05ae6SDmitry Chagin 		*n = CLOCK_PROCESS_CPUTIME_ID;
2947bc05ae6SDmitry Chagin 		break;
2957bc05ae6SDmitry Chagin 	case LINUX_CLOCK_THREAD_CPUTIME_ID:
2967bc05ae6SDmitry Chagin 		*n = CLOCK_THREAD_CPUTIME_ID;
2977bc05ae6SDmitry Chagin 		break;
2982711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_COARSE:
2992711aba9SDmitry Chagin 		*n = CLOCK_REALTIME_FAST;
3002711aba9SDmitry Chagin 		break;
3012711aba9SDmitry Chagin 	case LINUX_CLOCK_MONOTONIC_COARSE:
302e37db348SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC_RAW:
3032711aba9SDmitry Chagin 		*n = CLOCK_MONOTONIC_FAST;
3042711aba9SDmitry Chagin 		break;
3052711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME:
30625ada637SDmitry Chagin 		*n = CLOCK_UPTIME;
30725ada637SDmitry Chagin 		break;
3082711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_ALARM:
3092711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME_ALARM:
3102711aba9SDmitry Chagin 	case LINUX_CLOCK_SGI_CYCLE:
3112711aba9SDmitry Chagin 	case LINUX_CLOCK_TAI:
31219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
31319e252baSAlexander Leidinger 		    unsupported_clockid, l);
314452f4636SDmitry Chagin 		return (ENOTSUP);
31577424f41SJung-uk Kim 	default:
31619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
31719e252baSAlexander Leidinger 		    unknown_clockid, l);
318452f4636SDmitry Chagin 		return (ENOTSUP);
319ad2056f2SAlexander Leidinger 	}
320ad2056f2SAlexander Leidinger 
32177424f41SJung-uk Kim 	return (0);
322ad2056f2SAlexander Leidinger }
323ad2056f2SAlexander Leidinger 
324ad2056f2SAlexander Leidinger int
linux_to_native_timerflags(int * nflags,int flags)325f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags)
326f0f58384SDmitry Chagin {
327f0f58384SDmitry Chagin 
328f0f58384SDmitry Chagin 	if (flags & ~LINUX_TIMER_ABSTIME)
329f0f58384SDmitry Chagin 		return (EINVAL);
330f0f58384SDmitry Chagin 	*nflags = 0;
331f0f58384SDmitry Chagin 	if (flags & LINUX_TIMER_ABSTIME)
332f0f58384SDmitry Chagin 		*nflags |= TIMER_ABSTIME;
333f0f58384SDmitry Chagin 	return (0);
334f0f58384SDmitry Chagin }
335f0f58384SDmitry Chagin 
33699b6f430SDmitry Chagin static int
linux_common_clock_gettime(struct thread * td,clockid_t which,struct timespec * tp)33799b6f430SDmitry Chagin linux_common_clock_gettime(struct thread *td, clockid_t which,
33899b6f430SDmitry Chagin     struct timespec *tp)
339ad2056f2SAlexander Leidinger {
3402711aba9SDmitry Chagin 	struct rusage ru;
3412711aba9SDmitry Chagin 	struct thread *targettd;
3422711aba9SDmitry Chagin 	struct proc *p;
3432711aba9SDmitry Chagin 	int error, clockwhich;
3442506c761SDmitry Chagin 	clockid_t nwhich;
3452711aba9SDmitry Chagin 	pid_t pid;
3462711aba9SDmitry Chagin 	lwpid_t tid;
347ad2056f2SAlexander Leidinger 
34899b6f430SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
34919e252baSAlexander Leidinger 	if (error != 0) {
3504afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
35199b6f430SDmitry Chagin 		    "unsupported clock_gettime clockid %d", which);
35299b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_gettime,
35399b6f430SDmitry Chagin 		    conversion_error, error);
35477424f41SJung-uk Kim 		return (error);
35519e252baSAlexander Leidinger 	}
3562711aba9SDmitry Chagin 
3572711aba9SDmitry Chagin 	switch (nwhich) {
3582711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
35999b6f430SDmitry Chagin 		if (which < 0) {
36099b6f430SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_WHICH(which);
36199b6f430SDmitry Chagin 			pid = LINUX_CPUCLOCK_ID(which);
3627bc05ae6SDmitry Chagin 		} else {
3637bc05ae6SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_SCHED;
3647bc05ae6SDmitry Chagin 			pid = 0;
3657bc05ae6SDmitry Chagin 		}
3662711aba9SDmitry Chagin 		if (pid == 0) {
3672711aba9SDmitry Chagin 			p = td->td_proc;
3682711aba9SDmitry Chagin 			PROC_LOCK(p);
3692711aba9SDmitry Chagin 		} else {
3702711aba9SDmitry Chagin 			error = pget(pid, PGET_CANSEE, &p);
3712711aba9SDmitry Chagin 			if (error != 0)
3722711aba9SDmitry Chagin 				return (EINVAL);
3732711aba9SDmitry Chagin 		}
3742711aba9SDmitry Chagin 		switch (clockwhich) {
3752711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
3762711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3772711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
3782711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3792711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3802711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
38199b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3822711aba9SDmitry Chagin 			break;
3832711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
3842711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3852711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
3862711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3872711aba9SDmitry Chagin 			PROC_UNLOCK(p);
38899b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3892711aba9SDmitry Chagin 			break;
3902711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
39199b6f430SDmitry Chagin 			kern_process_cputime(p, tp);
3922711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3932711aba9SDmitry Chagin 			break;
3942711aba9SDmitry Chagin 		default:
3952711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3962711aba9SDmitry Chagin 			return (EINVAL);
3972711aba9SDmitry Chagin 		}
3982711aba9SDmitry Chagin 
3992711aba9SDmitry Chagin 		break;
4002711aba9SDmitry Chagin 
4012711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
40299b6f430SDmitry Chagin 		if (which < 0) {
40399b6f430SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_WHICH(which);
40499b6f430SDmitry Chagin 			tid = LINUX_CPUCLOCK_ID(which);
4057bc05ae6SDmitry Chagin 		} else {
4067bc05ae6SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_SCHED;
4077bc05ae6SDmitry Chagin 			tid = 0;
4087bc05ae6SDmitry Chagin 		}
4097bc05ae6SDmitry Chagin 		p = td->td_proc;
4102711aba9SDmitry Chagin 		if (tid == 0) {
4112711aba9SDmitry Chagin 			targettd = td;
4122711aba9SDmitry Chagin 			PROC_LOCK(p);
4132711aba9SDmitry Chagin 		} else {
4147bc05ae6SDmitry Chagin 			targettd = linux_tdfind(td, tid, p->p_pid);
4152711aba9SDmitry Chagin 			if (targettd == NULL)
4162711aba9SDmitry Chagin 				return (EINVAL);
4172711aba9SDmitry Chagin 		}
4182711aba9SDmitry Chagin 		switch (clockwhich) {
4192711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
4202711aba9SDmitry Chagin 			PROC_STATLOCK(p);
4212711aba9SDmitry Chagin 			thread_lock(targettd);
4222711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
4232711aba9SDmitry Chagin 			thread_unlock(targettd);
4242711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
4252711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4262711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
42799b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
4282711aba9SDmitry Chagin 			break;
4292711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
4302711aba9SDmitry Chagin 			PROC_STATLOCK(p);
4312711aba9SDmitry Chagin 			thread_lock(targettd);
4322711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
4332711aba9SDmitry Chagin 			thread_unlock(targettd);
4342711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
4352711aba9SDmitry Chagin 			PROC_UNLOCK(p);
43699b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
4372711aba9SDmitry Chagin 			break;
4382711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
4397bc05ae6SDmitry Chagin 			if (td == targettd)
4407bc05ae6SDmitry Chagin 				targettd = NULL;
44199b6f430SDmitry Chagin 			kern_thread_cputime(targettd, tp);
4422711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4432711aba9SDmitry Chagin 			break;
4442711aba9SDmitry Chagin 		default:
4452711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4462711aba9SDmitry Chagin 			return (EINVAL);
4472711aba9SDmitry Chagin 		}
4482711aba9SDmitry Chagin 		break;
4492711aba9SDmitry Chagin 
4502711aba9SDmitry Chagin 	default:
45199b6f430SDmitry Chagin 		error = kern_clock_gettime(td, nwhich, tp);
4522711aba9SDmitry Chagin 		break;
4532711aba9SDmitry Chagin 	}
45499b6f430SDmitry Chagin 
45599b6f430SDmitry Chagin 	return (error);
45699b6f430SDmitry Chagin }
45799b6f430SDmitry Chagin 
45899b6f430SDmitry Chagin int
linux_clock_gettime(struct thread * td,struct linux_clock_gettime_args * args)45999b6f430SDmitry Chagin linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
46099b6f430SDmitry Chagin {
46199b6f430SDmitry Chagin 	struct timespec tp;
46299b6f430SDmitry Chagin 	int error;
46399b6f430SDmitry Chagin 
46499b6f430SDmitry Chagin 	error = linux_common_clock_gettime(td, args->which, &tp);
46519e252baSAlexander Leidinger 	if (error != 0) {
46619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
46777424f41SJung-uk Kim 		return (error);
46819e252baSAlexander Leidinger 	}
4699a9482f8SDmitry Chagin 	error = linux_put_timespec(&tp, args->tp);
47019e252baSAlexander Leidinger 	if (error != 0)
47119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
47219e252baSAlexander Leidinger 
47319e252baSAlexander Leidinger 	return (error);
474ad2056f2SAlexander Leidinger }
475ad2056f2SAlexander Leidinger 
47699b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
47799b6f430SDmitry Chagin int
linux_clock_gettime64(struct thread * td,struct linux_clock_gettime64_args * args)47899b6f430SDmitry Chagin linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args)
47999b6f430SDmitry Chagin {
48099b6f430SDmitry Chagin 	struct timespec tp;
48199b6f430SDmitry Chagin 	int error;
48299b6f430SDmitry Chagin 
48399b6f430SDmitry Chagin 	error = linux_common_clock_gettime(td, args->which, &tp);
48499b6f430SDmitry Chagin 	if (error != 0) {
48599b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error);
48699b6f430SDmitry Chagin 		return (error);
48799b6f430SDmitry Chagin 	}
4889a9482f8SDmitry Chagin 	error = linux_put_timespec64(&tp, args->tp);
48999b6f430SDmitry Chagin 	if (error != 0)
49099b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error);
49199b6f430SDmitry Chagin 
49299b6f430SDmitry Chagin 	return (error);
49399b6f430SDmitry Chagin }
49499b6f430SDmitry Chagin #endif
49599b6f430SDmitry Chagin 
49619f9a0e4SDmitry Chagin static int
linux_common_clock_settime(struct thread * td,clockid_t which,struct timespec * ts)49719f9a0e4SDmitry Chagin linux_common_clock_settime(struct thread *td, clockid_t which,
49819f9a0e4SDmitry Chagin     struct timespec *ts)
49919f9a0e4SDmitry Chagin {
50019f9a0e4SDmitry Chagin 	int error;
50119f9a0e4SDmitry Chagin 	clockid_t nwhich;
50219f9a0e4SDmitry Chagin 
50319f9a0e4SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
50419f9a0e4SDmitry Chagin 	if (error != 0) {
50519f9a0e4SDmitry Chagin 		linux_msg(curthread,
50619f9a0e4SDmitry Chagin 		    "unsupported clock_settime clockid %d", which);
50719f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error,
50819f9a0e4SDmitry Chagin 		    error);
50919f9a0e4SDmitry Chagin 		return (error);
51019f9a0e4SDmitry Chagin 	}
51119f9a0e4SDmitry Chagin 
51219f9a0e4SDmitry Chagin 	error = kern_clock_settime(td, nwhich, ts);
51319f9a0e4SDmitry Chagin 	if (error != 0)
51419f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_settime,
51519f9a0e4SDmitry Chagin 		    settime_error, error);
51619f9a0e4SDmitry Chagin 
51719f9a0e4SDmitry Chagin 	return (error);
51819f9a0e4SDmitry Chagin }
51919f9a0e4SDmitry Chagin 
520ad2056f2SAlexander Leidinger int
linux_clock_settime(struct thread * td,struct linux_clock_settime_args * args)521ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
522ad2056f2SAlexander Leidinger {
523ad2056f2SAlexander Leidinger 	struct timespec ts;
524ad2056f2SAlexander Leidinger 	int error;
525ad2056f2SAlexander Leidinger 
526707e567aSDmitry Chagin 	error = linux_get_timespec(&ts, args->tp);
52719e252baSAlexander Leidinger 	if (error != 0) {
52819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
52919e252baSAlexander Leidinger 		return (error);
53019e252baSAlexander Leidinger 	}
53119f9a0e4SDmitry Chagin 	return (linux_common_clock_settime(td, args->which, &ts));
53219e252baSAlexander Leidinger }
53319e252baSAlexander Leidinger 
53419f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
53519f9a0e4SDmitry Chagin int
linux_clock_settime64(struct thread * td,struct linux_clock_settime64_args * args)53619f9a0e4SDmitry Chagin linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args)
53719f9a0e4SDmitry Chagin {
53819f9a0e4SDmitry Chagin 	struct timespec ts;
53919f9a0e4SDmitry Chagin 	int error;
54019f9a0e4SDmitry Chagin 
541707e567aSDmitry Chagin 	error = linux_get_timespec64(&ts, args->tp);
54219f9a0e4SDmitry Chagin 	if (error != 0) {
54319f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error);
54419f9a0e4SDmitry Chagin 		return (error);
54519f9a0e4SDmitry Chagin 	}
54619f9a0e4SDmitry Chagin 	return (linux_common_clock_settime(td, args->which, &ts));
547ad2056f2SAlexander Leidinger }
54819f9a0e4SDmitry Chagin #endif
549ad2056f2SAlexander Leidinger 
550187715a4SDmitry Chagin static int
linux_common_clock_getres(struct thread * td,clockid_t which,struct timespec * ts)551187715a4SDmitry Chagin linux_common_clock_getres(struct thread *td, clockid_t which,
552187715a4SDmitry Chagin     struct timespec *ts)
553ad2056f2SAlexander Leidinger {
5542711aba9SDmitry Chagin 	struct proc *p;
5552711aba9SDmitry Chagin 	int error, clockwhich;
5562506c761SDmitry Chagin 	clockid_t nwhich;
5572711aba9SDmitry Chagin 	pid_t pid;
5582711aba9SDmitry Chagin 	lwpid_t tid;
559ad2056f2SAlexander Leidinger 
560187715a4SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
56119e252baSAlexander Leidinger 	if (error != 0) {
5624afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
563187715a4SDmitry Chagin 		    "unsupported clock_getres clockid %d", which);
564187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_getres,
565187715a4SDmitry Chagin 		    conversion_error, error);
56677424f41SJung-uk Kim 		return (error);
56719e252baSAlexander Leidinger 	}
5682711aba9SDmitry Chagin 
5692711aba9SDmitry Chagin 	/*
5702711aba9SDmitry Chagin 	 * Check user supplied clock id in case of per-process
5712711aba9SDmitry Chagin 	 * or thread-specific cpu-time clock.
5722711aba9SDmitry Chagin 	 */
573187715a4SDmitry Chagin 	if (which < 0) {
5742711aba9SDmitry Chagin 		switch (nwhich) {
5752711aba9SDmitry Chagin 		case CLOCK_THREAD_CPUTIME_ID:
576187715a4SDmitry Chagin 			tid = LINUX_CPUCLOCK_ID(which);
5772711aba9SDmitry Chagin 			if (tid != 0) {
5782711aba9SDmitry Chagin 				p = td->td_proc;
5797bc05ae6SDmitry Chagin 				if (linux_tdfind(td, tid, p->p_pid) == NULL)
5807bc05ae6SDmitry Chagin 					return (EINVAL);
5812711aba9SDmitry Chagin 				PROC_UNLOCK(p);
5822711aba9SDmitry Chagin 			}
5832711aba9SDmitry Chagin 			break;
5842711aba9SDmitry Chagin 		case CLOCK_PROCESS_CPUTIME_ID:
585187715a4SDmitry Chagin 			pid = LINUX_CPUCLOCK_ID(which);
5862711aba9SDmitry Chagin 			if (pid != 0) {
5872711aba9SDmitry Chagin 				error = pget(pid, PGET_CANSEE, &p);
5882711aba9SDmitry Chagin 				if (error != 0)
5892711aba9SDmitry Chagin 					return (EINVAL);
5902711aba9SDmitry Chagin 				PROC_UNLOCK(p);
5912711aba9SDmitry Chagin 			}
5922711aba9SDmitry Chagin 			break;
5932711aba9SDmitry Chagin 		}
5947bc05ae6SDmitry Chagin 	}
5952711aba9SDmitry Chagin 
596187715a4SDmitry Chagin 	if (ts == NULL) {
597187715a4SDmitry Chagin 		LIN_SDT_PROBE0(time, linux_common_clock_getres, nullcall);
5982711aba9SDmitry Chagin 		return (0);
5992711aba9SDmitry Chagin 	}
6002711aba9SDmitry Chagin 
6012711aba9SDmitry Chagin 	switch (nwhich) {
6022711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
6032711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
604187715a4SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(which);
6057bc05ae6SDmitry Chagin 		/*
6067bc05ae6SDmitry Chagin 		 * In both cases (when the clock id obtained by a call to
6077bc05ae6SDmitry Chagin 		 * clock_getcpuclockid() or using the clock
6087bc05ae6SDmitry Chagin 		 * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision
6097bc05ae6SDmitry Chagin 		 * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock.
6107bc05ae6SDmitry Chagin 		 *
6117bc05ae6SDmitry Chagin 		 * See Linux posix_cpu_clock_getres() implementation.
6127bc05ae6SDmitry Chagin 		 */
613187715a4SDmitry Chagin 		if (which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) {
614187715a4SDmitry Chagin 			ts->tv_sec = 0;
615187715a4SDmitry Chagin 			ts->tv_nsec = 1;
6167bc05ae6SDmitry Chagin 			goto out;
6177bc05ae6SDmitry Chagin 		}
6187bc05ae6SDmitry Chagin 
6192711aba9SDmitry Chagin 		switch (clockwhich) {
6202711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
6212711aba9SDmitry Chagin 			nwhich = CLOCK_PROF;
6222711aba9SDmitry Chagin 			break;
6232711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
6242711aba9SDmitry Chagin 			nwhich = CLOCK_VIRTUAL;
6252711aba9SDmitry Chagin 			break;
6262711aba9SDmitry Chagin 		default:
6272711aba9SDmitry Chagin 			return (EINVAL);
6282711aba9SDmitry Chagin 		}
6292711aba9SDmitry Chagin 		break;
6302711aba9SDmitry Chagin 
6312711aba9SDmitry Chagin 	default:
6322711aba9SDmitry Chagin 		break;
6332711aba9SDmitry Chagin 	}
634187715a4SDmitry Chagin 	error = kern_clock_getres(td, nwhich, ts);
63519e252baSAlexander Leidinger 	if (error != 0) {
636187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_getres,
637187715a4SDmitry Chagin 		    getres_error, error);
63877424f41SJung-uk Kim 		return (error);
63919e252baSAlexander Leidinger 	}
6407bc05ae6SDmitry Chagin 
6417bc05ae6SDmitry Chagin out:
642187715a4SDmitry Chagin 	return (error);
643187715a4SDmitry Chagin }
644187715a4SDmitry Chagin 
645187715a4SDmitry Chagin int
linux_clock_getres(struct thread * td,struct linux_clock_getres_args * args)646187715a4SDmitry Chagin linux_clock_getres(struct thread *td,
647187715a4SDmitry Chagin     struct linux_clock_getres_args *args)
648187715a4SDmitry Chagin {
649187715a4SDmitry Chagin 	struct timespec ts;
650187715a4SDmitry Chagin 	int error;
651187715a4SDmitry Chagin 
652187715a4SDmitry Chagin 	error = linux_common_clock_getres(td, args->which, &ts);
653187715a4SDmitry Chagin 	if (error != 0 || args->tp == NULL)
654187715a4SDmitry Chagin 		return (error);
6559a9482f8SDmitry Chagin 	error = linux_put_timespec(&ts, args->tp);
65619e252baSAlexander Leidinger 	if (error != 0)
657187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_getres,
658187715a4SDmitry Chagin 		    copyout_error, error);
65919e252baSAlexander Leidinger 	return (error);
66077424f41SJung-uk Kim }
66177424f41SJung-uk Kim 
662187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
663187715a4SDmitry Chagin int
linux_clock_getres_time64(struct thread * td,struct linux_clock_getres_time64_args * args)664187715a4SDmitry Chagin linux_clock_getres_time64(struct thread *td,
665187715a4SDmitry Chagin     struct linux_clock_getres_time64_args *args)
666187715a4SDmitry Chagin {
667187715a4SDmitry Chagin 	struct timespec ts;
668187715a4SDmitry Chagin 	int error;
669187715a4SDmitry Chagin 
670187715a4SDmitry Chagin 	error = linux_common_clock_getres(td, args->which, &ts);
671187715a4SDmitry Chagin 	if (error != 0 || args->tp == NULL)
672187715a4SDmitry Chagin 		return (error);
6739a9482f8SDmitry Chagin 	error = linux_put_timespec64(&ts, args->tp);
674187715a4SDmitry Chagin 	if (error != 0)
675187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_getres_time64,
676187715a4SDmitry Chagin 		    copyout_error, error);
677187715a4SDmitry Chagin 	return (error);
678187715a4SDmitry Chagin }
679187715a4SDmitry Chagin #endif
680187715a4SDmitry Chagin 
68177424f41SJung-uk Kim int
linux_nanosleep(struct thread * td,struct linux_nanosleep_args * args)68277424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
68377424f41SJung-uk Kim {
68477424f41SJung-uk Kim 	struct timespec *rmtp;
68577424f41SJung-uk Kim 	struct timespec rqts, rmts;
6865c2748d5SDmitry Chagin 	int error, error2;
68777424f41SJung-uk Kim 
688707e567aSDmitry Chagin 	error = linux_get_timespec(&rqts, args->rqtp);
68919e252baSAlexander Leidinger 	if (error != 0) {
69019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
69177424f41SJung-uk Kim 		return (error);
69219e252baSAlexander Leidinger 	}
69377424f41SJung-uk Kim 	if (args->rmtp != NULL)
69477424f41SJung-uk Kim 		rmtp = &rmts;
69577424f41SJung-uk Kim 	else
69677424f41SJung-uk Kim 		rmtp = NULL;
69777424f41SJung-uk Kim 
69877424f41SJung-uk Kim 	error = kern_nanosleep(td, &rqts, rmtp);
6994cf66812SEric van Gyzen 	if (error == EINTR && args->rmtp != NULL) {
7009a9482f8SDmitry Chagin 		error2 = linux_put_timespec(rmtp, args->rmtp);
7015c2748d5SDmitry Chagin 		if (error2 != 0) {
70219e252baSAlexander Leidinger 			LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
7035c2748d5SDmitry Chagin 			    error2);
7045c2748d5SDmitry Chagin 			return (error2);
70577424f41SJung-uk Kim 		}
70619e252baSAlexander Leidinger 	}
70777424f41SJung-uk Kim 
7085c2748d5SDmitry Chagin 	return (error);
709ad2056f2SAlexander Leidinger }
710ad2056f2SAlexander Leidinger 
7116501370aSDmitry Chagin static int
linux_common_clock_nanosleep(struct thread * td,clockid_t which,l_int lflags,struct timespec * rqtp,struct timespec * rmtp)7126501370aSDmitry Chagin linux_common_clock_nanosleep(struct thread *td, clockid_t which,
7136501370aSDmitry Chagin     l_int lflags, struct timespec *rqtp, struct timespec *rmtp)
7146501370aSDmitry Chagin {
7156501370aSDmitry Chagin 	int error, flags;
7166501370aSDmitry Chagin 	clockid_t clockid;
7176501370aSDmitry Chagin 
7186501370aSDmitry Chagin 	error = linux_to_native_timerflags(&flags, lflags);
7196501370aSDmitry Chagin 	if (error != 0) {
7206501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_nanosleep,
7216501370aSDmitry Chagin 		    unsupported_flags, lflags);
7226501370aSDmitry Chagin 		return (error);
7236501370aSDmitry Chagin 	}
7246501370aSDmitry Chagin 
7256501370aSDmitry Chagin 	error = linux_to_native_clockid(&clockid, which);
7266501370aSDmitry Chagin 	if (error != 0) {
7276501370aSDmitry Chagin 		linux_msg(curthread,
7286501370aSDmitry Chagin 		    "unsupported clock_nanosleep clockid %d", which);
7296501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_nanosleep,
7306501370aSDmitry Chagin 		    unsupported_clockid, which);
7316501370aSDmitry Chagin 		return (error);
7326501370aSDmitry Chagin 	}
73366e73ce7SDmitry Chagin 	if (clockid == CLOCK_THREAD_CPUTIME_ID)
73466e73ce7SDmitry Chagin 		return (ENOTSUP);
7356501370aSDmitry Chagin 
7366501370aSDmitry Chagin 	return (kern_clock_nanosleep(td, clockid, flags, rqtp, rmtp));
7376501370aSDmitry Chagin }
7386501370aSDmitry Chagin 
739ad2056f2SAlexander Leidinger int
linux_clock_nanosleep(struct thread * td,struct linux_clock_nanosleep_args * args)7406501370aSDmitry Chagin linux_clock_nanosleep(struct thread *td,
7416501370aSDmitry Chagin     struct linux_clock_nanosleep_args *args)
742ad2056f2SAlexander Leidinger {
743ad2056f2SAlexander Leidinger 	struct timespec *rmtp;
744ad2056f2SAlexander Leidinger 	struct timespec rqts, rmts;
7456501370aSDmitry Chagin 	int error, error2;
746ad2056f2SAlexander Leidinger 
747707e567aSDmitry Chagin 	error = linux_get_timespec(&rqts, args->rqtp);
74819e252baSAlexander Leidinger 	if (error != 0) {
74919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
75019e252baSAlexander Leidinger 		    error);
75177424f41SJung-uk Kim 		return (error);
75219e252baSAlexander Leidinger 	}
753ad2056f2SAlexander Leidinger 	if (args->rmtp != NULL)
754ad2056f2SAlexander Leidinger 		rmtp = &rmts;
755ad2056f2SAlexander Leidinger 	else
756ad2056f2SAlexander Leidinger 		rmtp = NULL;
757ad2056f2SAlexander Leidinger 
7586501370aSDmitry Chagin 	error = linux_common_clock_nanosleep(td, args->which, args->flags,
7596501370aSDmitry Chagin 	    &rqts, rmtp);
7606501370aSDmitry Chagin 	if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
761f0f58384SDmitry Chagin 	    args->rmtp != NULL) {
7629a9482f8SDmitry Chagin 		error2 = linux_put_timespec(rmtp, args->rmtp);
7635c2748d5SDmitry Chagin 		if (error2 != 0) {
7645c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
7655c2748d5SDmitry Chagin 			    copyout_error, error2);
7665c2748d5SDmitry Chagin 			return (error2);
7675c2748d5SDmitry Chagin 		}
7685c2748d5SDmitry Chagin 	}
76977424f41SJung-uk Kim 	return (error);
77019e252baSAlexander Leidinger }
7716501370aSDmitry Chagin 
7726501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
7736501370aSDmitry Chagin int
linux_clock_nanosleep_time64(struct thread * td,struct linux_clock_nanosleep_time64_args * args)7746501370aSDmitry Chagin linux_clock_nanosleep_time64(struct thread *td,
7756501370aSDmitry Chagin     struct linux_clock_nanosleep_time64_args *args)
7766501370aSDmitry Chagin {
7776501370aSDmitry Chagin 	struct timespec *rmtp;
7786501370aSDmitry Chagin 	struct timespec rqts, rmts;
7796501370aSDmitry Chagin 	int error, error2;
7806501370aSDmitry Chagin 
781707e567aSDmitry Chagin 	error = linux_get_timespec64(&rqts, args->rqtp);
7826501370aSDmitry Chagin 	if (error != 0) {
7836501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
7846501370aSDmitry Chagin 		    copyin_error, error);
7856501370aSDmitry Chagin 		return (error);
7866501370aSDmitry Chagin 	}
7876501370aSDmitry Chagin 	if (args->rmtp != NULL)
7886501370aSDmitry Chagin 		rmtp = &rmts;
7896501370aSDmitry Chagin 	else
7906501370aSDmitry Chagin 		rmtp = NULL;
7916501370aSDmitry Chagin 
7926501370aSDmitry Chagin 	error = linux_common_clock_nanosleep(td, args->which, args->flags,
7936501370aSDmitry Chagin 	    &rqts, rmtp);
7946501370aSDmitry Chagin 	if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
7956501370aSDmitry Chagin 	    args->rmtp != NULL) {
7969a9482f8SDmitry Chagin 		error2 = linux_put_timespec64(rmtp, args->rmtp);
7976501370aSDmitry Chagin 		if (error2 != 0) {
7986501370aSDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
7996501370aSDmitry Chagin 			    copyout_error, error2);
8006501370aSDmitry Chagin 			return (error2);
8016501370aSDmitry Chagin 		}
8026501370aSDmitry Chagin 	}
8036501370aSDmitry Chagin 	return (error);
8046501370aSDmitry Chagin }
8056501370aSDmitry Chagin #endif
806