xref: /freebsd/sys/compat/linux/linux_time.c (revision 6501370a7dfb358daf07555136742bc064e68cb7)
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");
110*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int");
111*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int");
112*6501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
113*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, conversion_error, "int");
114*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int");
115*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int");
116*6501370aSDmitry 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 *);
124*6501370aSDmitry Chagin static int	linux_common_clock_nanosleep(struct thread *, clockid_t,
125*6501370aSDmitry 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 
1455e8caee2SEdward Tomasz Napierala 	if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999)
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 
153bfcce1a9SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
154bfcce1a9SDmitry Chagin int
155bfcce1a9SDmitry Chagin native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
156bfcce1a9SDmitry Chagin {
157bfcce1a9SDmitry Chagin 
158bfcce1a9SDmitry Chagin 	ltp64->tv_sec = ntp->tv_sec;
159bfcce1a9SDmitry Chagin 	ltp64->tv_nsec = ntp->tv_nsec;
160bfcce1a9SDmitry Chagin 
161bfcce1a9SDmitry Chagin 	return (0);
162bfcce1a9SDmitry Chagin }
163bfcce1a9SDmitry Chagin 
164bfcce1a9SDmitry Chagin int
165bfcce1a9SDmitry Chagin linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64)
166bfcce1a9SDmitry Chagin {
167bfcce1a9SDmitry Chagin 
168bfcce1a9SDmitry Chagin 	if (ltp64->tv_sec < 0 || ltp64->tv_nsec < 0 || ltp64->tv_nsec > 999999999)
169bfcce1a9SDmitry Chagin 		return (EINVAL);
170bfcce1a9SDmitry Chagin 	ntp->tv_sec = ltp64->tv_sec;
171bfcce1a9SDmitry Chagin 	ntp->tv_nsec = ltp64->tv_nsec;
172bfcce1a9SDmitry Chagin 
173bfcce1a9SDmitry Chagin 	return (0);
174bfcce1a9SDmitry Chagin }
175bfcce1a9SDmitry Chagin #endif
176bfcce1a9SDmitry Chagin 
17716ac71bcSDmitry Chagin int
178dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
179dd93b628SDmitry Chagin {
180dd93b628SDmitry Chagin 	int error;
181dd93b628SDmitry Chagin 
182dd93b628SDmitry Chagin 	error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
183dd93b628SDmitry Chagin 	if (error == 0)
184dd93b628SDmitry Chagin 		error = native_to_linux_timespec(&ltp->it_value, &ntp->it_interval);
185dd93b628SDmitry Chagin 	return (error);
186dd93b628SDmitry Chagin }
187dd93b628SDmitry Chagin 
188dd93b628SDmitry Chagin int
189dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
190dd93b628SDmitry Chagin {
191dd93b628SDmitry Chagin 	int error;
192dd93b628SDmitry Chagin 
193dd93b628SDmitry Chagin 	error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
194dd93b628SDmitry Chagin 	if (error == 0)
195dd93b628SDmitry Chagin 		error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
196dd93b628SDmitry Chagin 	return (error);
197dd93b628SDmitry Chagin }
198dd93b628SDmitry Chagin 
199dd93b628SDmitry Chagin int
200ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l)
201ad2056f2SAlexander Leidinger {
20219e252baSAlexander Leidinger 
2032711aba9SDmitry Chagin 	if (l < 0) {
2042711aba9SDmitry Chagin 		/* cpu-clock */
2052711aba9SDmitry Chagin 		if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
2062711aba9SDmitry Chagin 			return (EINVAL);
2072711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
2082711aba9SDmitry Chagin 			return (EINVAL);
2092711aba9SDmitry Chagin 
2102711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_PERTHREAD(l))
2112711aba9SDmitry Chagin 			*n = CLOCK_THREAD_CPUTIME_ID;
2122711aba9SDmitry Chagin 		else
2132711aba9SDmitry Chagin 			*n = CLOCK_PROCESS_CPUTIME_ID;
2142711aba9SDmitry Chagin 		return (0);
2152711aba9SDmitry Chagin 	}
2162711aba9SDmitry Chagin 
217ad2056f2SAlexander Leidinger 	switch (l) {
218ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_REALTIME:
219ad2056f2SAlexander Leidinger 		*n = CLOCK_REALTIME;
220ad2056f2SAlexander Leidinger 		break;
221ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC:
222ad2056f2SAlexander Leidinger 		*n = CLOCK_MONOTONIC;
223ad2056f2SAlexander Leidinger 		break;
2247bc05ae6SDmitry Chagin 	case LINUX_CLOCK_PROCESS_CPUTIME_ID:
2257bc05ae6SDmitry Chagin 		*n = CLOCK_PROCESS_CPUTIME_ID;
2267bc05ae6SDmitry Chagin 		break;
2277bc05ae6SDmitry Chagin 	case LINUX_CLOCK_THREAD_CPUTIME_ID:
2287bc05ae6SDmitry Chagin 		*n = CLOCK_THREAD_CPUTIME_ID;
2297bc05ae6SDmitry Chagin 		break;
2302711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_COARSE:
2312711aba9SDmitry Chagin 		*n = CLOCK_REALTIME_FAST;
2322711aba9SDmitry Chagin 		break;
2332711aba9SDmitry Chagin 	case LINUX_CLOCK_MONOTONIC_COARSE:
234e37db348SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC_RAW:
2352711aba9SDmitry Chagin 		*n = CLOCK_MONOTONIC_FAST;
2362711aba9SDmitry Chagin 		break;
2372711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME:
23825ada637SDmitry Chagin 		*n = CLOCK_UPTIME;
23925ada637SDmitry Chagin 		break;
2402711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_ALARM:
2412711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME_ALARM:
2422711aba9SDmitry Chagin 	case LINUX_CLOCK_SGI_CYCLE:
2432711aba9SDmitry Chagin 	case LINUX_CLOCK_TAI:
24419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
24519e252baSAlexander Leidinger 		    unsupported_clockid, l);
24619e252baSAlexander Leidinger 		return (EINVAL);
24777424f41SJung-uk Kim 	default:
24819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
24919e252baSAlexander Leidinger 		    unknown_clockid, l);
25077424f41SJung-uk Kim 		return (EINVAL);
251ad2056f2SAlexander Leidinger 	}
252ad2056f2SAlexander Leidinger 
25377424f41SJung-uk Kim 	return (0);
254ad2056f2SAlexander Leidinger }
255ad2056f2SAlexander Leidinger 
256ad2056f2SAlexander Leidinger int
257f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags)
258f0f58384SDmitry Chagin {
259f0f58384SDmitry Chagin 
260f0f58384SDmitry Chagin 	if (flags & ~LINUX_TIMER_ABSTIME)
261f0f58384SDmitry Chagin 		return (EINVAL);
262f0f58384SDmitry Chagin 	*nflags = 0;
263f0f58384SDmitry Chagin 	if (flags & LINUX_TIMER_ABSTIME)
264f0f58384SDmitry Chagin 		*nflags |= TIMER_ABSTIME;
265f0f58384SDmitry Chagin 	return (0);
266f0f58384SDmitry Chagin }
267f0f58384SDmitry Chagin 
26899b6f430SDmitry Chagin static int
26999b6f430SDmitry Chagin linux_common_clock_gettime(struct thread *td, clockid_t which,
27099b6f430SDmitry Chagin     struct timespec *tp)
271ad2056f2SAlexander Leidinger {
2722711aba9SDmitry Chagin 	struct rusage ru;
2732711aba9SDmitry Chagin 	struct thread *targettd;
2742711aba9SDmitry Chagin 	struct proc *p;
2752711aba9SDmitry Chagin 	int error, clockwhich;
2762506c761SDmitry Chagin 	clockid_t nwhich;
2772711aba9SDmitry Chagin 	pid_t pid;
2782711aba9SDmitry Chagin 	lwpid_t tid;
279ad2056f2SAlexander Leidinger 
28099b6f430SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
28119e252baSAlexander Leidinger 	if (error != 0) {
2824afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
28399b6f430SDmitry Chagin 		    "unsupported clock_gettime clockid %d", which);
28499b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_gettime,
28599b6f430SDmitry Chagin 		    conversion_error, error);
28677424f41SJung-uk Kim 		return (error);
28719e252baSAlexander Leidinger 	}
2882711aba9SDmitry Chagin 
2892711aba9SDmitry Chagin 	switch (nwhich) {
2902711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
29199b6f430SDmitry Chagin 		if (which < 0) {
29299b6f430SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_WHICH(which);
29399b6f430SDmitry Chagin 			pid = LINUX_CPUCLOCK_ID(which);
2947bc05ae6SDmitry Chagin 		} else {
2957bc05ae6SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_SCHED;
2967bc05ae6SDmitry Chagin 			pid = 0;
2977bc05ae6SDmitry Chagin 		}
2982711aba9SDmitry Chagin 		if (pid == 0) {
2992711aba9SDmitry Chagin 			p = td->td_proc;
3002711aba9SDmitry Chagin 			PROC_LOCK(p);
3012711aba9SDmitry Chagin 		} else {
3022711aba9SDmitry Chagin 			error = pget(pid, PGET_CANSEE, &p);
3032711aba9SDmitry Chagin 			if (error != 0)
3042711aba9SDmitry Chagin 				return (EINVAL);
3052711aba9SDmitry Chagin 		}
3062711aba9SDmitry Chagin 		switch (clockwhich) {
3072711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
3082711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3092711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
3102711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3112711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3122711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
31399b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3142711aba9SDmitry Chagin 			break;
3152711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
3162711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3172711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
3182711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3192711aba9SDmitry Chagin 			PROC_UNLOCK(p);
32099b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3212711aba9SDmitry Chagin 			break;
3222711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
32399b6f430SDmitry Chagin 			kern_process_cputime(p, tp);
3242711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3252711aba9SDmitry Chagin 			break;
3262711aba9SDmitry Chagin 		default:
3272711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3282711aba9SDmitry Chagin 			return (EINVAL);
3292711aba9SDmitry Chagin 		}
3302711aba9SDmitry Chagin 
3312711aba9SDmitry Chagin 		break;
3322711aba9SDmitry Chagin 
3332711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
33499b6f430SDmitry Chagin 		if (which < 0) {
33599b6f430SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_WHICH(which);
33699b6f430SDmitry Chagin 			tid = LINUX_CPUCLOCK_ID(which);
3377bc05ae6SDmitry Chagin 		} else {
3387bc05ae6SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_SCHED;
3397bc05ae6SDmitry Chagin 			tid = 0;
3407bc05ae6SDmitry Chagin 		}
3417bc05ae6SDmitry Chagin 		p = td->td_proc;
3422711aba9SDmitry Chagin 		if (tid == 0) {
3432711aba9SDmitry Chagin 			targettd = td;
3442711aba9SDmitry Chagin 			PROC_LOCK(p);
3452711aba9SDmitry Chagin 		} else {
3467bc05ae6SDmitry Chagin 			targettd = linux_tdfind(td, tid, p->p_pid);
3472711aba9SDmitry Chagin 			if (targettd == NULL)
3482711aba9SDmitry Chagin 				return (EINVAL);
3492711aba9SDmitry Chagin 		}
3502711aba9SDmitry Chagin 		switch (clockwhich) {
3512711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
3522711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3532711aba9SDmitry Chagin 			thread_lock(targettd);
3542711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
3552711aba9SDmitry Chagin 			thread_unlock(targettd);
3562711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3572711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3582711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
35999b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3602711aba9SDmitry Chagin 			break;
3612711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
3622711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3632711aba9SDmitry Chagin 			thread_lock(targettd);
3642711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
3652711aba9SDmitry Chagin 			thread_unlock(targettd);
3662711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3672711aba9SDmitry Chagin 			PROC_UNLOCK(p);
36899b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3692711aba9SDmitry Chagin 			break;
3702711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
3717bc05ae6SDmitry Chagin 			if (td == targettd)
3727bc05ae6SDmitry Chagin 				targettd = NULL;
37399b6f430SDmitry Chagin 			kern_thread_cputime(targettd, 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 		break;
3812711aba9SDmitry Chagin 
3822711aba9SDmitry Chagin 	default:
38399b6f430SDmitry Chagin 		error = kern_clock_gettime(td, nwhich, tp);
3842711aba9SDmitry Chagin 		break;
3852711aba9SDmitry Chagin 	}
38699b6f430SDmitry Chagin 
38799b6f430SDmitry Chagin 	return (error);
38899b6f430SDmitry Chagin }
38999b6f430SDmitry Chagin 
39099b6f430SDmitry Chagin int
39199b6f430SDmitry Chagin linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
39299b6f430SDmitry Chagin {
39399b6f430SDmitry Chagin 	struct l_timespec lts;
39499b6f430SDmitry Chagin 	struct timespec tp;
39599b6f430SDmitry Chagin 	int error;
39699b6f430SDmitry Chagin 
39799b6f430SDmitry Chagin 	error = linux_common_clock_gettime(td, args->which, &tp);
39819e252baSAlexander Leidinger 	if (error != 0) {
39919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
40077424f41SJung-uk Kim 		return (error);
40119e252baSAlexander Leidinger 	}
4020670e972SDmitry Chagin 	error = native_to_linux_timespec(&lts, &tp);
4030670e972SDmitry Chagin 	if (error != 0)
4040670e972SDmitry Chagin 		return (error);
40599b6f430SDmitry Chagin 	error = copyout(&lts, args->tp, sizeof(lts));
40619e252baSAlexander Leidinger 	if (error != 0)
40719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
40819e252baSAlexander Leidinger 
40919e252baSAlexander Leidinger 	return (error);
410ad2056f2SAlexander Leidinger }
411ad2056f2SAlexander Leidinger 
41299b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
41399b6f430SDmitry Chagin int
41499b6f430SDmitry Chagin linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args)
41599b6f430SDmitry Chagin {
41699b6f430SDmitry Chagin 	struct l_timespec64 lts;
41799b6f430SDmitry Chagin 	struct timespec tp;
41899b6f430SDmitry Chagin 	int error;
41999b6f430SDmitry Chagin 
42099b6f430SDmitry Chagin 	error = linux_common_clock_gettime(td, args->which, &tp);
42199b6f430SDmitry Chagin 	if (error != 0) {
42299b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error);
42399b6f430SDmitry Chagin 		return (error);
42499b6f430SDmitry Chagin 	}
42599b6f430SDmitry Chagin 	error = native_to_linux_timespec64(&lts, &tp);
42699b6f430SDmitry Chagin 	if (error != 0)
42799b6f430SDmitry Chagin 		return (error);
42899b6f430SDmitry Chagin 	error = copyout(&lts, args->tp, sizeof(lts));
42999b6f430SDmitry Chagin 	if (error != 0)
43099b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error);
43199b6f430SDmitry Chagin 
43299b6f430SDmitry Chagin 	return (error);
43399b6f430SDmitry Chagin }
43499b6f430SDmitry Chagin #endif
43599b6f430SDmitry Chagin 
43619f9a0e4SDmitry Chagin static int
43719f9a0e4SDmitry Chagin linux_common_clock_settime(struct thread *td, clockid_t which,
43819f9a0e4SDmitry Chagin     struct timespec *ts)
43919f9a0e4SDmitry Chagin {
44019f9a0e4SDmitry Chagin 	int error;
44119f9a0e4SDmitry Chagin 	clockid_t nwhich;
44219f9a0e4SDmitry Chagin 
44319f9a0e4SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
44419f9a0e4SDmitry Chagin 	if (error != 0) {
44519f9a0e4SDmitry Chagin 		linux_msg(curthread,
44619f9a0e4SDmitry Chagin 		    "unsupported clock_settime clockid %d", which);
44719f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error,
44819f9a0e4SDmitry Chagin 		    error);
44919f9a0e4SDmitry Chagin 		return (error);
45019f9a0e4SDmitry Chagin 	}
45119f9a0e4SDmitry Chagin 
45219f9a0e4SDmitry Chagin 	error = kern_clock_settime(td, nwhich, ts);
45319f9a0e4SDmitry Chagin 	if (error != 0)
45419f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_settime,
45519f9a0e4SDmitry Chagin 		    settime_error, error);
45619f9a0e4SDmitry Chagin 
45719f9a0e4SDmitry Chagin 	return (error);
45819f9a0e4SDmitry Chagin }
45919f9a0e4SDmitry Chagin 
460ad2056f2SAlexander Leidinger int
461ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
462ad2056f2SAlexander Leidinger {
463ad2056f2SAlexander Leidinger 	struct timespec ts;
464ad2056f2SAlexander Leidinger 	struct l_timespec lts;
465ad2056f2SAlexander Leidinger 	int error;
466ad2056f2SAlexander Leidinger 
46719f9a0e4SDmitry Chagin 	error = copyin(args->tp, &lts, sizeof(lts));
46819e252baSAlexander Leidinger 	if (error != 0) {
46919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
47019e252baSAlexander Leidinger 		return (error);
47119e252baSAlexander Leidinger 	}
47219e252baSAlexander Leidinger 	error = linux_to_native_timespec(&ts, &lts);
47319f9a0e4SDmitry Chagin 	if (error != 0)
47419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
47519e252baSAlexander Leidinger 		    error);
47619f9a0e4SDmitry Chagin 
47719f9a0e4SDmitry Chagin 	return (linux_common_clock_settime(td, args->which, &ts));
47819e252baSAlexander Leidinger }
47919e252baSAlexander Leidinger 
48019f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
48119f9a0e4SDmitry Chagin int
48219f9a0e4SDmitry Chagin linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args)
48319f9a0e4SDmitry Chagin {
48419f9a0e4SDmitry Chagin 	struct timespec ts;
48519f9a0e4SDmitry Chagin 	struct l_timespec64 lts;
48619f9a0e4SDmitry Chagin 	int error;
48719f9a0e4SDmitry Chagin 
48819f9a0e4SDmitry Chagin 	error = copyin(args->tp, &lts, sizeof(lts));
48919f9a0e4SDmitry Chagin 	if (error != 0) {
49019f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error);
49119f9a0e4SDmitry Chagin 		return (error);
49219f9a0e4SDmitry Chagin 	}
49319f9a0e4SDmitry Chagin 	error = linux_to_native_timespec64(&ts, &lts);
49419e252baSAlexander Leidinger 	if (error != 0)
49519f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_settime64, conversion_error,
49619f9a0e4SDmitry Chagin 		    error);
49719f9a0e4SDmitry Chagin 	return (linux_common_clock_settime(td, args->which, &ts));
498ad2056f2SAlexander Leidinger }
49919f9a0e4SDmitry Chagin #endif
500ad2056f2SAlexander Leidinger 
501187715a4SDmitry Chagin static int
502187715a4SDmitry Chagin linux_common_clock_getres(struct thread *td, clockid_t which,
503187715a4SDmitry Chagin     struct timespec *ts)
504ad2056f2SAlexander Leidinger {
5052711aba9SDmitry Chagin 	struct proc *p;
5062711aba9SDmitry Chagin 	int error, clockwhich;
5072506c761SDmitry Chagin 	clockid_t nwhich;
5082711aba9SDmitry Chagin 	pid_t pid;
5092711aba9SDmitry Chagin 	lwpid_t tid;
510ad2056f2SAlexander Leidinger 
511187715a4SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
51219e252baSAlexander Leidinger 	if (error != 0) {
5134afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
514187715a4SDmitry Chagin 		    "unsupported clock_getres clockid %d", which);
515187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_getres,
516187715a4SDmitry Chagin 		    conversion_error, error);
51777424f41SJung-uk Kim 		return (error);
51819e252baSAlexander Leidinger 	}
5192711aba9SDmitry Chagin 
5202711aba9SDmitry Chagin 	/*
5212711aba9SDmitry Chagin 	 * Check user supplied clock id in case of per-process
5222711aba9SDmitry Chagin 	 * or thread-specific cpu-time clock.
5232711aba9SDmitry Chagin 	 */
524187715a4SDmitry Chagin 	if (which < 0) {
5252711aba9SDmitry Chagin 		switch (nwhich) {
5262711aba9SDmitry Chagin 		case CLOCK_THREAD_CPUTIME_ID:
527187715a4SDmitry Chagin 			tid = LINUX_CPUCLOCK_ID(which);
5282711aba9SDmitry Chagin 			if (tid != 0) {
5292711aba9SDmitry Chagin 				p = td->td_proc;
5307bc05ae6SDmitry Chagin 				if (linux_tdfind(td, tid, p->p_pid) == NULL)
5317bc05ae6SDmitry Chagin 					return (EINVAL);
5322711aba9SDmitry Chagin 				PROC_UNLOCK(p);
5332711aba9SDmitry Chagin 			}
5342711aba9SDmitry Chagin 			break;
5352711aba9SDmitry Chagin 		case CLOCK_PROCESS_CPUTIME_ID:
536187715a4SDmitry Chagin 			pid = LINUX_CPUCLOCK_ID(which);
5372711aba9SDmitry Chagin 			if (pid != 0) {
5382711aba9SDmitry Chagin 				error = pget(pid, PGET_CANSEE, &p);
5392711aba9SDmitry Chagin 				if (error != 0)
5402711aba9SDmitry Chagin 					return (EINVAL);
5412711aba9SDmitry Chagin 				PROC_UNLOCK(p);
5422711aba9SDmitry Chagin 			}
5432711aba9SDmitry Chagin 			break;
5442711aba9SDmitry Chagin 		}
5457bc05ae6SDmitry Chagin 	}
5462711aba9SDmitry Chagin 
547187715a4SDmitry Chagin 	if (ts == NULL) {
548187715a4SDmitry Chagin 		LIN_SDT_PROBE0(time, linux_common_clock_getres, nullcall);
5492711aba9SDmitry Chagin 		return (0);
5502711aba9SDmitry Chagin 	}
5512711aba9SDmitry Chagin 
5522711aba9SDmitry Chagin 	switch (nwhich) {
5532711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
5542711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
555187715a4SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(which);
5567bc05ae6SDmitry Chagin 		/*
5577bc05ae6SDmitry Chagin 		 * In both cases (when the clock id obtained by a call to
5587bc05ae6SDmitry Chagin 		 * clock_getcpuclockid() or using the clock
5597bc05ae6SDmitry Chagin 		 * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision
5607bc05ae6SDmitry Chagin 		 * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock.
5617bc05ae6SDmitry Chagin 		 *
5627bc05ae6SDmitry Chagin 		 * See Linux posix_cpu_clock_getres() implementation.
5637bc05ae6SDmitry Chagin 		 */
564187715a4SDmitry Chagin 		if (which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) {
565187715a4SDmitry Chagin 			ts->tv_sec = 0;
566187715a4SDmitry Chagin 			ts->tv_nsec = 1;
5677bc05ae6SDmitry Chagin 			goto out;
5687bc05ae6SDmitry Chagin 		}
5697bc05ae6SDmitry Chagin 
5702711aba9SDmitry Chagin 		switch (clockwhich) {
5712711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
5722711aba9SDmitry Chagin 			nwhich = CLOCK_PROF;
5732711aba9SDmitry Chagin 			break;
5742711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
5752711aba9SDmitry Chagin 			nwhich = CLOCK_VIRTUAL;
5762711aba9SDmitry Chagin 			break;
5772711aba9SDmitry Chagin 		default:
5782711aba9SDmitry Chagin 			return (EINVAL);
5792711aba9SDmitry Chagin 		}
5802711aba9SDmitry Chagin 		break;
5812711aba9SDmitry Chagin 
5822711aba9SDmitry Chagin 	default:
5832711aba9SDmitry Chagin 		break;
5842711aba9SDmitry Chagin 	}
585187715a4SDmitry Chagin 	error = kern_clock_getres(td, nwhich, ts);
58619e252baSAlexander Leidinger 	if (error != 0) {
587187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_getres,
588187715a4SDmitry Chagin 		    getres_error, error);
58977424f41SJung-uk Kim 		return (error);
59019e252baSAlexander Leidinger 	}
5917bc05ae6SDmitry Chagin 
5927bc05ae6SDmitry Chagin out:
593187715a4SDmitry Chagin 	return (error);
594187715a4SDmitry Chagin }
595187715a4SDmitry Chagin 
596187715a4SDmitry Chagin int
597187715a4SDmitry Chagin linux_clock_getres(struct thread *td,
598187715a4SDmitry Chagin     struct linux_clock_getres_args *args)
599187715a4SDmitry Chagin {
600187715a4SDmitry Chagin 	struct timespec ts;
601187715a4SDmitry Chagin 	struct l_timespec lts;
602187715a4SDmitry Chagin 	int error;
603187715a4SDmitry Chagin 
604187715a4SDmitry Chagin 	error = linux_common_clock_getres(td, args->which, &ts);
605187715a4SDmitry Chagin 	if (error != 0 || args->tp == NULL)
606187715a4SDmitry Chagin 		return (error);
607187715a4SDmitry Chagin 
6080670e972SDmitry Chagin 	error = native_to_linux_timespec(&lts, &ts);
6090670e972SDmitry Chagin 	if (error != 0)
6100670e972SDmitry Chagin 		return (error);
611187715a4SDmitry Chagin 	error = copyout(&lts, args->tp, sizeof(lts));
61219e252baSAlexander Leidinger 	if (error != 0)
613187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_getres,
614187715a4SDmitry Chagin 		    copyout_error, error);
61519e252baSAlexander Leidinger 	return (error);
61677424f41SJung-uk Kim }
61777424f41SJung-uk Kim 
618187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
619187715a4SDmitry Chagin int
620187715a4SDmitry Chagin linux_clock_getres_time64(struct thread *td,
621187715a4SDmitry Chagin     struct linux_clock_getres_time64_args *args)
622187715a4SDmitry Chagin {
623187715a4SDmitry Chagin 	struct timespec ts;
624187715a4SDmitry Chagin 	struct l_timespec64 lts;
625187715a4SDmitry Chagin 	int error;
626187715a4SDmitry Chagin 
627187715a4SDmitry Chagin 	error = linux_common_clock_getres(td, args->which, &ts);
628187715a4SDmitry Chagin 	if (error != 0 || args->tp == NULL)
629187715a4SDmitry Chagin 		return (error);
630187715a4SDmitry Chagin 
631187715a4SDmitry Chagin 	error = native_to_linux_timespec64(&lts, &ts);
632187715a4SDmitry Chagin 	if (error != 0)
633187715a4SDmitry Chagin 		return (error);
634187715a4SDmitry Chagin 	error = copyout(&lts, args->tp, sizeof(lts));
635187715a4SDmitry Chagin 	if (error != 0)
636187715a4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_getres_time64,
637187715a4SDmitry Chagin 		    copyout_error, error);
638187715a4SDmitry Chagin 	return (error);
639187715a4SDmitry Chagin }
640187715a4SDmitry Chagin #endif
641187715a4SDmitry Chagin 
64277424f41SJung-uk Kim int
64377424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
64477424f41SJung-uk Kim {
64577424f41SJung-uk Kim 	struct timespec *rmtp;
64677424f41SJung-uk Kim 	struct l_timespec lrqts, lrmts;
64777424f41SJung-uk Kim 	struct timespec rqts, rmts;
6485c2748d5SDmitry Chagin 	int error, error2;
64977424f41SJung-uk Kim 
65077424f41SJung-uk Kim 	error = copyin(args->rqtp, &lrqts, sizeof lrqts);
65119e252baSAlexander Leidinger 	if (error != 0) {
65219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
65377424f41SJung-uk Kim 		return (error);
65419e252baSAlexander Leidinger 	}
65577424f41SJung-uk Kim 
65677424f41SJung-uk Kim 	if (args->rmtp != NULL)
65777424f41SJung-uk Kim 		rmtp = &rmts;
65877424f41SJung-uk Kim 	else
65977424f41SJung-uk Kim 		rmtp = NULL;
66077424f41SJung-uk Kim 
66177424f41SJung-uk Kim 	error = linux_to_native_timespec(&rqts, &lrqts);
66219e252baSAlexander Leidinger 	if (error != 0) {
66319e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
66477424f41SJung-uk Kim 		return (error);
66519e252baSAlexander Leidinger 	}
66677424f41SJung-uk Kim 	error = kern_nanosleep(td, &rqts, rmtp);
6674cf66812SEric van Gyzen 	if (error == EINTR && args->rmtp != NULL) {
6680670e972SDmitry Chagin 		error2 = native_to_linux_timespec(&lrmts, rmtp);
6690670e972SDmitry Chagin 		if (error2 != 0)
6700670e972SDmitry Chagin 			return (error2);
6715c2748d5SDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
6725c2748d5SDmitry Chagin 		if (error2 != 0) {
67319e252baSAlexander Leidinger 			LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
6745c2748d5SDmitry Chagin 			    error2);
6755c2748d5SDmitry Chagin 			return (error2);
67677424f41SJung-uk Kim 		}
67719e252baSAlexander Leidinger 	}
67877424f41SJung-uk Kim 
6795c2748d5SDmitry Chagin 	return (error);
680ad2056f2SAlexander Leidinger }
681ad2056f2SAlexander Leidinger 
682*6501370aSDmitry Chagin static int
683*6501370aSDmitry Chagin linux_common_clock_nanosleep(struct thread *td, clockid_t which,
684*6501370aSDmitry Chagin     l_int lflags, struct timespec *rqtp, struct timespec *rmtp)
685*6501370aSDmitry Chagin {
686*6501370aSDmitry Chagin 	int error, flags;
687*6501370aSDmitry Chagin 	clockid_t clockid;
688*6501370aSDmitry Chagin 
689*6501370aSDmitry Chagin 	error = linux_to_native_timerflags(&flags, lflags);
690*6501370aSDmitry Chagin 	if (error != 0) {
691*6501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_nanosleep,
692*6501370aSDmitry Chagin 		    unsupported_flags, lflags);
693*6501370aSDmitry Chagin 		return (error);
694*6501370aSDmitry Chagin 	}
695*6501370aSDmitry Chagin 
696*6501370aSDmitry Chagin 	error = linux_to_native_clockid(&clockid, which);
697*6501370aSDmitry Chagin 	if (error != 0) {
698*6501370aSDmitry Chagin 		linux_msg(curthread,
699*6501370aSDmitry Chagin 		    "unsupported clock_nanosleep clockid %d", which);
700*6501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_nanosleep,
701*6501370aSDmitry Chagin 		    unsupported_clockid, which);
702*6501370aSDmitry Chagin 		return (error);
703*6501370aSDmitry Chagin 	}
704*6501370aSDmitry Chagin 
705*6501370aSDmitry Chagin 	return (kern_clock_nanosleep(td, clockid, flags, rqtp, rmtp));
706*6501370aSDmitry Chagin }
707*6501370aSDmitry Chagin 
708ad2056f2SAlexander Leidinger int
709*6501370aSDmitry Chagin linux_clock_nanosleep(struct thread *td,
710*6501370aSDmitry Chagin     struct linux_clock_nanosleep_args *args)
711ad2056f2SAlexander Leidinger {
712ad2056f2SAlexander Leidinger 	struct timespec *rmtp;
713ad2056f2SAlexander Leidinger 	struct l_timespec lrqts, lrmts;
714ad2056f2SAlexander Leidinger 	struct timespec rqts, rmts;
715*6501370aSDmitry Chagin 	int error, error2;
716ad2056f2SAlexander Leidinger 
7175c2748d5SDmitry Chagin 	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
71819e252baSAlexander Leidinger 	if (error != 0) {
71919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
72019e252baSAlexander Leidinger 		    error);
72177424f41SJung-uk Kim 		return (error);
72219e252baSAlexander Leidinger 	}
723ad2056f2SAlexander Leidinger 
724*6501370aSDmitry Chagin 	error = linux_to_native_timespec(&rqts, &lrqts);
725*6501370aSDmitry Chagin 	if (error != 0) {
726*6501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
727*6501370aSDmitry Chagin 		    error);
728*6501370aSDmitry Chagin 		return (error);
729*6501370aSDmitry Chagin 	}
730*6501370aSDmitry Chagin 
731ad2056f2SAlexander Leidinger 	if (args->rmtp != NULL)
732ad2056f2SAlexander Leidinger 		rmtp = &rmts;
733ad2056f2SAlexander Leidinger 	else
734ad2056f2SAlexander Leidinger 		rmtp = NULL;
735ad2056f2SAlexander Leidinger 
736*6501370aSDmitry Chagin 	error = linux_common_clock_nanosleep(td, args->which, args->flags,
737*6501370aSDmitry Chagin 	    &rqts, rmtp);
738*6501370aSDmitry Chagin 	if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
739f0f58384SDmitry Chagin 	    args->rmtp != NULL) {
7400670e972SDmitry Chagin 		error2 = native_to_linux_timespec(&lrmts, rmtp);
7410670e972SDmitry Chagin 		if (error2 != 0)
7420670e972SDmitry Chagin 			return (error2);
7435c2748d5SDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
7445c2748d5SDmitry Chagin 		if (error2 != 0) {
7455c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
7465c2748d5SDmitry Chagin 			    copyout_error, error2);
7475c2748d5SDmitry Chagin 			return (error2);
7485c2748d5SDmitry Chagin 		}
7495c2748d5SDmitry Chagin 	}
75077424f41SJung-uk Kim 	return (error);
75119e252baSAlexander Leidinger }
752*6501370aSDmitry Chagin 
753*6501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
754*6501370aSDmitry Chagin int
755*6501370aSDmitry Chagin linux_clock_nanosleep_time64(struct thread *td,
756*6501370aSDmitry Chagin     struct linux_clock_nanosleep_time64_args *args)
757*6501370aSDmitry Chagin {
758*6501370aSDmitry Chagin 	struct timespec *rmtp;
759*6501370aSDmitry Chagin 	struct l_timespec64 lrqts, lrmts;
760*6501370aSDmitry Chagin 	struct timespec rqts, rmts;
761*6501370aSDmitry Chagin 	int error, error2;
762*6501370aSDmitry Chagin 
763*6501370aSDmitry Chagin 	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
764*6501370aSDmitry Chagin 	if (error != 0) {
765*6501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
766*6501370aSDmitry Chagin 		    copyin_error, error);
767*6501370aSDmitry Chagin 		return (error);
768*6501370aSDmitry Chagin 	}
769*6501370aSDmitry Chagin 
770*6501370aSDmitry Chagin 	error = linux_to_native_timespec64(&rqts, &lrqts);
771*6501370aSDmitry Chagin 	if (error != 0) {
772*6501370aSDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
773*6501370aSDmitry Chagin 		    conversion_error, error);
774*6501370aSDmitry Chagin 		return (error);
775*6501370aSDmitry Chagin 	}
776*6501370aSDmitry Chagin 
777*6501370aSDmitry Chagin 	if (args->rmtp != NULL)
778*6501370aSDmitry Chagin 		rmtp = &rmts;
779*6501370aSDmitry Chagin 	else
780*6501370aSDmitry Chagin 		rmtp = NULL;
781*6501370aSDmitry Chagin 
782*6501370aSDmitry Chagin 	error = linux_common_clock_nanosleep(td, args->which, args->flags,
783*6501370aSDmitry Chagin 	    &rqts, rmtp);
784*6501370aSDmitry Chagin 	if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
785*6501370aSDmitry Chagin 	    args->rmtp != NULL) {
786*6501370aSDmitry Chagin 		error2 = native_to_linux_timespec64(&lrmts, rmtp);
787*6501370aSDmitry Chagin 		if (error2 != 0)
788*6501370aSDmitry Chagin 			return (error2);
789*6501370aSDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
790*6501370aSDmitry Chagin 		if (error2 != 0) {
791*6501370aSDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
792*6501370aSDmitry Chagin 			    copyout_error, error2);
793*6501370aSDmitry Chagin 			return (error2);
794*6501370aSDmitry Chagin 		}
795*6501370aSDmitry Chagin 	}
796*6501370aSDmitry Chagin 	return (error);
797*6501370aSDmitry Chagin }
798*6501370aSDmitry Chagin #endif
799