xref: /freebsd/sys/compat/linux/linux_time.c (revision 5c2748d5)
1ad2056f2SAlexander Leidinger /*	$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */
2ad2056f2SAlexander Leidinger 
3ad2056f2SAlexander Leidinger /*-
4ad2056f2SAlexander Leidinger  * Copyright (c) 2001 The NetBSD Foundation, Inc.
5ad2056f2SAlexander Leidinger  * All rights reserved.
6ad2056f2SAlexander Leidinger  *
7ad2056f2SAlexander Leidinger  * This code is derived from software contributed to The NetBSD Foundation
8ad2056f2SAlexander Leidinger  * by Emmanuel Dreyfus.
9ad2056f2SAlexander Leidinger  *
10ad2056f2SAlexander Leidinger  * Redistribution and use in source and binary forms, with or without
11ad2056f2SAlexander Leidinger  * modification, are permitted provided that the following conditions
12ad2056f2SAlexander Leidinger  * are met:
13ad2056f2SAlexander Leidinger  * 1. Redistributions of source code must retain the above copyright
14ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer.
15ad2056f2SAlexander Leidinger  * 2. Redistributions in binary form must reproduce the above copyright
16ad2056f2SAlexander Leidinger  *    notice, this list of conditions and the following disclaimer in the
17ad2056f2SAlexander Leidinger  *    documentation and/or other materials provided with the distribution.
18ad2056f2SAlexander Leidinger  *
19ad2056f2SAlexander Leidinger  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20ad2056f2SAlexander Leidinger  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21ad2056f2SAlexander Leidinger  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22ad2056f2SAlexander Leidinger  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23ad2056f2SAlexander Leidinger  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24ad2056f2SAlexander Leidinger  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25ad2056f2SAlexander Leidinger  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26ad2056f2SAlexander Leidinger  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27ad2056f2SAlexander Leidinger  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28ad2056f2SAlexander Leidinger  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29ad2056f2SAlexander Leidinger  * POSSIBILITY OF SUCH DAMAGE.
30ad2056f2SAlexander Leidinger  */
31ad2056f2SAlexander Leidinger 
32ad2056f2SAlexander Leidinger #include <sys/cdefs.h>
33ad2056f2SAlexander Leidinger __FBSDID("$FreeBSD$");
34ad2056f2SAlexander Leidinger #if 0
35ad2056f2SAlexander Leidinger __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $");
36ad2056f2SAlexander Leidinger #endif
37ad2056f2SAlexander Leidinger 
38ad2056f2SAlexander Leidinger #include "opt_compat.h"
39ad2056f2SAlexander Leidinger 
40ad2056f2SAlexander Leidinger #include <sys/param.h>
4119e252baSAlexander Leidinger #include <sys/kernel.h>
422711aba9SDmitry Chagin #include <sys/lock.h>
43ad2056f2SAlexander Leidinger #include <sys/ucred.h>
44ad2056f2SAlexander Leidinger #include <sys/mount.h>
452711aba9SDmitry Chagin #include <sys/mutex.h>
462711aba9SDmitry Chagin #include <sys/resourcevar.h>
4719e252baSAlexander Leidinger #include <sys/sdt.h>
48ad2056f2SAlexander Leidinger #include <sys/signal.h>
49ad2056f2SAlexander Leidinger #include <sys/stdint.h>
50ad2056f2SAlexander Leidinger #include <sys/syscallsubr.h>
51ad2056f2SAlexander Leidinger #include <sys/sysproto.h>
52ad2056f2SAlexander Leidinger #include <sys/time.h>
53ad2056f2SAlexander Leidinger #include <sys/systm.h>
54ad2056f2SAlexander Leidinger #include <sys/proc.h>
55ad2056f2SAlexander Leidinger 
56ad2056f2SAlexander Leidinger #ifdef COMPAT_LINUX32
57ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h>
58ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h>
59ad2056f2SAlexander Leidinger #else
60ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h>
61ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h>
62ad2056f2SAlexander Leidinger #endif
63ad2056f2SAlexander Leidinger 
6419e252baSAlexander Leidinger #include <compat/linux/linux_dtrace.h>
652711aba9SDmitry Chagin #include <compat/linux/linux_timer.h>
6619e252baSAlexander Leidinger 
6719e252baSAlexander Leidinger /* DTrace init */
6819e252baSAlexander Leidinger LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
6919e252baSAlexander Leidinger 
7019e252baSAlexander Leidinger /**
7119e252baSAlexander Leidinger  * DTrace probes in this module.
7219e252baSAlexander Leidinger  */
7319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, native_to_linux_timespec, entry,
7419e252baSAlexander Leidinger     "struct l_timespec *", "struct timespec *");
7519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return);
7619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry,
7719e252baSAlexander Leidinger     "struct timespec *", "struct l_timespec *");
7819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int");
7919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *",
8019e252baSAlexander Leidinger     "clockid_t");
8119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
8219e252baSAlexander Leidinger     "clockid_t");
8319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
8419e252baSAlexander Leidinger     "clockid_t");
8519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int");
8619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t",
8719e252baSAlexander Leidinger     "struct l_timespec *");
8819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int");
8919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
9019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
9119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int");
9219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t",
9319e252baSAlexander Leidinger     "struct l_timespec *");
9419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
9519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int");
9619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
9719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int");
9819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t",
9919e252baSAlexander Leidinger     "struct l_timespec *");
10019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall);
10119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int");
10219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int");
10319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
10419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int");
10519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *",
10619e252baSAlexander Leidinger     "struct l_timespec *");
10719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
10819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
10919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
11019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int");
11119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int",
11219e252baSAlexander Leidinger     "struct l_timespec *", "struct l_timespec *");
11319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
11419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
11519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
11619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int");
11719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
11819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int");
11919e252baSAlexander Leidinger 
12068098228SDmitry Chagin 
12168098228SDmitry Chagin void
122ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
123ad2056f2SAlexander Leidinger {
12419e252baSAlexander Leidinger 
12519e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp);
12619e252baSAlexander Leidinger 
127ad2056f2SAlexander Leidinger 	ltp->tv_sec = ntp->tv_sec;
128ad2056f2SAlexander Leidinger 	ltp->tv_nsec = ntp->tv_nsec;
12919e252baSAlexander Leidinger 
13019e252baSAlexander Leidinger 	LIN_SDT_PROBE0(time, native_to_linux_timespec, return);
131ad2056f2SAlexander Leidinger }
132ad2056f2SAlexander Leidinger 
13368098228SDmitry Chagin int
134ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
135ad2056f2SAlexander Leidinger {
13619e252baSAlexander Leidinger 
13719e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp);
13819e252baSAlexander Leidinger 
13919e252baSAlexander Leidinger 	if (ltp->tv_sec < 0 || ltp->tv_nsec > (l_long)999999999L) {
14019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL);
14177424f41SJung-uk Kim 		return (EINVAL);
14219e252baSAlexander Leidinger 	}
143ad2056f2SAlexander Leidinger 	ntp->tv_sec = ltp->tv_sec;
144ad2056f2SAlexander Leidinger 	ntp->tv_nsec = ltp->tv_nsec;
14577424f41SJung-uk Kim 
14619e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0);
14777424f41SJung-uk Kim 	return (0);
148ad2056f2SAlexander Leidinger }
149ad2056f2SAlexander Leidinger 
15016ac71bcSDmitry Chagin int
151ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l)
152ad2056f2SAlexander Leidinger {
15319e252baSAlexander Leidinger 
15419e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l);
15519e252baSAlexander Leidinger 
1562711aba9SDmitry Chagin 	if (l < 0) {
1572711aba9SDmitry Chagin 		/* cpu-clock */
1582711aba9SDmitry Chagin 		if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
1592711aba9SDmitry Chagin 			return (EINVAL);
1602711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
1612711aba9SDmitry Chagin 			return (EINVAL);
1622711aba9SDmitry Chagin 
1632711aba9SDmitry Chagin 		if (LINUX_CPUCLOCK_PERTHREAD(l))
1642711aba9SDmitry Chagin 			*n = CLOCK_THREAD_CPUTIME_ID;
1652711aba9SDmitry Chagin 		else
1662711aba9SDmitry Chagin 			*n = CLOCK_PROCESS_CPUTIME_ID;
1672711aba9SDmitry Chagin 		return (0);
1682711aba9SDmitry Chagin 	}
1692711aba9SDmitry Chagin 
170ad2056f2SAlexander Leidinger 	switch (l) {
171ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_REALTIME:
172ad2056f2SAlexander Leidinger 		*n = CLOCK_REALTIME;
173ad2056f2SAlexander Leidinger 		break;
174ad2056f2SAlexander Leidinger 	case LINUX_CLOCK_MONOTONIC:
175ad2056f2SAlexander Leidinger 		*n = CLOCK_MONOTONIC;
176ad2056f2SAlexander Leidinger 		break;
1772711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_COARSE:
1782711aba9SDmitry Chagin 		*n = CLOCK_REALTIME_FAST;
1792711aba9SDmitry Chagin 		break;
1802711aba9SDmitry Chagin 	case LINUX_CLOCK_MONOTONIC_COARSE:
1812711aba9SDmitry Chagin 		*n = CLOCK_MONOTONIC_FAST;
1822711aba9SDmitry Chagin 		break;
1832711aba9SDmitry Chagin 	case LINUX_CLOCK_MONOTONIC_RAW:
1842711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME:
1852711aba9SDmitry Chagin 	case LINUX_CLOCK_REALTIME_ALARM:
1862711aba9SDmitry Chagin 	case LINUX_CLOCK_BOOTTIME_ALARM:
1872711aba9SDmitry Chagin 	case LINUX_CLOCK_SGI_CYCLE:
1882711aba9SDmitry Chagin 	case LINUX_CLOCK_TAI:
18919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
19019e252baSAlexander Leidinger 		    unsupported_clockid, l);
19119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
19219e252baSAlexander Leidinger 		return (EINVAL);
19377424f41SJung-uk Kim 	default:
19419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid,
19519e252baSAlexander Leidinger 		    unknown_clockid, l);
19619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
19777424f41SJung-uk Kim 		return (EINVAL);
198ad2056f2SAlexander Leidinger 	}
199ad2056f2SAlexander Leidinger 
20019e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0);
20177424f41SJung-uk Kim 	return (0);
202ad2056f2SAlexander Leidinger }
203ad2056f2SAlexander Leidinger 
204ad2056f2SAlexander Leidinger int
205ad2056f2SAlexander Leidinger linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
206ad2056f2SAlexander Leidinger {
207ad2056f2SAlexander Leidinger 	struct l_timespec lts;
208ad2056f2SAlexander Leidinger 	struct timespec tp;
2092711aba9SDmitry Chagin 	struct rusage ru;
2102711aba9SDmitry Chagin 	struct thread *targettd;
2112711aba9SDmitry Chagin 	struct proc *p;
2122711aba9SDmitry Chagin 	int error, clockwhich;
2132711aba9SDmitry Chagin 	clockid_t nwhich = 0;	/* XXX: GCC */
2142711aba9SDmitry Chagin 	pid_t pid;
2152711aba9SDmitry Chagin 	lwpid_t tid;
216ad2056f2SAlexander Leidinger 
21719e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp);
21819e252baSAlexander Leidinger 
219ad2056f2SAlexander Leidinger 	error = linux_to_native_clockid(&nwhich, args->which);
22019e252baSAlexander Leidinger 	if (error != 0) {
22119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error,
22219e252baSAlexander Leidinger 		    error);
22319e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
22477424f41SJung-uk Kim 		return (error);
22519e252baSAlexander Leidinger 	}
2262711aba9SDmitry Chagin 
2272711aba9SDmitry Chagin 	switch (nwhich) {
2282711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
2292711aba9SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
2302711aba9SDmitry Chagin 		pid = LINUX_CPUCLOCK_ID(args->which);
2312711aba9SDmitry Chagin 		if (pid == 0) {
2322711aba9SDmitry Chagin 			p = td->td_proc;
2332711aba9SDmitry Chagin 			PROC_LOCK(p);
2342711aba9SDmitry Chagin 		} else {
2352711aba9SDmitry Chagin 			error = pget(pid, PGET_CANSEE, &p);
2362711aba9SDmitry Chagin 			if (error != 0)
2372711aba9SDmitry Chagin 				return (EINVAL);
2382711aba9SDmitry Chagin 		}
2392711aba9SDmitry Chagin 		switch (clockwhich) {
2402711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
2412711aba9SDmitry Chagin 			PROC_STATLOCK(p);
2422711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
2432711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
2442711aba9SDmitry Chagin 			PROC_UNLOCK(p);
2452711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
2462711aba9SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
2472711aba9SDmitry Chagin 			break;
2482711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
2492711aba9SDmitry Chagin 			PROC_STATLOCK(p);
2502711aba9SDmitry Chagin 			calcru(p, &ru.ru_utime, &ru.ru_stime);
2512711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
2522711aba9SDmitry Chagin 			PROC_UNLOCK(p);
2532711aba9SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
2542711aba9SDmitry Chagin 			break;
2552711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
2562711aba9SDmitry Chagin 			PROC_UNLOCK(p);
2572711aba9SDmitry Chagin 			error = kern_clock_getcpuclockid2(td, pid,
2582711aba9SDmitry Chagin 			    CPUCLOCK_WHICH_PID, &nwhich);
2592711aba9SDmitry Chagin 			if (error != 0)
2602711aba9SDmitry Chagin 				return (EINVAL);
261ad2056f2SAlexander Leidinger 			error = kern_clock_gettime(td, nwhich, &tp);
2622711aba9SDmitry Chagin 			break;
2632711aba9SDmitry Chagin 		default:
2642711aba9SDmitry Chagin 			PROC_UNLOCK(p);
2652711aba9SDmitry Chagin 			return (EINVAL);
2662711aba9SDmitry Chagin 		}
2672711aba9SDmitry Chagin 
2682711aba9SDmitry Chagin 		break;
2692711aba9SDmitry Chagin 
2702711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
2712711aba9SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
2722711aba9SDmitry Chagin 		p = td->td_proc;
2732711aba9SDmitry Chagin 		tid = LINUX_CPUCLOCK_ID(args->which);
2742711aba9SDmitry Chagin 		if (tid == 0) {
2752711aba9SDmitry Chagin 			targettd = td;
2762711aba9SDmitry Chagin 			PROC_LOCK(p);
2772711aba9SDmitry Chagin 		} else {
2782711aba9SDmitry Chagin 			targettd = tdfind(tid, p->p_pid);
2792711aba9SDmitry Chagin 			if (targettd == NULL)
2802711aba9SDmitry Chagin 				return (EINVAL);
2812711aba9SDmitry Chagin 		}
2822711aba9SDmitry Chagin 		switch (clockwhich) {
2832711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
2842711aba9SDmitry Chagin 			PROC_STATLOCK(p);
2852711aba9SDmitry Chagin 			thread_lock(targettd);
2862711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
2872711aba9SDmitry Chagin 			thread_unlock(targettd);
2882711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
2892711aba9SDmitry Chagin 			PROC_UNLOCK(p);
2902711aba9SDmitry Chagin 			timevaladd(&ru.ru_utime, &ru.ru_stime);
2912711aba9SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
2922711aba9SDmitry Chagin 			break;
2932711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
2942711aba9SDmitry Chagin 			PROC_STATLOCK(p);
2952711aba9SDmitry Chagin 			thread_lock(targettd);
2962711aba9SDmitry Chagin 			rufetchtd(targettd, &ru);
2972711aba9SDmitry Chagin 			thread_unlock(targettd);
2982711aba9SDmitry Chagin 			PROC_STATUNLOCK(p);
2992711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3002711aba9SDmitry Chagin 			TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
3012711aba9SDmitry Chagin 			break;
3022711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
3032711aba9SDmitry Chagin 			error = kern_clock_getcpuclockid2(td, tid,
3042711aba9SDmitry Chagin 			    CPUCLOCK_WHICH_TID, &nwhich);
3052711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3062711aba9SDmitry Chagin 			if (error != 0)
3072711aba9SDmitry Chagin 				return (EINVAL);
3082711aba9SDmitry Chagin 			error = kern_clock_gettime(td, nwhich, &tp);
3092711aba9SDmitry Chagin 			break;
3102711aba9SDmitry Chagin 		default:
3112711aba9SDmitry Chagin 			PROC_UNLOCK(p);
3122711aba9SDmitry Chagin 			return (EINVAL);
3132711aba9SDmitry Chagin 		}
3142711aba9SDmitry Chagin 		break;
3152711aba9SDmitry Chagin 
3162711aba9SDmitry Chagin 	default:
3172711aba9SDmitry Chagin 		error = kern_clock_gettime(td, nwhich, &tp);
3182711aba9SDmitry Chagin 		break;
3192711aba9SDmitry Chagin 	}
32019e252baSAlexander Leidinger 	if (error != 0) {
32119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
32219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
32377424f41SJung-uk Kim 		return (error);
32419e252baSAlexander Leidinger 	}
325ad2056f2SAlexander Leidinger 	native_to_linux_timespec(&lts, &tp);
326ad2056f2SAlexander Leidinger 
32719e252baSAlexander Leidinger 	error = copyout(&lts, args->tp, sizeof lts);
32819e252baSAlexander Leidinger 	if (error != 0)
32919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
33019e252baSAlexander Leidinger 
33119e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
33219e252baSAlexander Leidinger 	return (error);
333ad2056f2SAlexander Leidinger }
334ad2056f2SAlexander Leidinger 
335ad2056f2SAlexander Leidinger int
336ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
337ad2056f2SAlexander Leidinger {
338ad2056f2SAlexander Leidinger 	struct timespec ts;
339ad2056f2SAlexander Leidinger 	struct l_timespec lts;
340ad2056f2SAlexander Leidinger 	int error;
341ad2056f2SAlexander Leidinger 	clockid_t nwhich = 0;	/* XXX: GCC */
342ad2056f2SAlexander Leidinger 
34319e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp);
344ad2056f2SAlexander Leidinger 
34519e252baSAlexander Leidinger 	error = linux_to_native_clockid(&nwhich, args->which);
34619e252baSAlexander Leidinger 	if (error != 0) {
34719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
34819e252baSAlexander Leidinger 		    error);
34919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
35019e252baSAlexander Leidinger 		return (error);
35119e252baSAlexander Leidinger 	}
35219e252baSAlexander Leidinger 	error = copyin(args->tp, &lts, sizeof lts);
35319e252baSAlexander Leidinger 	if (error != 0) {
35419e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
35519e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
35619e252baSAlexander Leidinger 		return (error);
35719e252baSAlexander Leidinger 	}
35819e252baSAlexander Leidinger 	error = linux_to_native_timespec(&ts, &lts);
35919e252baSAlexander Leidinger 	if (error != 0) {
36019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
36119e252baSAlexander Leidinger 		    error);
36219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
36319e252baSAlexander Leidinger 		return (error);
36419e252baSAlexander Leidinger 	}
36519e252baSAlexander Leidinger 
36619e252baSAlexander Leidinger 	error = kern_clock_settime(td, nwhich, &ts);
36719e252baSAlexander Leidinger 	if (error != 0)
36819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error);
36919e252baSAlexander Leidinger 
37019e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
37119e252baSAlexander Leidinger 	return (error);
372ad2056f2SAlexander Leidinger }
373ad2056f2SAlexander Leidinger 
374ad2056f2SAlexander Leidinger int
375ad2056f2SAlexander Leidinger linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
376ad2056f2SAlexander Leidinger {
3772711aba9SDmitry Chagin 	struct proc *p;
378ad2056f2SAlexander Leidinger 	struct timespec ts;
379ad2056f2SAlexander Leidinger 	struct l_timespec lts;
3802711aba9SDmitry Chagin 	int error, clockwhich;
381ad2056f2SAlexander Leidinger 	clockid_t nwhich = 0;	/* XXX: GCC */
3822711aba9SDmitry Chagin 	pid_t pid;
3832711aba9SDmitry Chagin 	lwpid_t tid;
384ad2056f2SAlexander Leidinger 
38519e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp);
38619e252baSAlexander Leidinger 
387ad2056f2SAlexander Leidinger 	error = linux_to_native_clockid(&nwhich, args->which);
38819e252baSAlexander Leidinger 	if (error != 0) {
38919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error,
39019e252baSAlexander Leidinger 		    error);
39119e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
39277424f41SJung-uk Kim 		return (error);
39319e252baSAlexander Leidinger 	}
3942711aba9SDmitry Chagin 
3952711aba9SDmitry Chagin 	/*
3962711aba9SDmitry Chagin 	 * Check user supplied clock id in case of per-process
3972711aba9SDmitry Chagin 	 * or thread-specific cpu-time clock.
3982711aba9SDmitry Chagin 	 */
3992711aba9SDmitry Chagin 	switch (nwhich) {
4002711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
4012711aba9SDmitry Chagin 		tid = LINUX_CPUCLOCK_ID(args->which);
4022711aba9SDmitry Chagin 		if (tid != 0) {
4032711aba9SDmitry Chagin 			p = td->td_proc;
4042711aba9SDmitry Chagin 			if (tdfind(tid, p->p_pid) == NULL)
4052711aba9SDmitry Chagin 				return (ESRCH);
4062711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4072711aba9SDmitry Chagin 		}
4082711aba9SDmitry Chagin 		break;
4092711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
4102711aba9SDmitry Chagin 		pid = LINUX_CPUCLOCK_ID(args->which);
4112711aba9SDmitry Chagin 		if (pid != 0) {
4122711aba9SDmitry Chagin 			error = pget(pid, PGET_CANSEE, &p);
4132711aba9SDmitry Chagin 			if (error != 0)
4142711aba9SDmitry Chagin 				return (EINVAL);
4152711aba9SDmitry Chagin 			PROC_UNLOCK(p);
4162711aba9SDmitry Chagin 		}
4172711aba9SDmitry Chagin 		break;
4182711aba9SDmitry Chagin 	}
4192711aba9SDmitry Chagin 
4202711aba9SDmitry Chagin 	if (args->tp == NULL) {
4212711aba9SDmitry Chagin 		LIN_SDT_PROBE0(time, linux_clock_getres, nullcall);
4222711aba9SDmitry Chagin 		LIN_SDT_PROBE1(time, linux_clock_getres, return, 0);
4232711aba9SDmitry Chagin 	  	return (0);
4242711aba9SDmitry Chagin 	}
4252711aba9SDmitry Chagin 
4262711aba9SDmitry Chagin 	switch (nwhich) {
4272711aba9SDmitry Chagin 	case CLOCK_THREAD_CPUTIME_ID:
4282711aba9SDmitry Chagin 	case CLOCK_PROCESS_CPUTIME_ID:
4292711aba9SDmitry Chagin 		clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
4302711aba9SDmitry Chagin 		switch (clockwhich) {
4312711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_PROF:
4322711aba9SDmitry Chagin 			nwhich = CLOCK_PROF;
4332711aba9SDmitry Chagin 			break;
4342711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_VIRT:
4352711aba9SDmitry Chagin 			nwhich = CLOCK_VIRTUAL;
4362711aba9SDmitry Chagin 			break;
4372711aba9SDmitry Chagin 		case LINUX_CPUCLOCK_SCHED:
4382711aba9SDmitry Chagin 			break;
4392711aba9SDmitry Chagin 		default:
4402711aba9SDmitry Chagin 			return (EINVAL);
4412711aba9SDmitry Chagin 		}
4422711aba9SDmitry Chagin 		break;
4432711aba9SDmitry Chagin 
4442711aba9SDmitry Chagin 	default:
4452711aba9SDmitry Chagin 		break;
4462711aba9SDmitry Chagin 	}
447ad2056f2SAlexander Leidinger 	error = kern_clock_getres(td, nwhich, &ts);
44819e252baSAlexander Leidinger 	if (error != 0) {
44919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error);
45019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
45177424f41SJung-uk Kim 		return (error);
45219e252baSAlexander Leidinger 	}
453ad2056f2SAlexander Leidinger 	native_to_linux_timespec(&lts, &ts);
454ad2056f2SAlexander Leidinger 
45519e252baSAlexander Leidinger 	error = copyout(&lts, args->tp, sizeof lts);
45619e252baSAlexander Leidinger 	if (error != 0)
45719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
45819e252baSAlexander Leidinger 
45919e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
46019e252baSAlexander Leidinger 	return (error);
46177424f41SJung-uk Kim }
46277424f41SJung-uk Kim 
46377424f41SJung-uk Kim int
46477424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
46577424f41SJung-uk Kim {
46677424f41SJung-uk Kim 	struct timespec *rmtp;
46777424f41SJung-uk Kim 	struct l_timespec lrqts, lrmts;
46877424f41SJung-uk Kim 	struct timespec rqts, rmts;
4695c2748d5SDmitry Chagin 	int error, error2;
47077424f41SJung-uk Kim 
47119e252baSAlexander Leidinger 	LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp);
47219e252baSAlexander Leidinger 
47377424f41SJung-uk Kim 	error = copyin(args->rqtp, &lrqts, sizeof lrqts);
47419e252baSAlexander Leidinger 	if (error != 0) {
47519e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
47619e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
47777424f41SJung-uk Kim 		return (error);
47819e252baSAlexander Leidinger 	}
47977424f41SJung-uk Kim 
48077424f41SJung-uk Kim 	if (args->rmtp != NULL)
48177424f41SJung-uk Kim 		rmtp = &rmts;
48277424f41SJung-uk Kim 	else
48377424f41SJung-uk Kim 		rmtp = NULL;
48477424f41SJung-uk Kim 
48577424f41SJung-uk Kim 	error = linux_to_native_timespec(&rqts, &lrqts);
48619e252baSAlexander Leidinger 	if (error != 0) {
48719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
48819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
48977424f41SJung-uk Kim 		return (error);
49019e252baSAlexander Leidinger 	}
49177424f41SJung-uk Kim 	error = kern_nanosleep(td, &rqts, rmtp);
49277424f41SJung-uk Kim 	if (args->rmtp != NULL) {
49377424f41SJung-uk Kim 		native_to_linux_timespec(&lrmts, rmtp);
4945c2748d5SDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
4955c2748d5SDmitry Chagin 		if (error2 != 0) {
49619e252baSAlexander Leidinger 			LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
4975c2748d5SDmitry Chagin 			    error2);
4985c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_nanosleep, return, error2);
4995c2748d5SDmitry Chagin 			return (error2);
50077424f41SJung-uk Kim 		}
50119e252baSAlexander Leidinger 	}
50277424f41SJung-uk Kim 
5035c2748d5SDmitry Chagin 	LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
5045c2748d5SDmitry Chagin 	return (error);
505ad2056f2SAlexander Leidinger }
506ad2056f2SAlexander Leidinger 
507ad2056f2SAlexander Leidinger int
508ad2056f2SAlexander Leidinger linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args)
509ad2056f2SAlexander Leidinger {
510ad2056f2SAlexander Leidinger 	struct timespec *rmtp;
511ad2056f2SAlexander Leidinger 	struct l_timespec lrqts, lrmts;
512ad2056f2SAlexander Leidinger 	struct timespec rqts, rmts;
5135c2748d5SDmitry Chagin 	int error, error2;
514ad2056f2SAlexander Leidinger 
51519e252baSAlexander Leidinger 	LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which,
51619e252baSAlexander Leidinger 	    args->flags, args->rqtp, args->rmtp);
517ad2056f2SAlexander Leidinger 
51819e252baSAlexander Leidinger 	if (args->flags != 0) {
51919e252baSAlexander Leidinger 		/* XXX deal with TIMER_ABSTIME */
52019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags,
52119e252baSAlexander Leidinger 		    args->flags);
52219e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL);
52319e252baSAlexander Leidinger 		return (EINVAL);	/* XXX deal with TIMER_ABSTIME */
52419e252baSAlexander Leidinger 	}
52519e252baSAlexander Leidinger 
52619e252baSAlexander Leidinger 	if (args->which != LINUX_CLOCK_REALTIME) {
52719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid,
52819e252baSAlexander Leidinger 		    args->which);
52919e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL);
53077424f41SJung-uk Kim 		return (EINVAL);
53119e252baSAlexander Leidinger 	}
532ad2056f2SAlexander Leidinger 
5335c2748d5SDmitry Chagin 	error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
53419e252baSAlexander Leidinger 	if (error != 0) {
53519e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
53619e252baSAlexander Leidinger 		    error);
53719e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
53877424f41SJung-uk Kim 		return (error);
53919e252baSAlexander Leidinger 	}
540ad2056f2SAlexander Leidinger 
541ad2056f2SAlexander Leidinger 	if (args->rmtp != NULL)
542ad2056f2SAlexander Leidinger 		rmtp = &rmts;
543ad2056f2SAlexander Leidinger 	else
544ad2056f2SAlexander Leidinger 		rmtp = NULL;
545ad2056f2SAlexander Leidinger 
54677424f41SJung-uk Kim 	error = linux_to_native_timespec(&rqts, &lrqts);
54719e252baSAlexander Leidinger 	if (error != 0) {
54819e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
54919e252baSAlexander Leidinger 		    error);
55019e252baSAlexander Leidinger 		LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
55177424f41SJung-uk Kim 		return (error);
55219e252baSAlexander Leidinger 	}
553ad2056f2SAlexander Leidinger 	error = kern_nanosleep(td, &rqts, rmtp);
5545c2748d5SDmitry Chagin 	if (args->rmtp != NULL) {
5555c2748d5SDmitry Chagin 		/* XXX. Not for TIMER_ABSTIME */
5565c2748d5SDmitry Chagin 	   	native_to_linux_timespec(&lrmts, rmtp);
5575c2748d5SDmitry Chagin 		error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
5585c2748d5SDmitry Chagin 		if (error2 != 0) {
5595c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
5605c2748d5SDmitry Chagin 			    copyout_error, error2);
5615c2748d5SDmitry Chagin 			LIN_SDT_PROBE1(time, linux_clock_nanosleep,
5625c2748d5SDmitry Chagin 			    return, error2);
5635c2748d5SDmitry Chagin 			return (error2);
5645c2748d5SDmitry Chagin 		}
5655c2748d5SDmitry Chagin 	}
5665c2748d5SDmitry Chagin 
56719e252baSAlexander Leidinger 	LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
56877424f41SJung-uk Kim 	return (error);
56919e252baSAlexander Leidinger }
570