xref: /freebsd/sys/compat/linux/linux_time.c (revision 2506c76121da2863fb10de5b194b4e65b6c382b5)
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>
682711aba9SDmitry Chagin #include <compat/linux/linux_timer.h>
6919e252baSAlexander Leidinger 
7019e252baSAlexander Leidinger /* DTrace init */
7119e252baSAlexander Leidinger LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
7219e252baSAlexander Leidinger 
7319e252baSAlexander Leidinger /**
7419e252baSAlexander Leidinger  * DTrace probes in this module.
7519e252baSAlexander Leidinger  */
7619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, native_to_linux_timespec, entry,
7719e252baSAlexander Leidinger     "struct l_timespec *", "struct timespec *");
7819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return);
7919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry,
8019e252baSAlexander Leidinger     "struct timespec *", "struct l_timespec *");
8119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int");
8219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *",
8319e252baSAlexander Leidinger     "clockid_t");
8419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
8519e252baSAlexander Leidinger     "clockid_t");
8619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
8719e252baSAlexander Leidinger     "clockid_t");
8819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int");
8919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t",
9019e252baSAlexander Leidinger     "struct l_timespec *");
9119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int");
9219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
9319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
9419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int");
9519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t",
9619e252baSAlexander Leidinger     "struct l_timespec *");
9719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
9819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int");
9919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
10019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int");
10119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t",
10219e252baSAlexander Leidinger     "struct l_timespec *");
10319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall);
10419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int");
10519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int");
10619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
10719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int");
10819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *",
10919e252baSAlexander Leidinger     "struct l_timespec *");
11019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
11119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
11219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
11319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int");
11419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int",
11519e252baSAlexander Leidinger     "struct l_timespec *", "struct l_timespec *");
11619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
11719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
11819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
11919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int");
12019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
12119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int");
12219e252baSAlexander Leidinger 
12368098228SDmitry Chagin 
1240670e972SDmitry Chagin int
125ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
126ad2056f2SAlexander Leidinger {
12719e252baSAlexander Leidinger 
12819e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp);
1290670e972SDmitry Chagin #ifdef COMPAT_LINUX32
13071b50d08SDmitry Chagin 	if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN)
1310670e972SDmitry Chagin 		return (EOVERFLOW);
1320670e972SDmitry Chagin #endif
133ad2056f2SAlexander Leidinger 	ltp->tv_sec = ntp->tv_sec;
134ad2056f2SAlexander Leidinger 	ltp->tv_nsec = ntp->tv_nsec;
13519e252baSAlexander Leidinger 
13619e252baSAlexander Leidinger 	LIN_SDT_PROBE0(time, native_to_linux_timespec, return);
1370670e972SDmitry Chagin 	return (0);
138ad2056f2SAlexander Leidinger }
139ad2056f2SAlexander Leidinger 
14068098228SDmitry Chagin int
141ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
142ad2056f2SAlexander Leidinger {
14319e252baSAlexander Leidinger 
14419e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp);
14519e252baSAlexander Leidinger 
1462ac9dcedSDmitry Chagin 	if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999) {
14719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL);
14877424f41SJung-uk Kim 		return (EINVAL);
14919e252baSAlexander Leidinger 	}
150ad2056f2SAlexander Leidinger 	ntp->tv_sec = ltp->tv_sec;
151ad2056f2SAlexander Leidinger 	ntp->tv_nsec = ltp->tv_nsec;
15277424f41SJung-uk Kim 
15319e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0);
15477424f41SJung-uk Kim 	return (0);
155ad2056f2SAlexander Leidinger }
156ad2056f2SAlexander Leidinger 
15716ac71bcSDmitry Chagin int
158dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
159dd93b628SDmitry Chagin {
160dd93b628SDmitry Chagin 	int error;
161dd93b628SDmitry Chagin 
162dd93b628SDmitry Chagin 	error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
163dd93b628SDmitry Chagin 	if (error == 0)
164dd93b628SDmitry Chagin 		error = native_to_linux_timespec(&ltp->it_value, &ntp->it_interval);
165dd93b628SDmitry Chagin 	return (error);
166dd93b628SDmitry Chagin }
167dd93b628SDmitry Chagin 
168dd93b628SDmitry Chagin int
169dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
170dd93b628SDmitry Chagin {
171dd93b628SDmitry Chagin 	int error;
172dd93b628SDmitry Chagin 
173dd93b628SDmitry Chagin 	error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
174dd93b628SDmitry Chagin 	if (error == 0)
175dd93b628SDmitry Chagin 		error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
176dd93b628SDmitry Chagin 	return (error);
177dd93b628SDmitry Chagin }
178dd93b628SDmitry Chagin 
179dd93b628SDmitry Chagin int
180ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l)
181ad2056f2SAlexander Leidinger {
18219e252baSAlexander Leidinger 
18319e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l);
18419e252baSAlexander Leidinger 
1852711aba9SDmitry Chagin 	if (l < 0) {
1862711aba9SDmitry Chagin 		/* cpu-clock */
1872711aba9SDmitry Chagin 		if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
1882711aba9SDmitry Chagin 			return (EINVAL);
1892711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
1902711aba9SDmitry Chagin 			return (EINVAL);
1912711aba9SDmitry Chagin 
1922711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_PERTHREAD(l))
1932711aba9SDmitry Chagin 			*n = CLOCK_THREAD_CPUTIME_ID;
1942711aba9SDmitry Chagin 		else
1952711aba9SDmitry Chagin 			*n = CLOCK_PROCESS_CPUTIME_ID;
1962711aba9SDmitry Chagin 		return (0);
1972711aba9SDmitry Chagin 	}
1982711aba9SDmitry Chagin 
199ad2056f2SAlexander Leidinger 	switch (l) {
200ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_REALTIME:
201ad2056f2SAlexander Leidinger 		*n = CLOCK_REALTIME;
202ad2056f2SAlexander Leidinger 		break;
203ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC:
204ad2056f2SAlexander Leidinger 		*n = CLOCK_MONOTONIC;
205ad2056f2SAlexander Leidinger 		break;
2062711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_COARSE:
2072711aba9SDmitry Chagin 		*n = CLOCK_REALTIME_FAST;
2082711aba9SDmitry Chagin 		break;
2092711aba9SDmitry Chagin 	case LINUX_CLOCK_MONOTONIC_COARSE:
2102711aba9SDmitry Chagin 		*n = CLOCK_MONOTONIC_FAST;
2112711aba9SDmitry Chagin 		break;
2122711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME:
21325ada637SDmitry Chagin 		*n = CLOCK_UPTIME;
21425ada637SDmitry Chagin 		break;
21525ada637SDmitry Chagin 	case LINUX_CLOCK_MONOTONIC_RAW:
2162711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_ALARM:
2172711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME_ALARM:
2182711aba9SDmitry Chagin 	case LINUX_CLOCK_SGI_CYCLE:
2192711aba9SDmitry Chagin 	case LINUX_CLOCK_TAI:
22019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
22119e252baSAlexander Leidinger 		    unsupported_clockid, l);
22219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
22319e252baSAlexander Leidinger 		return (EINVAL);
22477424f41SJung-uk Kim 	default:
22519e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
22619e252baSAlexander Leidinger 		    unknown_clockid, l);
22719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
22877424f41SJung-uk Kim 		return (EINVAL);
229ad2056f2SAlexander Leidinger 	}
230ad2056f2SAlexander Leidinger 
23119e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0);
23277424f41SJung-uk Kim 	return (0);
233ad2056f2SAlexander Leidinger }
234ad2056f2SAlexander Leidinger 
235ad2056f2SAlexander Leidinger int
236f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags)
237f0f58384SDmitry Chagin {
238f0f58384SDmitry Chagin 
239f0f58384SDmitry Chagin 	if (flags & ~LINUX_TIMER_ABSTIME)
240f0f58384SDmitry Chagin 		return (EINVAL);
241f0f58384SDmitry Chagin 	*nflags = 0;
242f0f58384SDmitry Chagin 	if (flags & LINUX_TIMER_ABSTIME)
243f0f58384SDmitry Chagin 		*nflags |= TIMER_ABSTIME;
244f0f58384SDmitry Chagin 	return (0);
245f0f58384SDmitry Chagin }
246f0f58384SDmitry Chagin 
247f0f58384SDmitry Chagin int
248ad2056f2SAlexander Leidinger linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
249ad2056f2SAlexander Leidinger {
250ad2056f2SAlexander Leidinger 	struct l_timespec lts;
251ad2056f2SAlexander Leidinger 	struct timespec tp;
2522711aba9SDmitry Chagin 	struct rusage ru;
2532711aba9SDmitry Chagin 	struct thread *targettd;
2542711aba9SDmitry Chagin 	struct proc *p;
2552711aba9SDmitry Chagin 	int error, clockwhich;
256*2506c761SDmitry Chagin 	clockid_t nwhich;
2572711aba9SDmitry Chagin 	pid_t pid;
2582711aba9SDmitry Chagin 	lwpid_t tid;
259ad2056f2SAlexander Leidinger 
26019e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp);
26119e252baSAlexander Leidinger 
262ad2056f2SAlexander Leidinger 	error = linux_to_native_clockid(&nwhich, args->which);
26319e252baSAlexander Leidinger 	if (error != 0) {
26419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error,
26519e252baSAlexander Leidinger 		    error);
26619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
26777424f41SJung-uk Kim 		return (error);
26819e252baSAlexander Leidinger 	}
2692711aba9SDmitry Chagin 
2702711aba9SDmitry Chagin 	switch (nwhich) {
2712711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
2722711aba9SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
2732711aba9SDmitry Chagin 		pid = LINUX_CPUCLOCK_ID(args->which);
2742711aba9SDmitry Chagin 		if (pid == 0) {
2752711aba9SDmitry Chagin 			p = td->td_proc;
2762711aba9SDmitry Chagin 			PROC_LOCK(p);
2772711aba9SDmitry Chagin 		} else {
2782711aba9SDmitry Chagin 			error = pget(pid, PGET_CANSEE, &p);
2792711aba9SDmitry Chagin 			if (error != 0)
2802711aba9SDmitry Chagin 				return (EINVAL);
2812711aba9SDmitry Chagin 		}
2822711aba9SDmitry Chagin 		switch (clockwhich) {
2832711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
2842711aba9SDmitry Chagin 			PROC_STATLOCK(p);
2852711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
2862711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
2872711aba9SDmitry Chagin 			PROC_UNLOCK(p);
2882711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
2892711aba9SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
2902711aba9SDmitry Chagin 			break;
2912711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
2922711aba9SDmitry Chagin 			PROC_STATLOCK(p);
2932711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
2942711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
2952711aba9SDmitry Chagin 			PROC_UNLOCK(p);
2962711aba9SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
2972711aba9SDmitry Chagin 			break;
2982711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
2992711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3002711aba9SDmitry Chagin 			error = kern_clock_getcpuclockid2(td, pid,
3012711aba9SDmitry Chagin 			    CPUCLOCK_WHICH_PID, &nwhich);
3022711aba9SDmitry Chagin 			if (error != 0)
3032711aba9SDmitry Chagin 				return (EINVAL);
304ad2056f2SAlexander Leidinger 			error = kern_clock_gettime(td, nwhich, &tp);
3052711aba9SDmitry Chagin 			break;
3062711aba9SDmitry Chagin 		default:
3072711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3082711aba9SDmitry Chagin 			return (EINVAL);
3092711aba9SDmitry Chagin 		}
3102711aba9SDmitry Chagin 
3112711aba9SDmitry Chagin 		break;
3122711aba9SDmitry Chagin 
3132711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
3142711aba9SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
3152711aba9SDmitry Chagin 		p = td->td_proc;
3162711aba9SDmitry Chagin 		tid = LINUX_CPUCLOCK_ID(args->which);
3172711aba9SDmitry Chagin 		if (tid == 0) {
3182711aba9SDmitry Chagin 			targettd = td;
3192711aba9SDmitry Chagin 			PROC_LOCK(p);
3202711aba9SDmitry Chagin 		} else {
3212711aba9SDmitry Chagin 			targettd = tdfind(tid, p->p_pid);
3222711aba9SDmitry Chagin 			if (targettd == NULL)
3232711aba9SDmitry Chagin 				return (EINVAL);
3242711aba9SDmitry Chagin 		}
3252711aba9SDmitry Chagin 		switch (clockwhich) {
3262711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
3272711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3282711aba9SDmitry Chagin 			thread_lock(targettd);
3292711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
3302711aba9SDmitry Chagin 			thread_unlock(targettd);
3312711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3322711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3332711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
3342711aba9SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
3352711aba9SDmitry Chagin 			break;
3362711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
3372711aba9SDmitry Chagin 			PROC_STATLOCK(p);
3382711aba9SDmitry Chagin 			thread_lock(targettd);
3392711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
3402711aba9SDmitry Chagin 			thread_unlock(targettd);
3412711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
3422711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3432711aba9SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
3442711aba9SDmitry Chagin 			break;
3452711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
3462711aba9SDmitry Chagin 			error = kern_clock_getcpuclockid2(td, tid,
3472711aba9SDmitry Chagin 			    CPUCLOCK_WHICH_TID, &nwhich);
3482711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3492711aba9SDmitry Chagin 			if (error != 0)
3502711aba9SDmitry Chagin 				return (EINVAL);
3512711aba9SDmitry Chagin 			error = kern_clock_gettime(td, nwhich, &tp);
3522711aba9SDmitry Chagin 			break;
3532711aba9SDmitry Chagin 		default:
3542711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3552711aba9SDmitry Chagin 			return (EINVAL);
3562711aba9SDmitry Chagin 		}
3572711aba9SDmitry Chagin 		break;
3582711aba9SDmitry Chagin 
3592711aba9SDmitry Chagin 	default:
3602711aba9SDmitry Chagin 		error = kern_clock_gettime(td, nwhich, &tp);
3612711aba9SDmitry Chagin 		break;
3622711aba9SDmitry Chagin 	}
36319e252baSAlexander Leidinger 	if (error != 0) {
36419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
36519e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
36677424f41SJung-uk Kim 		return (error);
36719e252baSAlexander Leidinger 	}
3680670e972SDmitry Chagin 	error = native_to_linux_timespec(&lts, &tp);
3690670e972SDmitry Chagin 	if (error != 0)
3700670e972SDmitry Chagin 		return (error);
37119e252baSAlexander Leidinger 	error = copyout(&lts, args->tp, sizeof lts);
37219e252baSAlexander Leidinger 	if (error != 0)
37319e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
37419e252baSAlexander Leidinger 
37519e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
37619e252baSAlexander Leidinger 	return (error);
377ad2056f2SAlexander Leidinger }
378ad2056f2SAlexander Leidinger 
379ad2056f2SAlexander Leidinger int
380ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
381ad2056f2SAlexander Leidinger {
382ad2056f2SAlexander Leidinger 	struct timespec ts;
383ad2056f2SAlexander Leidinger 	struct l_timespec lts;
384ad2056f2SAlexander Leidinger 	int error;
385*2506c761SDmitry Chagin 	clockid_t nwhich;
386ad2056f2SAlexander Leidinger 
38719e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp);
388ad2056f2SAlexander Leidinger 
38919e252baSAlexander Leidinger 	error = linux_to_native_clockid(&nwhich, args->which);
39019e252baSAlexander Leidinger 	if (error != 0) {
39119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
39219e252baSAlexander Leidinger 		    error);
39319e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
39419e252baSAlexander Leidinger 		return (error);
39519e252baSAlexander Leidinger 	}
39619e252baSAlexander Leidinger 	error = copyin(args->tp, &lts, sizeof lts);
39719e252baSAlexander Leidinger 	if (error != 0) {
39819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
39919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
40019e252baSAlexander Leidinger 		return (error);
40119e252baSAlexander Leidinger 	}
40219e252baSAlexander Leidinger 	error = linux_to_native_timespec(&ts, &lts);
40319e252baSAlexander Leidinger 	if (error != 0) {
40419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
40519e252baSAlexander Leidinger 		    error);
40619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
40719e252baSAlexander Leidinger 		return (error);
40819e252baSAlexander Leidinger 	}
40919e252baSAlexander Leidinger 
41019e252baSAlexander Leidinger 	error = kern_clock_settime(td, nwhich, &ts);
41119e252baSAlexander Leidinger 	if (error != 0)
41219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error);
41319e252baSAlexander Leidinger 
41419e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
41519e252baSAlexander Leidinger 	return (error);
416ad2056f2SAlexander Leidinger }
417ad2056f2SAlexander Leidinger 
418ad2056f2SAlexander Leidinger int
419ad2056f2SAlexander Leidinger linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
420ad2056f2SAlexander Leidinger {
4212711aba9SDmitry Chagin 	struct proc *p;
422ad2056f2SAlexander Leidinger 	struct timespec ts;
423ad2056f2SAlexander Leidinger 	struct l_timespec lts;
4242711aba9SDmitry Chagin 	int error, clockwhich;
425*2506c761SDmitry Chagin 	clockid_t nwhich;
4262711aba9SDmitry Chagin 	pid_t pid;
4272711aba9SDmitry Chagin 	lwpid_t tid;
428ad2056f2SAlexander Leidinger 
42919e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp);
43019e252baSAlexander Leidinger 
431ad2056f2SAlexander Leidinger 	error = linux_to_native_clockid(&nwhich, args->which);
43219e252baSAlexander Leidinger 	if (error != 0) {
43319e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error,
43419e252baSAlexander Leidinger 		    error);
43519e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
43677424f41SJung-uk Kim 		return (error);
43719e252baSAlexander Leidinger 	}
4382711aba9SDmitry Chagin 
4392711aba9SDmitry Chagin 	/*
4402711aba9SDmitry Chagin 	 * Check user supplied clock id in case of per-process
4412711aba9SDmitry Chagin 	 * or thread-specific cpu-time clock.
4422711aba9SDmitry Chagin 	 */
4432711aba9SDmitry Chagin 	switch (nwhich) {
4442711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
4452711aba9SDmitry Chagin 		tid = LINUX_CPUCLOCK_ID(args->which);
4462711aba9SDmitry Chagin 		if (tid != 0) {
4472711aba9SDmitry Chagin 			p = td->td_proc;
4482711aba9SDmitry Chagin 			if (tdfind(tid, p->p_pid) == NULL)
4492711aba9SDmitry Chagin 				return (ESRCH);
4502711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4512711aba9SDmitry Chagin 		}
4522711aba9SDmitry Chagin 		break;
4532711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
4542711aba9SDmitry Chagin 		pid = LINUX_CPUCLOCK_ID(args->which);
4552711aba9SDmitry Chagin 		if (pid != 0) {
4562711aba9SDmitry Chagin 			error = pget(pid, PGET_CANSEE, &p);
4572711aba9SDmitry Chagin 			if (error != 0)
4582711aba9SDmitry Chagin 				return (EINVAL);
4592711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4602711aba9SDmitry Chagin 		}
4612711aba9SDmitry Chagin 		break;
4622711aba9SDmitry Chagin 	}
4632711aba9SDmitry Chagin 
4642711aba9SDmitry Chagin 	if (args->tp == NULL) {
4652711aba9SDmitry Chagin 		LIN_SDT_PROBE0(time, linux_clock_getres, nullcall);
4662711aba9SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_getres, return, 0);
4672711aba9SDmitry Chagin 		return (0);
4682711aba9SDmitry Chagin 	}
4692711aba9SDmitry Chagin 
4702711aba9SDmitry Chagin 	switch (nwhich) {
4712711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
4722711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
4732711aba9SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
4742711aba9SDmitry Chagin 		switch (clockwhich) {
4752711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
4762711aba9SDmitry Chagin 			nwhich = CLOCK_PROF;
4772711aba9SDmitry Chagin 			break;
4782711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
4792711aba9SDmitry Chagin 			nwhich = CLOCK_VIRTUAL;
4802711aba9SDmitry Chagin 			break;
4812711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
4822711aba9SDmitry Chagin 			break;
4832711aba9SDmitry Chagin 		default:
4842711aba9SDmitry Chagin 			return (EINVAL);
4852711aba9SDmitry Chagin 		}
4862711aba9SDmitry Chagin 		break;
4872711aba9SDmitry Chagin 
4882711aba9SDmitry Chagin 	default:
4892711aba9SDmitry Chagin 		break;
4902711aba9SDmitry Chagin 	}
491ad2056f2SAlexander Leidinger 	error = kern_clock_getres(td, nwhich, &ts);
49219e252baSAlexander Leidinger 	if (error != 0) {
49319e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error);
49419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
49577424f41SJung-uk Kim 		return (error);
49619e252baSAlexander Leidinger 	}
4970670e972SDmitry Chagin 	error = native_to_linux_timespec(&lts, &ts);
4980670e972SDmitry Chagin 	if (error != 0)
4990670e972SDmitry Chagin 		return (error);
50019e252baSAlexander Leidinger 	error = copyout(&lts, args->tp, sizeof lts);
50119e252baSAlexander Leidinger 	if (error != 0)
50219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
50319e252baSAlexander Leidinger 
50419e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
50519e252baSAlexander Leidinger 	return (error);
50677424f41SJung-uk Kim }
50777424f41SJung-uk Kim 
50877424f41SJung-uk Kim int
50977424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
51077424f41SJung-uk Kim {
51177424f41SJung-uk Kim 	struct timespec *rmtp;
51277424f41SJung-uk Kim 	struct l_timespec lrqts, lrmts;
51377424f41SJung-uk Kim 	struct timespec rqts, rmts;
5145c2748d5SDmitry Chagin 	int error, error2;
51577424f41SJung-uk Kim 
51619e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp);
51719e252baSAlexander Leidinger 
51877424f41SJung-uk Kim 	error = copyin(args->rqtp, &lrqts, sizeof lrqts);
51919e252baSAlexander Leidinger 	if (error != 0) {
52019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
52119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
52277424f41SJung-uk Kim 		return (error);
52319e252baSAlexander Leidinger 	}
52477424f41SJung-uk Kim 
52577424f41SJung-uk Kim 	if (args->rmtp != NULL)
52677424f41SJung-uk Kim 		rmtp = &rmts;
52777424f41SJung-uk Kim 	else
52877424f41SJung-uk Kim 		rmtp = NULL;
52977424f41SJung-uk Kim 
53077424f41SJung-uk Kim 	error = linux_to_native_timespec(&rqts, &lrqts);
53119e252baSAlexander Leidinger 	if (error != 0) {
53219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
53319e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
53477424f41SJung-uk Kim 		return (error);
53519e252baSAlexander Leidinger 	}
53677424f41SJung-uk Kim 	error = kern_nanosleep(td, &rqts, rmtp);
5374cf66812SEric van Gyzen 	if (error == EINTR && args->rmtp != NULL) {
5380670e972SDmitry Chagin 		error2 = native_to_linux_timespec(&lrmts, rmtp);
5390670e972SDmitry Chagin 		if (error2 != 0)
5400670e972SDmitry Chagin 			return (error2);
5415c2748d5SDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
5425c2748d5SDmitry Chagin 		if (error2 != 0) {
54319e252baSAlexander Leidinger 			LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
5445c2748d5SDmitry Chagin 			    error2);
5455c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_nanosleep, return, error2);
5465c2748d5SDmitry Chagin 			return (error2);
54777424f41SJung-uk Kim 		}
54819e252baSAlexander Leidinger 	}
54977424f41SJung-uk Kim 
5505c2748d5SDmitry Chagin 	LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
5515c2748d5SDmitry Chagin 	return (error);
552ad2056f2SAlexander Leidinger }
553ad2056f2SAlexander Leidinger 
554ad2056f2SAlexander Leidinger int
555ad2056f2SAlexander Leidinger linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args)
556ad2056f2SAlexander Leidinger {
557ad2056f2SAlexander Leidinger 	struct timespec *rmtp;
558ad2056f2SAlexander Leidinger 	struct l_timespec lrqts, lrmts;
559ad2056f2SAlexander Leidinger 	struct timespec rqts, rmts;
560f0f58384SDmitry Chagin 	int error, error2, flags;
561f0f58384SDmitry Chagin 	clockid_t clockid;
562ad2056f2SAlexander Leidinger 
56319e252baSAlexander Leidinger 	LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which,
56419e252baSAlexander Leidinger 	    args->flags, args->rqtp, args->rmtp);
565ad2056f2SAlexander Leidinger 
566f0f58384SDmitry Chagin 	error = linux_to_native_timerflags(&flags, args->flags);
567f0f58384SDmitry Chagin 	if (error != 0) {
56819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags,
56919e252baSAlexander Leidinger 		    args->flags);
570f0f58384SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
571f0f58384SDmitry Chagin 		return (error);
57219e252baSAlexander Leidinger 	}
57319e252baSAlexander Leidinger 
574f0f58384SDmitry Chagin 	error = linux_to_native_clockid(&clockid, args->which);
575f0f58384SDmitry Chagin 	if (error != 0) {
57619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid,
57719e252baSAlexander Leidinger 		    args->which);
578f0f58384SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
579f0f58384SDmitry Chagin 		return (error);
58019e252baSAlexander Leidinger 	}
581ad2056f2SAlexander Leidinger 
5825c2748d5SDmitry Chagin 	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
58319e252baSAlexander Leidinger 	if (error != 0) {
58419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
58519e252baSAlexander Leidinger 		    error);
58619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
58777424f41SJung-uk Kim 		return (error);
58819e252baSAlexander Leidinger 	}
589ad2056f2SAlexander Leidinger 
590ad2056f2SAlexander Leidinger 	if (args->rmtp != NULL)
591ad2056f2SAlexander Leidinger 		rmtp = &rmts;
592ad2056f2SAlexander Leidinger 	else
593ad2056f2SAlexander Leidinger 		rmtp = NULL;
594ad2056f2SAlexander Leidinger 
59577424f41SJung-uk Kim 	error = linux_to_native_timespec(&rqts, &lrqts);
59619e252baSAlexander Leidinger 	if (error != 0) {
59719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
59819e252baSAlexander Leidinger 		    error);
59919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
60077424f41SJung-uk Kim 		return (error);
60119e252baSAlexander Leidinger 	}
602f0f58384SDmitry Chagin 	error = kern_clock_nanosleep(td, clockid, flags, &rqts, rmtp);
603f0f58384SDmitry Chagin 	if (error == EINTR && (flags & TIMER_ABSTIME) == 0 &&
604f0f58384SDmitry Chagin 	    args->rmtp != NULL) {
6050670e972SDmitry Chagin 		error2 = native_to_linux_timespec(&lrmts, rmtp);
6060670e972SDmitry Chagin 		if (error2 != 0)
6070670e972SDmitry Chagin 			return (error2);
6085c2748d5SDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
6095c2748d5SDmitry Chagin 		if (error2 != 0) {
6105c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
6115c2748d5SDmitry Chagin 			    copyout_error, error2);
6125c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
6135c2748d5SDmitry Chagin 			    return, error2);
6145c2748d5SDmitry Chagin 			return (error2);
6155c2748d5SDmitry Chagin 		}
6165c2748d5SDmitry Chagin 	}
6175c2748d5SDmitry Chagin 
61819e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
61977424f41SJung-uk Kim 	return (error);
62019e252baSAlexander Leidinger }
621