xref: /freebsd/sys/compat/linux/linux_time.c (revision 19f9a0e4df54f8d1e99234146024422bdcfa09ce)
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");
90*19f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, settime_error, "int");
91*19f9a0e4SDmitry 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");
93*19f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
94*19f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, conversion_error, "int");
95*19f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, copyin_error, "int");
96*19f9a0e4SDmitry Chagin #endif
9719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall);
9819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int");
9919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int");
10019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
10119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
10219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
10319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
10419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
10519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
10619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
10719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int");
10819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
10919e252baSAlexander Leidinger 
11099b6f430SDmitry Chagin static int	linux_common_clock_gettime(struct thread *, clockid_t,
11199b6f430SDmitry Chagin 		    struct timespec *);
112*19f9a0e4SDmitry Chagin static int	linux_common_clock_settime(struct thread *, clockid_t,
113*19f9a0e4SDmitry Chagin 		    struct timespec *);
11499b6f430SDmitry Chagin 
1150670e972SDmitry Chagin int
116ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
117ad2056f2SAlexander Leidinger {
11819e252baSAlexander Leidinger 
1190670e972SDmitry Chagin #ifdef COMPAT_LINUX32
12071b50d08SDmitry Chagin 	if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN)
1210670e972SDmitry Chagin 		return (EOVERFLOW);
1220670e972SDmitry Chagin #endif
123ad2056f2SAlexander Leidinger 	ltp->tv_sec = ntp->tv_sec;
124ad2056f2SAlexander Leidinger 	ltp->tv_nsec = ntp->tv_nsec;
12519e252baSAlexander Leidinger 
1260670e972SDmitry Chagin 	return (0);
127ad2056f2SAlexander Leidinger }
128ad2056f2SAlexander Leidinger 
12968098228SDmitry Chagin int
130ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
131ad2056f2SAlexander Leidinger {
13219e252baSAlexander Leidinger 
1335e8caee2SEdward Tomasz Napierala 	if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999)
13477424f41SJung-uk Kim 		return (EINVAL);
135ad2056f2SAlexander Leidinger 	ntp->tv_sec = ltp->tv_sec;
136ad2056f2SAlexander Leidinger 	ntp->tv_nsec = ltp->tv_nsec;
13777424f41SJung-uk Kim 
13877424f41SJung-uk Kim 	return (0);
139ad2056f2SAlexander Leidinger }
140ad2056f2SAlexander Leidinger 
141bfcce1a9SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
142bfcce1a9SDmitry Chagin int
143bfcce1a9SDmitry Chagin native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
144bfcce1a9SDmitry Chagin {
145bfcce1a9SDmitry Chagin 
146bfcce1a9SDmitry Chagin 	ltp64->tv_sec = ntp->tv_sec;
147bfcce1a9SDmitry Chagin 	ltp64->tv_nsec = ntp->tv_nsec;
148bfcce1a9SDmitry Chagin 
149bfcce1a9SDmitry Chagin 	return (0);
150bfcce1a9SDmitry Chagin }
151bfcce1a9SDmitry Chagin 
152bfcce1a9SDmitry Chagin int
153bfcce1a9SDmitry Chagin linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64)
154bfcce1a9SDmitry Chagin {
155bfcce1a9SDmitry Chagin 
156bfcce1a9SDmitry Chagin 	if (ltp64->tv_sec < 0 || ltp64->tv_nsec < 0 || ltp64->tv_nsec > 999999999)
157bfcce1a9SDmitry Chagin 		return (EINVAL);
158bfcce1a9SDmitry Chagin 	ntp->tv_sec = ltp64->tv_sec;
159bfcce1a9SDmitry Chagin 	ntp->tv_nsec = ltp64->tv_nsec;
160bfcce1a9SDmitry Chagin 
161bfcce1a9SDmitry Chagin 	return (0);
162bfcce1a9SDmitry Chagin }
163bfcce1a9SDmitry Chagin #endif
164bfcce1a9SDmitry Chagin 
16516ac71bcSDmitry Chagin int
166dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
167dd93b628SDmitry Chagin {
168dd93b628SDmitry Chagin 	int error;
169dd93b628SDmitry Chagin 
170dd93b628SDmitry Chagin 	error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
171dd93b628SDmitry Chagin 	if (error == 0)
172dd93b628SDmitry Chagin 		error = native_to_linux_timespec(&ltp->it_value, &ntp->it_interval);
173dd93b628SDmitry Chagin 	return (error);
174dd93b628SDmitry Chagin }
175dd93b628SDmitry Chagin 
176dd93b628SDmitry Chagin int
177dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
178dd93b628SDmitry Chagin {
179dd93b628SDmitry Chagin 	int error;
180dd93b628SDmitry Chagin 
181dd93b628SDmitry Chagin 	error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
182dd93b628SDmitry Chagin 	if (error == 0)
183dd93b628SDmitry Chagin 		error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
184dd93b628SDmitry Chagin 	return (error);
185dd93b628SDmitry Chagin }
186dd93b628SDmitry Chagin 
187dd93b628SDmitry Chagin int
188ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l)
189ad2056f2SAlexander Leidinger {
19019e252baSAlexander Leidinger 
1912711aba9SDmitry Chagin 	if (l < 0) {
1922711aba9SDmitry Chagin 		/* cpu-clock */
1932711aba9SDmitry Chagin 		if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
1942711aba9SDmitry Chagin 			return (EINVAL);
1952711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
1962711aba9SDmitry Chagin 			return (EINVAL);
1972711aba9SDmitry Chagin 
1982711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_PERTHREAD(l))
1992711aba9SDmitry Chagin 			*n = CLOCK_THREAD_CPUTIME_ID;
2002711aba9SDmitry Chagin 		else
2012711aba9SDmitry Chagin 			*n = CLOCK_PROCESS_CPUTIME_ID;
2022711aba9SDmitry Chagin 		return (0);
2032711aba9SDmitry Chagin 	}
2042711aba9SDmitry Chagin 
205ad2056f2SAlexander Leidinger 	switch (l) {
206ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_REALTIME:
207ad2056f2SAlexander Leidinger 		*n = CLOCK_REALTIME;
208ad2056f2SAlexander Leidinger 		break;
209ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC:
210ad2056f2SAlexander Leidinger 		*n = CLOCK_MONOTONIC;
211ad2056f2SAlexander Leidinger 		break;
2127bc05ae6SDmitry Chagin 	case LINUX_CLOCK_PROCESS_CPUTIME_ID:
2137bc05ae6SDmitry Chagin 		*n = CLOCK_PROCESS_CPUTIME_ID;
2147bc05ae6SDmitry Chagin 		break;
2157bc05ae6SDmitry Chagin 	case LINUX_CLOCK_THREAD_CPUTIME_ID:
2167bc05ae6SDmitry Chagin 		*n = CLOCK_THREAD_CPUTIME_ID;
2177bc05ae6SDmitry Chagin 		break;
2182711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_COARSE:
2192711aba9SDmitry Chagin 		*n = CLOCK_REALTIME_FAST;
2202711aba9SDmitry Chagin 		break;
2212711aba9SDmitry Chagin 	case LINUX_CLOCK_MONOTONIC_COARSE:
222e37db348SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC_RAW:
2232711aba9SDmitry Chagin 		*n = CLOCK_MONOTONIC_FAST;
2242711aba9SDmitry Chagin 		break;
2252711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME:
22625ada637SDmitry Chagin 		*n = CLOCK_UPTIME;
22725ada637SDmitry Chagin 		break;
2282711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_ALARM:
2292711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME_ALARM:
2302711aba9SDmitry Chagin 	case LINUX_CLOCK_SGI_CYCLE:
2312711aba9SDmitry Chagin 	case LINUX_CLOCK_TAI:
23219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
23319e252baSAlexander Leidinger 		    unsupported_clockid, l);
23419e252baSAlexander Leidinger 		return (EINVAL);
23577424f41SJung-uk Kim 	default:
23619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
23719e252baSAlexander Leidinger 		    unknown_clockid, l);
23877424f41SJung-uk Kim 		return (EINVAL);
239ad2056f2SAlexander Leidinger 	}
240ad2056f2SAlexander Leidinger 
24177424f41SJung-uk Kim 	return (0);
242ad2056f2SAlexander Leidinger }
243ad2056f2SAlexander Leidinger 
244ad2056f2SAlexander Leidinger int
245f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags)
246f0f58384SDmitry Chagin {
247f0f58384SDmitry Chagin 
248f0f58384SDmitry Chagin 	if (flags & ~LINUX_TIMER_ABSTIME)
249f0f58384SDmitry Chagin 		return (EINVAL);
250f0f58384SDmitry Chagin 	*nflags = 0;
251f0f58384SDmitry Chagin 	if (flags & LINUX_TIMER_ABSTIME)
252f0f58384SDmitry Chagin 		*nflags |= TIMER_ABSTIME;
253f0f58384SDmitry Chagin 	return (0);
254f0f58384SDmitry Chagin }
255f0f58384SDmitry Chagin 
25699b6f430SDmitry Chagin static int
25799b6f430SDmitry Chagin linux_common_clock_gettime(struct thread *td, clockid_t which,
25899b6f430SDmitry Chagin     struct timespec *tp)
259ad2056f2SAlexander Leidinger {
2602711aba9SDmitry Chagin 	struct rusage ru;
2612711aba9SDmitry Chagin 	struct thread *targettd;
2622711aba9SDmitry Chagin 	struct proc *p;
2632711aba9SDmitry Chagin 	int error, clockwhich;
2642506c761SDmitry Chagin 	clockid_t nwhich;
2652711aba9SDmitry Chagin 	pid_t pid;
2662711aba9SDmitry Chagin 	lwpid_t tid;
267ad2056f2SAlexander Leidinger 
26899b6f430SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
26919e252baSAlexander Leidinger 	if (error != 0) {
2704afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
27199b6f430SDmitry Chagin 		    "unsupported clock_gettime clockid %d", which);
27299b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_gettime,
27399b6f430SDmitry Chagin 		    conversion_error, error);
27477424f41SJung-uk Kim 		return (error);
27519e252baSAlexander Leidinger 	}
2762711aba9SDmitry Chagin 
2772711aba9SDmitry Chagin 	switch (nwhich) {
2782711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
27999b6f430SDmitry Chagin 		if (which < 0) {
28099b6f430SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_WHICH(which);
28199b6f430SDmitry Chagin 			pid = LINUX_CPUCLOCK_ID(which);
2827bc05ae6SDmitry Chagin 		} else {
2837bc05ae6SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_SCHED;
2847bc05ae6SDmitry Chagin 			pid = 0;
2857bc05ae6SDmitry Chagin 		}
2862711aba9SDmitry Chagin 		if (pid == 0) {
2872711aba9SDmitry Chagin 			p = td->td_proc;
2882711aba9SDmitry Chagin 			PROC_LOCK(p);
2892711aba9SDmitry Chagin 		} else {
2902711aba9SDmitry Chagin 			error = pget(pid, PGET_CANSEE, &p);
2912711aba9SDmitry Chagin 			if (error != 0)
2922711aba9SDmitry Chagin 				return (EINVAL);
2932711aba9SDmitry Chagin 		}
2942711aba9SDmitry Chagin 		switch (clockwhich) {
2952711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
2962711aba9SDmitry Chagin 			PROC_STATLOCK(p);
2972711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
2982711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
2992711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3002711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
30199b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3022711aba9SDmitry Chagin 			break;
3032711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
3042711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3052711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
3062711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3072711aba9SDmitry Chagin 			PROC_UNLOCK(p);
30899b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3092711aba9SDmitry Chagin 			break;
3102711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
31199b6f430SDmitry Chagin 			kern_process_cputime(p, tp);
3122711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3132711aba9SDmitry Chagin 			break;
3142711aba9SDmitry Chagin 		default:
3152711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3162711aba9SDmitry Chagin 			return (EINVAL);
3172711aba9SDmitry Chagin 		}
3182711aba9SDmitry Chagin 
3192711aba9SDmitry Chagin 		break;
3202711aba9SDmitry Chagin 
3212711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
32299b6f430SDmitry Chagin 		if (which < 0) {
32399b6f430SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_WHICH(which);
32499b6f430SDmitry Chagin 			tid = LINUX_CPUCLOCK_ID(which);
3257bc05ae6SDmitry Chagin 		} else {
3267bc05ae6SDmitry Chagin 			clockwhich = LINUX_CPUCLOCK_SCHED;
3277bc05ae6SDmitry Chagin 			tid = 0;
3287bc05ae6SDmitry Chagin 		}
3297bc05ae6SDmitry Chagin 		p = td->td_proc;
3302711aba9SDmitry Chagin 		if (tid == 0) {
3312711aba9SDmitry Chagin 			targettd = td;
3322711aba9SDmitry Chagin 			PROC_LOCK(p);
3332711aba9SDmitry Chagin 		} else {
3347bc05ae6SDmitry Chagin 			targettd = linux_tdfind(td, tid, p->p_pid);
3352711aba9SDmitry Chagin 			if (targettd == NULL)
3362711aba9SDmitry Chagin 				return (EINVAL);
3372711aba9SDmitry Chagin 		}
3382711aba9SDmitry Chagin 		switch (clockwhich) {
3392711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
3402711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3412711aba9SDmitry Chagin 			thread_lock(targettd);
3422711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
3432711aba9SDmitry Chagin 			thread_unlock(targettd);
3442711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3452711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3462711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
34799b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3482711aba9SDmitry Chagin 			break;
3492711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
3502711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3512711aba9SDmitry Chagin 			thread_lock(targettd);
3522711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
3532711aba9SDmitry Chagin 			thread_unlock(targettd);
3542711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3552711aba9SDmitry Chagin 			PROC_UNLOCK(p);
35699b6f430SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
3572711aba9SDmitry Chagin 			break;
3582711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
3597bc05ae6SDmitry Chagin 			if (td == targettd)
3607bc05ae6SDmitry Chagin 				targettd = NULL;
36199b6f430SDmitry Chagin 			kern_thread_cputime(targettd, tp);
3622711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3632711aba9SDmitry Chagin 			break;
3642711aba9SDmitry Chagin 		default:
3652711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3662711aba9SDmitry Chagin 			return (EINVAL);
3672711aba9SDmitry Chagin 		}
3682711aba9SDmitry Chagin 		break;
3692711aba9SDmitry Chagin 
3702711aba9SDmitry Chagin 	default:
37199b6f430SDmitry Chagin 		error = kern_clock_gettime(td, nwhich, tp);
3722711aba9SDmitry Chagin 		break;
3732711aba9SDmitry Chagin 	}
37499b6f430SDmitry Chagin 
37599b6f430SDmitry Chagin 	return (error);
37699b6f430SDmitry Chagin }
37799b6f430SDmitry Chagin 
37899b6f430SDmitry Chagin int
37999b6f430SDmitry Chagin linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
38099b6f430SDmitry Chagin {
38199b6f430SDmitry Chagin 	struct l_timespec lts;
38299b6f430SDmitry Chagin 	struct timespec tp;
38399b6f430SDmitry Chagin 	int error;
38499b6f430SDmitry Chagin 
38599b6f430SDmitry Chagin 	error = linux_common_clock_gettime(td, args->which, &tp);
38619e252baSAlexander Leidinger 	if (error != 0) {
38719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
38877424f41SJung-uk Kim 		return (error);
38919e252baSAlexander Leidinger 	}
3900670e972SDmitry Chagin 	error = native_to_linux_timespec(&lts, &tp);
3910670e972SDmitry Chagin 	if (error != 0)
3920670e972SDmitry Chagin 		return (error);
39399b6f430SDmitry Chagin 	error = copyout(&lts, args->tp, sizeof(lts));
39419e252baSAlexander Leidinger 	if (error != 0)
39519e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
39619e252baSAlexander Leidinger 
39719e252baSAlexander Leidinger 	return (error);
398ad2056f2SAlexander Leidinger }
399ad2056f2SAlexander Leidinger 
40099b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
40199b6f430SDmitry Chagin int
40299b6f430SDmitry Chagin linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args)
40399b6f430SDmitry Chagin {
40499b6f430SDmitry Chagin 	struct l_timespec64 lts;
40599b6f430SDmitry Chagin 	struct timespec tp;
40699b6f430SDmitry Chagin 	int error;
40799b6f430SDmitry Chagin 
40899b6f430SDmitry Chagin 	error = linux_common_clock_gettime(td, args->which, &tp);
40999b6f430SDmitry Chagin 	if (error != 0) {
41099b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error);
41199b6f430SDmitry Chagin 		return (error);
41299b6f430SDmitry Chagin 	}
41399b6f430SDmitry Chagin 	error = native_to_linux_timespec64(&lts, &tp);
41499b6f430SDmitry Chagin 	if (error != 0)
41599b6f430SDmitry Chagin 		return (error);
41699b6f430SDmitry Chagin 	error = copyout(&lts, args->tp, sizeof(lts));
41799b6f430SDmitry Chagin 	if (error != 0)
41899b6f430SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error);
41999b6f430SDmitry Chagin 
42099b6f430SDmitry Chagin 	return (error);
42199b6f430SDmitry Chagin }
42299b6f430SDmitry Chagin #endif
42399b6f430SDmitry Chagin 
424*19f9a0e4SDmitry Chagin static int
425*19f9a0e4SDmitry Chagin linux_common_clock_settime(struct thread *td, clockid_t which,
426*19f9a0e4SDmitry Chagin     struct timespec *ts)
427*19f9a0e4SDmitry Chagin {
428*19f9a0e4SDmitry Chagin 	int error;
429*19f9a0e4SDmitry Chagin 	clockid_t nwhich;
430*19f9a0e4SDmitry Chagin 
431*19f9a0e4SDmitry Chagin 	error = linux_to_native_clockid(&nwhich, which);
432*19f9a0e4SDmitry Chagin 	if (error != 0) {
433*19f9a0e4SDmitry Chagin 		linux_msg(curthread,
434*19f9a0e4SDmitry Chagin 		    "unsupported clock_settime clockid %d", which);
435*19f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error,
436*19f9a0e4SDmitry Chagin 		    error);
437*19f9a0e4SDmitry Chagin 		return (error);
438*19f9a0e4SDmitry Chagin 	}
439*19f9a0e4SDmitry Chagin 
440*19f9a0e4SDmitry Chagin 	error = kern_clock_settime(td, nwhich, ts);
441*19f9a0e4SDmitry Chagin 	if (error != 0)
442*19f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_common_clock_settime,
443*19f9a0e4SDmitry Chagin 		    settime_error, error);
444*19f9a0e4SDmitry Chagin 
445*19f9a0e4SDmitry Chagin 	return (error);
446*19f9a0e4SDmitry Chagin }
447*19f9a0e4SDmitry Chagin 
448ad2056f2SAlexander Leidinger int
449ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
450ad2056f2SAlexander Leidinger {
451ad2056f2SAlexander Leidinger 	struct timespec ts;
452ad2056f2SAlexander Leidinger 	struct l_timespec lts;
453ad2056f2SAlexander Leidinger 	int error;
454ad2056f2SAlexander Leidinger 
455*19f9a0e4SDmitry Chagin 	error = copyin(args->tp, &lts, sizeof(lts));
45619e252baSAlexander Leidinger 	if (error != 0) {
45719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
45819e252baSAlexander Leidinger 		return (error);
45919e252baSAlexander Leidinger 	}
46019e252baSAlexander Leidinger 	error = linux_to_native_timespec(&ts, &lts);
461*19f9a0e4SDmitry Chagin 	if (error != 0)
46219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
46319e252baSAlexander Leidinger 		    error);
464*19f9a0e4SDmitry Chagin 
465*19f9a0e4SDmitry Chagin 	return (linux_common_clock_settime(td, args->which, &ts));
46619e252baSAlexander Leidinger }
46719e252baSAlexander Leidinger 
468*19f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
469*19f9a0e4SDmitry Chagin int
470*19f9a0e4SDmitry Chagin linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args)
471*19f9a0e4SDmitry Chagin {
472*19f9a0e4SDmitry Chagin 	struct timespec ts;
473*19f9a0e4SDmitry Chagin 	struct l_timespec64 lts;
474*19f9a0e4SDmitry Chagin 	int error;
475*19f9a0e4SDmitry Chagin 
476*19f9a0e4SDmitry Chagin 	error = copyin(args->tp, &lts, sizeof(lts));
477*19f9a0e4SDmitry Chagin 	if (error != 0) {
478*19f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error);
479*19f9a0e4SDmitry Chagin 		return (error);
480*19f9a0e4SDmitry Chagin 	}
481*19f9a0e4SDmitry Chagin 	error = linux_to_native_timespec64(&ts, &lts);
48219e252baSAlexander Leidinger 	if (error != 0)
483*19f9a0e4SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_settime64, conversion_error,
484*19f9a0e4SDmitry Chagin 		    error);
485*19f9a0e4SDmitry Chagin 	return (linux_common_clock_settime(td, args->which, &ts));
486ad2056f2SAlexander Leidinger }
487*19f9a0e4SDmitry Chagin #endif
488ad2056f2SAlexander Leidinger 
489ad2056f2SAlexander Leidinger int
490ad2056f2SAlexander Leidinger linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
491ad2056f2SAlexander Leidinger {
4922711aba9SDmitry Chagin 	struct proc *p;
493ad2056f2SAlexander Leidinger 	struct timespec ts;
494ad2056f2SAlexander Leidinger 	struct l_timespec lts;
4952711aba9SDmitry Chagin 	int error, clockwhich;
4962506c761SDmitry Chagin 	clockid_t nwhich;
4972711aba9SDmitry Chagin 	pid_t pid;
4982711aba9SDmitry Chagin 	lwpid_t tid;
499ad2056f2SAlexander Leidinger 
500ad2056f2SAlexander Leidinger 	error = linux_to_native_clockid(&nwhich, args->which);
50119e252baSAlexander Leidinger 	if (error != 0) {
5024afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
5034afe4faeSEdward Tomasz Napierala 		    "unsupported clock_getres clockid %d", args->which);
50419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error,
50519e252baSAlexander Leidinger 		    error);
50677424f41SJung-uk Kim 		return (error);
50719e252baSAlexander Leidinger 	}
5082711aba9SDmitry Chagin 
5092711aba9SDmitry Chagin 	/*
5102711aba9SDmitry Chagin 	 * Check user supplied clock id in case of per-process
5112711aba9SDmitry Chagin 	 * or thread-specific cpu-time clock.
5122711aba9SDmitry Chagin 	 */
5137bc05ae6SDmitry Chagin 	if (args->which < 0) {
5142711aba9SDmitry Chagin 		switch (nwhich) {
5152711aba9SDmitry Chagin 		case CLOCK_THREAD_CPUTIME_ID:
5162711aba9SDmitry Chagin 			tid = LINUX_CPUCLOCK_ID(args->which);
5172711aba9SDmitry Chagin 			if (tid != 0) {
5182711aba9SDmitry Chagin 				p = td->td_proc;
5197bc05ae6SDmitry Chagin 				if (linux_tdfind(td, tid, p->p_pid) == NULL)
5207bc05ae6SDmitry Chagin 					return (EINVAL);
5212711aba9SDmitry Chagin 				PROC_UNLOCK(p);
5222711aba9SDmitry Chagin 			}
5232711aba9SDmitry Chagin 			break;
5242711aba9SDmitry Chagin 		case CLOCK_PROCESS_CPUTIME_ID:
5252711aba9SDmitry Chagin 			pid = LINUX_CPUCLOCK_ID(args->which);
5262711aba9SDmitry Chagin 			if (pid != 0) {
5272711aba9SDmitry Chagin 				error = pget(pid, PGET_CANSEE, &p);
5282711aba9SDmitry Chagin 				if (error != 0)
5292711aba9SDmitry Chagin 					return (EINVAL);
5302711aba9SDmitry Chagin 				PROC_UNLOCK(p);
5312711aba9SDmitry Chagin 			}
5322711aba9SDmitry Chagin 			break;
5332711aba9SDmitry Chagin 		}
5347bc05ae6SDmitry Chagin 	}
5352711aba9SDmitry Chagin 
5362711aba9SDmitry Chagin 	if (args->tp == NULL) {
5372711aba9SDmitry Chagin 		LIN_SDT_PROBE0(time, linux_clock_getres, nullcall);
5382711aba9SDmitry Chagin 		return (0);
5392711aba9SDmitry Chagin 	}
5402711aba9SDmitry Chagin 
5412711aba9SDmitry Chagin 	switch (nwhich) {
5422711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
5432711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
5442711aba9SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
5457bc05ae6SDmitry Chagin 		/*
5467bc05ae6SDmitry Chagin 		 * In both cases (when the clock id obtained by a call to
5477bc05ae6SDmitry Chagin 		 * clock_getcpuclockid() or using the clock
5487bc05ae6SDmitry Chagin 		 * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision
5497bc05ae6SDmitry Chagin 		 * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock.
5507bc05ae6SDmitry Chagin 		 *
5517bc05ae6SDmitry Chagin 		 * See Linux posix_cpu_clock_getres() implementation.
5527bc05ae6SDmitry Chagin 		 */
5537bc05ae6SDmitry Chagin 		if (args->which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) {
5547bc05ae6SDmitry Chagin 			ts.tv_sec = 0;
5557bc05ae6SDmitry Chagin 			ts.tv_nsec = 1;
5567bc05ae6SDmitry Chagin 			goto out;
5577bc05ae6SDmitry Chagin 		}
5587bc05ae6SDmitry Chagin 
5592711aba9SDmitry Chagin 		switch (clockwhich) {
5602711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
5612711aba9SDmitry Chagin 			nwhich = CLOCK_PROF;
5622711aba9SDmitry Chagin 			break;
5632711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
5642711aba9SDmitry Chagin 			nwhich = CLOCK_VIRTUAL;
5652711aba9SDmitry Chagin 			break;
5662711aba9SDmitry Chagin 		default:
5672711aba9SDmitry Chagin 			return (EINVAL);
5682711aba9SDmitry Chagin 		}
5692711aba9SDmitry Chagin 		break;
5702711aba9SDmitry Chagin 
5712711aba9SDmitry Chagin 	default:
5722711aba9SDmitry Chagin 		break;
5732711aba9SDmitry Chagin 	}
574ad2056f2SAlexander Leidinger 	error = kern_clock_getres(td, nwhich, &ts);
57519e252baSAlexander Leidinger 	if (error != 0) {
57619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error);
57777424f41SJung-uk Kim 		return (error);
57819e252baSAlexander Leidinger 	}
5797bc05ae6SDmitry Chagin 
5807bc05ae6SDmitry Chagin out:
5810670e972SDmitry Chagin 	error = native_to_linux_timespec(&lts, &ts);
5820670e972SDmitry Chagin 	if (error != 0)
5830670e972SDmitry Chagin 		return (error);
58419e252baSAlexander Leidinger 	error = copyout(&lts, args->tp, sizeof lts);
58519e252baSAlexander Leidinger 	if (error != 0)
58619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
58719e252baSAlexander Leidinger 
58819e252baSAlexander Leidinger 	return (error);
58977424f41SJung-uk Kim }
59077424f41SJung-uk Kim 
59177424f41SJung-uk Kim int
59277424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
59377424f41SJung-uk Kim {
59477424f41SJung-uk Kim 	struct timespec *rmtp;
59577424f41SJung-uk Kim 	struct l_timespec lrqts, lrmts;
59677424f41SJung-uk Kim 	struct timespec rqts, rmts;
5975c2748d5SDmitry Chagin 	int error, error2;
59877424f41SJung-uk Kim 
59977424f41SJung-uk Kim 	error = copyin(args->rqtp, &lrqts, sizeof lrqts);
60019e252baSAlexander Leidinger 	if (error != 0) {
60119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
60277424f41SJung-uk Kim 		return (error);
60319e252baSAlexander Leidinger 	}
60477424f41SJung-uk Kim 
60577424f41SJung-uk Kim 	if (args->rmtp != NULL)
60677424f41SJung-uk Kim 		rmtp = &rmts;
60777424f41SJung-uk Kim 	else
60877424f41SJung-uk Kim 		rmtp = NULL;
60977424f41SJung-uk Kim 
61077424f41SJung-uk Kim 	error = linux_to_native_timespec(&rqts, &lrqts);
61119e252baSAlexander Leidinger 	if (error != 0) {
61219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
61377424f41SJung-uk Kim 		return (error);
61419e252baSAlexander Leidinger 	}
61577424f41SJung-uk Kim 	error = kern_nanosleep(td, &rqts, rmtp);
6164cf66812SEric van Gyzen 	if (error == EINTR && args->rmtp != NULL) {
6170670e972SDmitry Chagin 		error2 = native_to_linux_timespec(&lrmts, rmtp);
6180670e972SDmitry Chagin 		if (error2 != 0)
6190670e972SDmitry Chagin 			return (error2);
6205c2748d5SDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
6215c2748d5SDmitry Chagin 		if (error2 != 0) {
62219e252baSAlexander Leidinger 			LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
6235c2748d5SDmitry Chagin 			    error2);
6245c2748d5SDmitry Chagin 			return (error2);
62577424f41SJung-uk Kim 		}
62619e252baSAlexander Leidinger 	}
62777424f41SJung-uk Kim 
6285c2748d5SDmitry Chagin 	return (error);
629ad2056f2SAlexander Leidinger }
630ad2056f2SAlexander Leidinger 
631ad2056f2SAlexander Leidinger int
632ad2056f2SAlexander Leidinger linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args)
633ad2056f2SAlexander Leidinger {
634ad2056f2SAlexander Leidinger 	struct timespec *rmtp;
635ad2056f2SAlexander Leidinger 	struct l_timespec lrqts, lrmts;
636ad2056f2SAlexander Leidinger 	struct timespec rqts, rmts;
637f0f58384SDmitry Chagin 	int error, error2, flags;
638f0f58384SDmitry Chagin 	clockid_t clockid;
639ad2056f2SAlexander Leidinger 
640f0f58384SDmitry Chagin 	error = linux_to_native_timerflags(&flags, args->flags);
641f0f58384SDmitry Chagin 	if (error != 0) {
64219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags,
64319e252baSAlexander Leidinger 		    args->flags);
644f0f58384SDmitry Chagin 		return (error);
64519e252baSAlexander Leidinger 	}
64619e252baSAlexander Leidinger 
647f0f58384SDmitry Chagin 	error = linux_to_native_clockid(&clockid, args->which);
648f0f58384SDmitry Chagin 	if (error != 0) {
6494afe4faeSEdward Tomasz Napierala 		linux_msg(curthread,
6504afe4faeSEdward Tomasz Napierala 		    "unsupported clock_nanosleep clockid %d", args->which);
65119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid,
65219e252baSAlexander Leidinger 		    args->which);
653f0f58384SDmitry Chagin 		return (error);
65419e252baSAlexander Leidinger 	}
655ad2056f2SAlexander Leidinger 
6565c2748d5SDmitry Chagin 	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
65719e252baSAlexander Leidinger 	if (error != 0) {
65819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
65919e252baSAlexander Leidinger 		    error);
66077424f41SJung-uk Kim 		return (error);
66119e252baSAlexander Leidinger 	}
662ad2056f2SAlexander Leidinger 
663ad2056f2SAlexander Leidinger 	if (args->rmtp != NULL)
664ad2056f2SAlexander Leidinger 		rmtp = &rmts;
665ad2056f2SAlexander Leidinger 	else
666ad2056f2SAlexander Leidinger 		rmtp = NULL;
667ad2056f2SAlexander Leidinger 
66877424f41SJung-uk Kim 	error = linux_to_native_timespec(&rqts, &lrqts);
66919e252baSAlexander Leidinger 	if (error != 0) {
67019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
67119e252baSAlexander Leidinger 		    error);
67277424f41SJung-uk Kim 		return (error);
67319e252baSAlexander Leidinger 	}
674f0f58384SDmitry Chagin 	error = kern_clock_nanosleep(td, clockid, flags, &rqts, rmtp);
675f0f58384SDmitry Chagin 	if (error == EINTR && (flags & TIMER_ABSTIME) == 0 &&
676f0f58384SDmitry Chagin 	    args->rmtp != NULL) {
6770670e972SDmitry Chagin 		error2 = native_to_linux_timespec(&lrmts, rmtp);
6780670e972SDmitry Chagin 		if (error2 != 0)
6790670e972SDmitry Chagin 			return (error2);
6805c2748d5SDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
6815c2748d5SDmitry Chagin 		if (error2 != 0) {
6825c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
6835c2748d5SDmitry Chagin 			    copyout_error, error2);
6845c2748d5SDmitry Chagin 			return (error2);
6855c2748d5SDmitry Chagin 		}
6865c2748d5SDmitry Chagin 	}
6875c2748d5SDmitry Chagin 
68877424f41SJung-uk Kim 	return (error);
68919e252baSAlexander Leidinger }
690