xref: /freebsd/sys/compat/linux/linux_time.c (revision 1579b320f1a4d555250b82fa74a391d963e7ae13)
1ad2056f2SAlexander Leidinger /*	$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */
2ad2056f2SAlexander Leidinger 
3ad2056f2SAlexander Leidinger /*-
47f2d13d6SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
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 __FBSDID("$FreeBSD$");
36ad2056f2SAlexander Leidinger #if 0
37ad2056f2SAlexander Leidinger __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $");
38ad2056f2SAlexander Leidinger #endif
39ad2056f2SAlexander Leidinger 
40ad2056f2SAlexander Leidinger #include "opt_compat.h"
41ad2056f2SAlexander Leidinger 
42ad2056f2SAlexander Leidinger #include <sys/param.h>
4319e252baSAlexander Leidinger #include <sys/kernel.h>
442711aba9SDmitry Chagin #include <sys/lock.h>
45ad2056f2SAlexander Leidinger #include <sys/ucred.h>
460670e972SDmitry Chagin #include <sys/limits.h>
47ad2056f2SAlexander Leidinger #include <sys/mount.h>
482711aba9SDmitry Chagin #include <sys/mutex.h>
492711aba9SDmitry Chagin #include <sys/resourcevar.h>
5019e252baSAlexander Leidinger #include <sys/sdt.h>
51ad2056f2SAlexander Leidinger #include <sys/signal.h>
52ad2056f2SAlexander Leidinger #include <sys/stdint.h>
53ad2056f2SAlexander Leidinger #include <sys/syscallsubr.h>
54ad2056f2SAlexander Leidinger #include <sys/sysproto.h>
55ad2056f2SAlexander Leidinger #include <sys/time.h>
56ad2056f2SAlexander Leidinger #include <sys/systm.h>
57ad2056f2SAlexander Leidinger #include <sys/proc.h>
58ad2056f2SAlexander Leidinger 
59ad2056f2SAlexander Leidinger #ifdef COMPAT_LINUX32
60ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h>
61ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h>
62ad2056f2SAlexander Leidinger #else
63ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h>
64ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h>
65ad2056f2SAlexander Leidinger #endif
66ad2056f2SAlexander Leidinger 
6719e252baSAlexander Leidinger #include <compat/linux/linux_dtrace.h>
687bc05ae6SDmitry Chagin #include <compat/linux/linux_misc.h>
692711aba9SDmitry Chagin #include <compat/linux/linux_timer.h>
704afe4faeSEdward Tomasz Napierala #include <compat/linux/linux_util.h>
7119e252baSAlexander Leidinger 
7219e252baSAlexander Leidinger /* DTrace init */
7319e252baSAlexander Leidinger LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
7419e252baSAlexander Leidinger 
7519e252baSAlexander Leidinger /**
7619e252baSAlexander Leidinger  * DTrace probes in this module.
7719e252baSAlexander Leidinger  */
7819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
7919e252baSAlexander Leidinger     "clockid_t");
8019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
8119e252baSAlexander Leidinger     "clockid_t");
8299b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_gettime, conversion_error, "int");
8319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
8419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
8599b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
8699b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, gettime_error, "int");
8799b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, copyout_error, "int");
8899b6f430SDmitry Chagin #endif
8919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
9019f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, settime_error, "int");
9119f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, conversion_error, "int");
9219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
9319f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
9419f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, conversion_error, "int");
9519f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, copyin_error, "int");
9619f9a0e4SDmitry Chagin #endif
97187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE0(time, linux_common_clock_getres, nullcall);
98187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, conversion_error, "int");
99187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, getres_error, "int");
10019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
101187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
102187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres_time64, copyout_error, "int");
103187715a4SDmitry Chagin #endif
10419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
10519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
10619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
10719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
10819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
10919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
1106501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int");
1116501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int");
1126501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
1136501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, conversion_error, "int");
1146501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int");
1156501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int");
1166501370aSDmitry Chagin #endif
11719e252baSAlexander Leidinger 
11899b6f430SDmitry Chagin static int	linux_common_clock_gettime(struct thread *, clockid_t,
11999b6f430SDmitry Chagin 		    struct timespec *);
12019f9a0e4SDmitry Chagin static int	linux_common_clock_settime(struct thread *, clockid_t,
12119f9a0e4SDmitry Chagin 		    struct timespec *);
122187715a4SDmitry Chagin static int	linux_common_clock_getres(struct thread *, clockid_t,
123187715a4SDmitry Chagin 		    struct timespec *);
1246501370aSDmitry Chagin static int	linux_common_clock_nanosleep(struct thread *, clockid_t,
1256501370aSDmitry Chagin 		    l_int, struct timespec *, struct timespec *);
12699b6f430SDmitry Chagin 
1270670e972SDmitry Chagin int
128ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
129ad2056f2SAlexander Leidinger {
13019e252baSAlexander Leidinger 
1310670e972SDmitry Chagin #ifdef COMPAT_LINUX32
13271b50d08SDmitry Chagin 	if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN)
1330670e972SDmitry Chagin 		return (EOVERFLOW);
1340670e972SDmitry Chagin #endif
135ad2056f2SAlexander Leidinger 	ltp->tv_sec = ntp->tv_sec;
136ad2056f2SAlexander Leidinger 	ltp->tv_nsec = ntp->tv_nsec;
13719e252baSAlexander Leidinger 
1380670e972SDmitry Chagin 	return (0);
139ad2056f2SAlexander Leidinger }
140ad2056f2SAlexander Leidinger 
14168098228SDmitry Chagin int
142ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
143ad2056f2SAlexander Leidinger {
14419e252baSAlexander Leidinger 
14591e7bdcdSDmitry Chagin 	if (!timespecvalid_interval(ltp))
14677424f41SJung-uk Kim 		return (EINVAL);
147ad2056f2SAlexander Leidinger 	ntp->tv_sec = ltp->tv_sec;
148ad2056f2SAlexander Leidinger 	ntp->tv_nsec = ltp->tv_nsec;
14977424f41SJung-uk Kim 
15077424f41SJung-uk Kim 	return (0);
151ad2056f2SAlexander Leidinger }
152ad2056f2SAlexander Leidinger 
1539a9482f8SDmitry Chagin int
1549a9482f8SDmitry Chagin linux_put_timespec(struct timespec *ntp, struct l_timespec *ltp)
1559a9482f8SDmitry Chagin {
1569a9482f8SDmitry Chagin 	struct l_timespec lts;
1579a9482f8SDmitry Chagin 	int error;
1589a9482f8SDmitry Chagin 
1599a9482f8SDmitry Chagin 	error = native_to_linux_timespec(&lts, ntp);
1609a9482f8SDmitry Chagin 	if (error != 0)
1619a9482f8SDmitry Chagin 		return (error);
1629a9482f8SDmitry Chagin 	return (copyout(&lts, ltp, sizeof(lts)));
1639a9482f8SDmitry Chagin }
1649a9482f8SDmitry Chagin 
165bfcce1a9SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
166bfcce1a9SDmitry Chagin int
167bfcce1a9SDmitry Chagin native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
168bfcce1a9SDmitry Chagin {
169bfcce1a9SDmitry Chagin 
170bfcce1a9SDmitry Chagin 	ltp64->tv_sec = ntp->tv_sec;
171bfcce1a9SDmitry Chagin 	ltp64->tv_nsec = ntp->tv_nsec;
172bfcce1a9SDmitry Chagin 
173bfcce1a9SDmitry Chagin 	return (0);
174bfcce1a9SDmitry Chagin }
175bfcce1a9SDmitry Chagin 
176bfcce1a9SDmitry Chagin int
177bfcce1a9SDmitry Chagin linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64)
178bfcce1a9SDmitry Chagin {
179bfcce1a9SDmitry Chagin 
180*1579b320SDmitry Chagin 	/* Zero out the padding in compat mode. */
181*1579b320SDmitry Chagin 	ntp->tv_nsec = ltp64->tv_nsec & 0xFFFFFFFFUL;
182bfcce1a9SDmitry Chagin 	ntp->tv_sec = ltp64->tv_sec;
183*1579b320SDmitry Chagin 
184*1579b320SDmitry Chagin 	if (!timespecvalid_interval(ntp))
185*1579b320SDmitry Chagin 		return (EINVAL);
186bfcce1a9SDmitry Chagin 
187bfcce1a9SDmitry Chagin 	return (0);
188bfcce1a9SDmitry Chagin }
1899a9482f8SDmitry Chagin 
1909a9482f8SDmitry Chagin int
1919a9482f8SDmitry Chagin linux_put_timespec64(struct timespec *ntp, struct l_timespec64 *ltp)
1929a9482f8SDmitry Chagin {
1939a9482f8SDmitry Chagin 	struct l_timespec64 lts;
1949a9482f8SDmitry Chagin 	int error;
1959a9482f8SDmitry Chagin 
1969a9482f8SDmitry Chagin 	error = native_to_linux_timespec64(&lts, ntp);
1979a9482f8SDmitry Chagin 	if (error != 0)
1989a9482f8SDmitry Chagin 		return (error);
1999a9482f8SDmitry Chagin 	return (copyout(&lts, ltp, sizeof(lts)));
2009a9482f8SDmitry Chagin }
201bfcce1a9SDmitry Chagin #endif
202bfcce1a9SDmitry Chagin 
20316ac71bcSDmitry Chagin int
204dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
205dd93b628SDmitry Chagin {
206dd93b628SDmitry Chagin 	int error;
207dd93b628SDmitry Chagin 
208dd93b628SDmitry Chagin 	error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
209dd93b628SDmitry Chagin 	if (error == 0)
2100938d04aSDmitry Chagin 		error = native_to_linux_timespec(&ltp->it_value, &ntp->it_value);
211dd93b628SDmitry Chagin 	return (error);
212dd93b628SDmitry Chagin }
213dd93b628SDmitry Chagin 
214dd93b628SDmitry Chagin int
215dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
216dd93b628SDmitry Chagin {
217dd93b628SDmitry Chagin 	int error;
218dd93b628SDmitry Chagin 
219dd93b628SDmitry Chagin 	error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
220dd93b628SDmitry Chagin 	if (error == 0)
221dd93b628SDmitry Chagin 		error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
222dd93b628SDmitry Chagin 	return (error);
223dd93b628SDmitry Chagin }
224dd93b628SDmitry Chagin 
225783c1bd8SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
226783c1bd8SDmitry Chagin int
227783c1bd8SDmitry Chagin linux_to_native_itimerspec64(struct itimerspec *ntp, struct l_itimerspec64 *ltp)
228783c1bd8SDmitry Chagin {
229783c1bd8SDmitry Chagin 	int error;
230783c1bd8SDmitry Chagin 
231783c1bd8SDmitry Chagin 	error = linux_to_native_timespec64(&ntp->it_interval, &ltp->it_interval);
232783c1bd8SDmitry Chagin 	if (error == 0)
233783c1bd8SDmitry Chagin 		error = linux_to_native_timespec64(&ntp->it_value, &ltp->it_value);
234783c1bd8SDmitry Chagin 	return (error);
235783c1bd8SDmitry Chagin }
236783c1bd8SDmitry Chagin 
237783c1bd8SDmitry Chagin int
238783c1bd8SDmitry Chagin native_to_linux_itimerspec64(struct l_itimerspec64 *ltp, struct itimerspec *ntp)
239783c1bd8SDmitry Chagin {
240783c1bd8SDmitry Chagin 	int error;
241783c1bd8SDmitry Chagin 
242783c1bd8SDmitry Chagin 	error = native_to_linux_timespec64(&ltp->it_interval, &ntp->it_interval);
243783c1bd8SDmitry Chagin 	if (error == 0)
244783c1bd8SDmitry Chagin 		error = native_to_linux_timespec64(&ltp->it_value, &ntp->it_value);
245783c1bd8SDmitry Chagin 	return (error);
246783c1bd8SDmitry Chagin }
247783c1bd8SDmitry Chagin #endif
248783c1bd8SDmitry Chagin 
249dd93b628SDmitry Chagin int
250ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l)
251ad2056f2SAlexander Leidinger {
25219e252baSAlexander Leidinger 
2532711aba9SDmitry Chagin 	if (l < 0) {
2542711aba9SDmitry Chagin 		/* cpu-clock */
2552711aba9SDmitry Chagin 		if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
2562711aba9SDmitry Chagin 			return (EINVAL);
2572711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
2582711aba9SDmitry Chagin 			return (EINVAL);
2592711aba9SDmitry Chagin 
2602711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_PERTHREAD(l))
2612711aba9SDmitry Chagin 			*n = CLOCK_THREAD_CPUTIME_ID;
2622711aba9SDmitry Chagin 		else
2632711aba9SDmitry Chagin 			*n = CLOCK_PROCESS_CPUTIME_ID;
2642711aba9SDmitry Chagin 		return (0);
2652711aba9SDmitry Chagin 	}
2662711aba9SDmitry Chagin 
267ad2056f2SAlexander Leidinger 	switch (l) {
268ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_REALTIME:
269ad2056f2SAlexander Leidinger 		*n = CLOCK_REALTIME;
270ad2056f2SAlexander Leidinger 		break;
271ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC:
272ad2056f2SAlexander Leidinger 		*n = CLOCK_MONOTONIC;
273ad2056f2SAlexander Leidinger 		break;
2747bc05ae6SDmitry Chagin 	case LINUX_CLOCK_PROCESS_CPUTIME_ID:
2757bc05ae6SDmitry Chagin 		*n = CLOCK_PROCESS_CPUTIME_ID;
2767bc05ae6SDmitry Chagin 		break;
2777bc05ae6SDmitry Chagin 	case LINUX_CLOCK_THREAD_CPUTIME_ID:
2787bc05ae6SDmitry Chagin 		*n = CLOCK_THREAD_CPUTIME_ID;
2797bc05ae6SDmitry Chagin 		break;
2802711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_COARSE:
2812711aba9SDmitry Chagin 		*n = CLOCK_REALTIME_FAST;
2822711aba9SDmitry Chagin 		break;
2832711aba9SDmitry Chagin 	case LINUX_CLOCK_MONOTONIC_COARSE:
284e37db348SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC_RAW:
2852711aba9SDmitry Chagin 		*n = CLOCK_MONOTONIC_FAST;
2862711aba9SDmitry Chagin 		break;
2872711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME:
28825ada637SDmitry Chagin 		*n = CLOCK_UPTIME;
28925ada637SDmitry Chagin 		break;
2902711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_ALARM:
2912711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME_ALARM:
2922711aba9SDmitry Chagin 	case LINUX_CLOCK_SGI_CYCLE:
2932711aba9SDmitry Chagin 	case LINUX_CLOCK_TAI:
29419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
29519e252baSAlexander Leidinger 		    unsupported_clockid, l);
29619e252baSAlexander Leidinger 		return (EINVAL);
29777424f41SJung-uk Kim 	default:
29819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
29919e252baSAlexander Leidinger 		    unknown_clockid, l);
30077424f41SJung-uk Kim 		return (EINVAL);
301ad2056f2SAlexander Leidinger 	}
302ad2056f2SAlexander Leidinger 
30377424f41SJung-uk Kim 	return (0);
304ad2056f2SAlexander Leidinger }
305ad2056f2SAlexander Leidinger 
306ad2056f2SAlexander Leidinger int
307f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags)
308f0f58384SDmitry Chagin {
309f0f58384SDmitry Chagin 
310f0f58384SDmitry Chagin 	if (flags & ~LINUX_TIMER_ABSTIME)
311f0f58384SDmitry Chagin 		return (EINVAL);
312f0f58384SDmitry Chagin 	*nflags = 0;
313f0f58384SDmitry Chagin 	if (flags & LINUX_TIMER_ABSTIME)
314f0f58384SDmitry Chagin 		*nflags |= TIMER_ABSTIME;
315f0f58384SDmitry Chagin 	return (0);
316f0f58384SDmitry Chagin }
317f0f58384SDmitry Chagin 
31899b6f430SDmitry Chagin static int
31999b6f430SDmitry Chagin linux_common_clock_gettime(struct thread *td, clockid_t which,
32099b6f430SDmitry Chagin     struct timespec *tp)
321ad2056f2SAlexander Leidinger {
3222711aba9SDmitry Chagin 	struct rusage ru;
3232711aba9SDmitry Chagin 	struct thread *targettd;
3242711aba9SDmitry Chagin 	struct proc *p;
3252711aba9SDmitry Chagin 	int error, clockwhich;
3262506c761SDmitry Chagin 	clockid_t nwhich;
3272711aba9SDmitry Chagin 	pid_t pid;
3282711aba9SDmitry Chagin 	lwpid_t tid;
329ad2056f2SAlexander Leidinger 
33099b6f430SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
33119e252baSAlexander Leidinger 	if (error != 0) {
3324afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
33399b6f430SDmitry Chagin 		    "unsupported clock_gettime clockid %d", which);
33499b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_gettime,
33599b6f430SDmitry Chagin 		    conversion_error, error);
33677424f41SJung-uk Kim 		return (error);
33719e252baSAlexander Leidinger 	}
3382711aba9SDmitry Chagin 
3392711aba9SDmitry Chagin 	switch (nwhich) {
3402711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
34199b6f430SDmitry Chagin 		if (which < 0) {
34299b6f430SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_WHICH(which);
34399b6f430SDmitry Chagin 			pid = LINUX_CPUCLOCK_ID(which);
3447bc05ae6SDmitry Chagin 		} else {
3457bc05ae6SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_SCHED;
3467bc05ae6SDmitry Chagin 			pid = 0;
3477bc05ae6SDmitry Chagin 		}
3482711aba9SDmitry Chagin 		if (pid == 0) {
3492711aba9SDmitry Chagin 			p = td->td_proc;
3502711aba9SDmitry Chagin 			PROC_LOCK(p);
3512711aba9SDmitry Chagin 		} else {
3522711aba9SDmitry Chagin 			error = pget(pid, PGET_CANSEE, &p);
3532711aba9SDmitry Chagin 			if (error != 0)
3542711aba9SDmitry Chagin 				return (EINVAL);
3552711aba9SDmitry Chagin 		}
3562711aba9SDmitry Chagin 		switch (clockwhich) {
3572711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
3582711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3592711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
3602711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3612711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3622711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
36399b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3642711aba9SDmitry Chagin 			break;
3652711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
3662711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3672711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
3682711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3692711aba9SDmitry Chagin 			PROC_UNLOCK(p);
37099b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3712711aba9SDmitry Chagin 			break;
3722711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
37399b6f430SDmitry Chagin 			kern_process_cputime(p, tp);
3742711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3752711aba9SDmitry Chagin 			break;
3762711aba9SDmitry Chagin 		default:
3772711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3782711aba9SDmitry Chagin 			return (EINVAL);
3792711aba9SDmitry Chagin 		}
3802711aba9SDmitry Chagin 
3812711aba9SDmitry Chagin 		break;
3822711aba9SDmitry Chagin 
3832711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
38499b6f430SDmitry Chagin 		if (which < 0) {
38599b6f430SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_WHICH(which);
38699b6f430SDmitry Chagin 			tid = LINUX_CPUCLOCK_ID(which);
3877bc05ae6SDmitry Chagin 		} else {
3887bc05ae6SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_SCHED;
3897bc05ae6SDmitry Chagin 			tid = 0;
3907bc05ae6SDmitry Chagin 		}
3917bc05ae6SDmitry Chagin 		p = td->td_proc;
3922711aba9SDmitry Chagin 		if (tid == 0) {
3932711aba9SDmitry Chagin 			targettd = td;
3942711aba9SDmitry Chagin 			PROC_LOCK(p);
3952711aba9SDmitry Chagin 		} else {
3967bc05ae6SDmitry Chagin 			targettd = linux_tdfind(td, tid, p->p_pid);
3972711aba9SDmitry Chagin 			if (targettd == NULL)
3982711aba9SDmitry Chagin 				return (EINVAL);
3992711aba9SDmitry Chagin 		}
4002711aba9SDmitry Chagin 		switch (clockwhich) {
4012711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
4022711aba9SDmitry Chagin 			PROC_STATLOCK(p);
4032711aba9SDmitry Chagin 			thread_lock(targettd);
4042711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
4052711aba9SDmitry Chagin 			thread_unlock(targettd);
4062711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
4072711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4082711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
40999b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
4102711aba9SDmitry Chagin 			break;
4112711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
4122711aba9SDmitry Chagin 			PROC_STATLOCK(p);
4132711aba9SDmitry Chagin 			thread_lock(targettd);
4142711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
4152711aba9SDmitry Chagin 			thread_unlock(targettd);
4162711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
4172711aba9SDmitry Chagin 			PROC_UNLOCK(p);
41899b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
4192711aba9SDmitry Chagin 			break;
4202711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
4217bc05ae6SDmitry Chagin 			if (td == targettd)
4227bc05ae6SDmitry Chagin 				targettd = NULL;
42399b6f430SDmitry Chagin 			kern_thread_cputime(targettd, tp);
4242711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4252711aba9SDmitry Chagin 			break;
4262711aba9SDmitry Chagin 		default:
4272711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4282711aba9SDmitry Chagin 			return (EINVAL);
4292711aba9SDmitry Chagin 		}
4302711aba9SDmitry Chagin 		break;
4312711aba9SDmitry Chagin 
4322711aba9SDmitry Chagin 	default:
43399b6f430SDmitry Chagin 		error = kern_clock_gettime(td, nwhich, tp);
4342711aba9SDmitry Chagin 		break;
4352711aba9SDmitry Chagin 	}
43699b6f430SDmitry Chagin 
43799b6f430SDmitry Chagin 	return (error);
43899b6f430SDmitry Chagin }
43999b6f430SDmitry Chagin 
44099b6f430SDmitry Chagin int
44199b6f430SDmitry Chagin linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
44299b6f430SDmitry Chagin {
44399b6f430SDmitry Chagin 	struct timespec tp;
44499b6f430SDmitry Chagin 	int error;
44599b6f430SDmitry Chagin 
44699b6f430SDmitry Chagin 	error = linux_common_clock_gettime(td, args->which, &tp);
44719e252baSAlexander Leidinger 	if (error != 0) {
44819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
44977424f41SJung-uk Kim 		return (error);
45019e252baSAlexander Leidinger 	}
4519a9482f8SDmitry Chagin 	error = linux_put_timespec(&tp, args->tp);
45219e252baSAlexander Leidinger 	if (error != 0)
45319e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
45419e252baSAlexander Leidinger 
45519e252baSAlexander Leidinger 	return (error);
456ad2056f2SAlexander Leidinger }
457ad2056f2SAlexander Leidinger 
45899b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
45999b6f430SDmitry Chagin int
46099b6f430SDmitry Chagin linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args)
46199b6f430SDmitry Chagin {
46299b6f430SDmitry Chagin 	struct timespec tp;
46399b6f430SDmitry Chagin 	int error;
46499b6f430SDmitry Chagin 
46599b6f430SDmitry Chagin 	error = linux_common_clock_gettime(td, args->which, &tp);
46699b6f430SDmitry Chagin 	if (error != 0) {
46799b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error);
46899b6f430SDmitry Chagin 		return (error);
46999b6f430SDmitry Chagin 	}
4709a9482f8SDmitry Chagin 	error = linux_put_timespec64(&tp, args->tp);
47199b6f430SDmitry Chagin 	if (error != 0)
47299b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error);
47399b6f430SDmitry Chagin 
47499b6f430SDmitry Chagin 	return (error);
47599b6f430SDmitry Chagin }
47699b6f430SDmitry Chagin #endif
47799b6f430SDmitry Chagin 
47819f9a0e4SDmitry Chagin static int
47919f9a0e4SDmitry Chagin linux_common_clock_settime(struct thread *td, clockid_t which,
48019f9a0e4SDmitry Chagin     struct timespec *ts)
48119f9a0e4SDmitry Chagin {
48219f9a0e4SDmitry Chagin 	int error;
48319f9a0e4SDmitry Chagin 	clockid_t nwhich;
48419f9a0e4SDmitry Chagin 
48519f9a0e4SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
48619f9a0e4SDmitry Chagin 	if (error != 0) {
48719f9a0e4SDmitry Chagin 		linux_msg(curthread,
48819f9a0e4SDmitry Chagin 		    "unsupported clock_settime clockid %d", which);
48919f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error,
49019f9a0e4SDmitry Chagin 		    error);
49119f9a0e4SDmitry Chagin 		return (error);
49219f9a0e4SDmitry Chagin 	}
49319f9a0e4SDmitry Chagin 
49419f9a0e4SDmitry Chagin 	error = kern_clock_settime(td, nwhich, ts);
49519f9a0e4SDmitry Chagin 	if (error != 0)
49619f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_settime,
49719f9a0e4SDmitry Chagin 		    settime_error, error);
49819f9a0e4SDmitry Chagin 
49919f9a0e4SDmitry Chagin 	return (error);
50019f9a0e4SDmitry Chagin }
50119f9a0e4SDmitry Chagin 
502ad2056f2SAlexander Leidinger int
503ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
504ad2056f2SAlexander Leidinger {
505ad2056f2SAlexander Leidinger 	struct timespec ts;
506ad2056f2SAlexander Leidinger 	struct l_timespec lts;
507ad2056f2SAlexander Leidinger 	int error;
508ad2056f2SAlexander Leidinger 
50919f9a0e4SDmitry Chagin 	error = copyin(args->tp, &lts, sizeof(lts));
51019e252baSAlexander Leidinger 	if (error != 0) {
51119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
51219e252baSAlexander Leidinger 		return (error);
51319e252baSAlexander Leidinger 	}
51419e252baSAlexander Leidinger 	error = linux_to_native_timespec(&ts, &lts);
51519f9a0e4SDmitry Chagin 	if (error != 0)
51619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
51719e252baSAlexander Leidinger 		    error);
51819f9a0e4SDmitry Chagin 
51919f9a0e4SDmitry Chagin 	return (linux_common_clock_settime(td, args->which, &ts));
52019e252baSAlexander Leidinger }
52119e252baSAlexander Leidinger 
52219f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
52319f9a0e4SDmitry Chagin int
52419f9a0e4SDmitry Chagin linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args)
52519f9a0e4SDmitry Chagin {
52619f9a0e4SDmitry Chagin 	struct timespec ts;
52719f9a0e4SDmitry Chagin 	struct l_timespec64 lts;
52819f9a0e4SDmitry Chagin 	int error;
52919f9a0e4SDmitry Chagin 
53019f9a0e4SDmitry Chagin 	error = copyin(args->tp, &lts, sizeof(lts));
53119f9a0e4SDmitry Chagin 	if (error != 0) {
53219f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error);
53319f9a0e4SDmitry Chagin 		return (error);
53419f9a0e4SDmitry Chagin 	}
53519f9a0e4SDmitry Chagin 	error = linux_to_native_timespec64(&ts, &lts);
53619e252baSAlexander Leidinger 	if (error != 0)
53719f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_settime64, conversion_error,
53819f9a0e4SDmitry Chagin 		    error);
53919f9a0e4SDmitry Chagin 	return (linux_common_clock_settime(td, args->which, &ts));
540ad2056f2SAlexander Leidinger }
54119f9a0e4SDmitry Chagin #endif
542ad2056f2SAlexander Leidinger 
543187715a4SDmitry Chagin static int
544187715a4SDmitry Chagin linux_common_clock_getres(struct thread *td, clockid_t which,
545187715a4SDmitry Chagin     struct timespec *ts)
546ad2056f2SAlexander Leidinger {
5472711aba9SDmitry Chagin 	struct proc *p;
5482711aba9SDmitry Chagin 	int error, clockwhich;
5492506c761SDmitry Chagin 	clockid_t nwhich;
5502711aba9SDmitry Chagin 	pid_t pid;
5512711aba9SDmitry Chagin 	lwpid_t tid;
552ad2056f2SAlexander Leidinger 
553187715a4SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
55419e252baSAlexander Leidinger 	if (error != 0) {
5554afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
556187715a4SDmitry Chagin 		    "unsupported clock_getres clockid %d", which);
557187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_getres,
558187715a4SDmitry Chagin 		    conversion_error, error);
55977424f41SJung-uk Kim 		return (error);
56019e252baSAlexander Leidinger 	}
5612711aba9SDmitry Chagin 
5622711aba9SDmitry Chagin 	/*
5632711aba9SDmitry Chagin 	 * Check user supplied clock id in case of per-process
5642711aba9SDmitry Chagin 	 * or thread-specific cpu-time clock.
5652711aba9SDmitry Chagin 	 */
566187715a4SDmitry Chagin 	if (which < 0) {
5672711aba9SDmitry Chagin 		switch (nwhich) {
5682711aba9SDmitry Chagin 		case CLOCK_THREAD_CPUTIME_ID:
569187715a4SDmitry Chagin 			tid = LINUX_CPUCLOCK_ID(which);
5702711aba9SDmitry Chagin 			if (tid != 0) {
5712711aba9SDmitry Chagin 				p = td->td_proc;
5727bc05ae6SDmitry Chagin 				if (linux_tdfind(td, tid, p->p_pid) == NULL)
5737bc05ae6SDmitry Chagin 					return (EINVAL);
5742711aba9SDmitry Chagin 				PROC_UNLOCK(p);
5752711aba9SDmitry Chagin 			}
5762711aba9SDmitry Chagin 			break;
5772711aba9SDmitry Chagin 		case CLOCK_PROCESS_CPUTIME_ID:
578187715a4SDmitry Chagin 			pid = LINUX_CPUCLOCK_ID(which);
5792711aba9SDmitry Chagin 			if (pid != 0) {
5802711aba9SDmitry Chagin 				error = pget(pid, PGET_CANSEE, &p);
5812711aba9SDmitry Chagin 				if (error != 0)
5822711aba9SDmitry Chagin 					return (EINVAL);
5832711aba9SDmitry Chagin 				PROC_UNLOCK(p);
5842711aba9SDmitry Chagin 			}
5852711aba9SDmitry Chagin 			break;
5862711aba9SDmitry Chagin 		}
5877bc05ae6SDmitry Chagin 	}
5882711aba9SDmitry Chagin 
589187715a4SDmitry Chagin 	if (ts == NULL) {
590187715a4SDmitry Chagin 		LIN_SDT_PROBE0(time, linux_common_clock_getres, nullcall);
5912711aba9SDmitry Chagin 		return (0);
5922711aba9SDmitry Chagin 	}
5932711aba9SDmitry Chagin 
5942711aba9SDmitry Chagin 	switch (nwhich) {
5952711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
5962711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
597187715a4SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(which);
5987bc05ae6SDmitry Chagin 		/*
5997bc05ae6SDmitry Chagin 		 * In both cases (when the clock id obtained by a call to
6007bc05ae6SDmitry Chagin 		 * clock_getcpuclockid() or using the clock
6017bc05ae6SDmitry Chagin 		 * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision
6027bc05ae6SDmitry Chagin 		 * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock.
6037bc05ae6SDmitry Chagin 		 *
6047bc05ae6SDmitry Chagin 		 * See Linux posix_cpu_clock_getres() implementation.
6057bc05ae6SDmitry Chagin 		 */
606187715a4SDmitry Chagin 		if (which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) {
607187715a4SDmitry Chagin 			ts->tv_sec = 0;
608187715a4SDmitry Chagin 			ts->tv_nsec = 1;
6097bc05ae6SDmitry Chagin 			goto out;
6107bc05ae6SDmitry Chagin 		}
6117bc05ae6SDmitry Chagin 
6122711aba9SDmitry Chagin 		switch (clockwhich) {
6132711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
6142711aba9SDmitry Chagin 			nwhich = CLOCK_PROF;
6152711aba9SDmitry Chagin 			break;
6162711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
6172711aba9SDmitry Chagin 			nwhich = CLOCK_VIRTUAL;
6182711aba9SDmitry Chagin 			break;
6192711aba9SDmitry Chagin 		default:
6202711aba9SDmitry Chagin 			return (EINVAL);
6212711aba9SDmitry Chagin 		}
6222711aba9SDmitry Chagin 		break;
6232711aba9SDmitry Chagin 
6242711aba9SDmitry Chagin 	default:
6252711aba9SDmitry Chagin 		break;
6262711aba9SDmitry Chagin 	}
627187715a4SDmitry Chagin 	error = kern_clock_getres(td, nwhich, ts);
62819e252baSAlexander Leidinger 	if (error != 0) {
629187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_getres,
630187715a4SDmitry Chagin 		    getres_error, error);
63177424f41SJung-uk Kim 		return (error);
63219e252baSAlexander Leidinger 	}
6337bc05ae6SDmitry Chagin 
6347bc05ae6SDmitry Chagin out:
635187715a4SDmitry Chagin 	return (error);
636187715a4SDmitry Chagin }
637187715a4SDmitry Chagin 
638187715a4SDmitry Chagin int
639187715a4SDmitry Chagin linux_clock_getres(struct thread *td,
640187715a4SDmitry Chagin     struct linux_clock_getres_args *args)
641187715a4SDmitry Chagin {
642187715a4SDmitry Chagin 	struct timespec ts;
643187715a4SDmitry Chagin 	int error;
644187715a4SDmitry Chagin 
645187715a4SDmitry Chagin 	error = linux_common_clock_getres(td, args->which, &ts);
646187715a4SDmitry Chagin 	if (error != 0 || args->tp == NULL)
647187715a4SDmitry Chagin 		return (error);
6489a9482f8SDmitry Chagin 	error = linux_put_timespec(&ts, args->tp);
64919e252baSAlexander Leidinger 	if (error != 0)
650187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_getres,
651187715a4SDmitry Chagin 		    copyout_error, error);
65219e252baSAlexander Leidinger 	return (error);
65377424f41SJung-uk Kim }
65477424f41SJung-uk Kim 
655187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
656187715a4SDmitry Chagin int
657187715a4SDmitry Chagin linux_clock_getres_time64(struct thread *td,
658187715a4SDmitry Chagin     struct linux_clock_getres_time64_args *args)
659187715a4SDmitry Chagin {
660187715a4SDmitry Chagin 	struct timespec ts;
661187715a4SDmitry Chagin 	int error;
662187715a4SDmitry Chagin 
663187715a4SDmitry Chagin 	error = linux_common_clock_getres(td, args->which, &ts);
664187715a4SDmitry Chagin 	if (error != 0 || args->tp == NULL)
665187715a4SDmitry Chagin 		return (error);
6669a9482f8SDmitry Chagin 	error = linux_put_timespec64(&ts, args->tp);
667187715a4SDmitry Chagin 	if (error != 0)
668187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_getres_time64,
669187715a4SDmitry Chagin 		    copyout_error, error);
670187715a4SDmitry Chagin 	return (error);
671187715a4SDmitry Chagin }
672187715a4SDmitry Chagin #endif
673187715a4SDmitry Chagin 
67477424f41SJung-uk Kim int
67577424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
67677424f41SJung-uk Kim {
67777424f41SJung-uk Kim 	struct timespec *rmtp;
6789a9482f8SDmitry Chagin 	struct l_timespec lrqts;
67977424f41SJung-uk Kim 	struct timespec rqts, rmts;
6805c2748d5SDmitry Chagin 	int error, error2;
68177424f41SJung-uk Kim 
68277424f41SJung-uk Kim 	error = copyin(args->rqtp, &lrqts, sizeof lrqts);
68319e252baSAlexander Leidinger 	if (error != 0) {
68419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
68577424f41SJung-uk Kim 		return (error);
68619e252baSAlexander Leidinger 	}
68777424f41SJung-uk Kim 
68877424f41SJung-uk Kim 	if (args->rmtp != NULL)
68977424f41SJung-uk Kim 		rmtp = &rmts;
69077424f41SJung-uk Kim 	else
69177424f41SJung-uk Kim 		rmtp = NULL;
69277424f41SJung-uk Kim 
69377424f41SJung-uk Kim 	error = linux_to_native_timespec(&rqts, &lrqts);
69419e252baSAlexander Leidinger 	if (error != 0) {
69519e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
69677424f41SJung-uk Kim 		return (error);
69719e252baSAlexander Leidinger 	}
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
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
7406501370aSDmitry Chagin linux_clock_nanosleep(struct thread *td,
7416501370aSDmitry Chagin     struct linux_clock_nanosleep_args *args)
742ad2056f2SAlexander Leidinger {
743ad2056f2SAlexander Leidinger 	struct timespec *rmtp;
7449a9482f8SDmitry Chagin 	struct l_timespec lrqts;
745ad2056f2SAlexander Leidinger 	struct timespec rqts, rmts;
7466501370aSDmitry Chagin 	int error, error2;
747ad2056f2SAlexander Leidinger 
7485c2748d5SDmitry Chagin 	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
74919e252baSAlexander Leidinger 	if (error != 0) {
75019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
75119e252baSAlexander Leidinger 		    error);
75277424f41SJung-uk Kim 		return (error);
75319e252baSAlexander Leidinger 	}
754ad2056f2SAlexander Leidinger 
7556501370aSDmitry Chagin 	error = linux_to_native_timespec(&rqts, &lrqts);
7566501370aSDmitry Chagin 	if (error != 0) {
7576501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
7586501370aSDmitry Chagin 		    error);
7596501370aSDmitry Chagin 		return (error);
7606501370aSDmitry Chagin 	}
7616501370aSDmitry Chagin 
762ad2056f2SAlexander Leidinger 	if (args->rmtp != NULL)
763ad2056f2SAlexander Leidinger 		rmtp = &rmts;
764ad2056f2SAlexander Leidinger 	else
765ad2056f2SAlexander Leidinger 		rmtp = NULL;
766ad2056f2SAlexander Leidinger 
7676501370aSDmitry Chagin 	error = linux_common_clock_nanosleep(td, args->which, args->flags,
7686501370aSDmitry Chagin 	    &rqts, rmtp);
7696501370aSDmitry Chagin 	if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
770f0f58384SDmitry Chagin 	    args->rmtp != NULL) {
7719a9482f8SDmitry Chagin 		error2 = linux_put_timespec(rmtp, args->rmtp);
7725c2748d5SDmitry Chagin 		if (error2 != 0) {
7735c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
7745c2748d5SDmitry Chagin 			    copyout_error, error2);
7755c2748d5SDmitry Chagin 			return (error2);
7765c2748d5SDmitry Chagin 		}
7775c2748d5SDmitry Chagin 	}
77877424f41SJung-uk Kim 	return (error);
77919e252baSAlexander Leidinger }
7806501370aSDmitry Chagin 
7816501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
7826501370aSDmitry Chagin int
7836501370aSDmitry Chagin linux_clock_nanosleep_time64(struct thread *td,
7846501370aSDmitry Chagin     struct linux_clock_nanosleep_time64_args *args)
7856501370aSDmitry Chagin {
7866501370aSDmitry Chagin 	struct timespec *rmtp;
7879a9482f8SDmitry Chagin 	struct l_timespec64 lrqts;
7886501370aSDmitry Chagin 	struct timespec rqts, rmts;
7896501370aSDmitry Chagin 	int error, error2;
7906501370aSDmitry Chagin 
7916501370aSDmitry Chagin 	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
7926501370aSDmitry Chagin 	if (error != 0) {
7936501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
7946501370aSDmitry Chagin 		    copyin_error, error);
7956501370aSDmitry Chagin 		return (error);
7966501370aSDmitry Chagin 	}
7976501370aSDmitry Chagin 
7986501370aSDmitry Chagin 	error = linux_to_native_timespec64(&rqts, &lrqts);
7996501370aSDmitry Chagin 	if (error != 0) {
8006501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
8016501370aSDmitry Chagin 		    conversion_error, error);
8026501370aSDmitry Chagin 		return (error);
8036501370aSDmitry Chagin 	}
8046501370aSDmitry Chagin 
8056501370aSDmitry Chagin 	if (args->rmtp != NULL)
8066501370aSDmitry Chagin 		rmtp = &rmts;
8076501370aSDmitry Chagin 	else
8086501370aSDmitry Chagin 		rmtp = NULL;
8096501370aSDmitry Chagin 
8106501370aSDmitry Chagin 	error = linux_common_clock_nanosleep(td, args->which, args->flags,
8116501370aSDmitry Chagin 	    &rqts, rmtp);
8126501370aSDmitry Chagin 	if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
8136501370aSDmitry Chagin 	    args->rmtp != NULL) {
8149a9482f8SDmitry Chagin 		error2 = linux_put_timespec64(rmtp, args->rmtp);
8156501370aSDmitry Chagin 		if (error2 != 0) {
8166501370aSDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
8176501370aSDmitry Chagin 			    copyout_error, error2);
8186501370aSDmitry Chagin 			return (error2);
8196501370aSDmitry Chagin 		}
8206501370aSDmitry Chagin 	}
8216501370aSDmitry Chagin 	return (error);
8226501370aSDmitry Chagin }
8236501370aSDmitry Chagin #endif
824