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> 70*4afe4faeSEdward 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_DEFINE2(time, native_to_linux_timespec, entry, 7919e252baSAlexander Leidinger "struct l_timespec *", "struct timespec *"); 8019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return); 8119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry, 8219e252baSAlexander Leidinger "struct timespec *", "struct l_timespec *"); 8319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int"); 8419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *", 8519e252baSAlexander Leidinger "clockid_t"); 8619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid, 8719e252baSAlexander Leidinger "clockid_t"); 8819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid, 8919e252baSAlexander Leidinger "clockid_t"); 9019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int"); 9119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t", 9219e252baSAlexander Leidinger "struct l_timespec *"); 9319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int"); 9419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int"); 9519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int"); 9619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int"); 9719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t", 9819e252baSAlexander Leidinger "struct l_timespec *"); 9919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int"); 10019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int"); 10119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int"); 10219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int"); 10319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t", 10419e252baSAlexander Leidinger "struct l_timespec *"); 10519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall); 10619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int"); 10719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int"); 10819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int"); 10919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int"); 11019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *", 11119e252baSAlexander Leidinger "struct l_timespec *"); 11219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int"); 11319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int"); 11419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int"); 11519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int"); 11619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int", 11719e252baSAlexander Leidinger "struct l_timespec *", "struct l_timespec *"); 11819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int"); 11919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int"); 12019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int"); 12119e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int"); 12219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int"); 12319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int"); 12419e252baSAlexander Leidinger 12568098228SDmitry Chagin 1260670e972SDmitry Chagin int 127ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp) 128ad2056f2SAlexander Leidinger { 12919e252baSAlexander Leidinger 13019e252baSAlexander Leidinger LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp); 1310670e972SDmitry Chagin #ifdef COMPAT_LINUX32 13271b50d08SDmitry Chagin if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN) 1330670e972SDmitry Chagin return (EOVERFLOW); 1340670e972SDmitry Chagin #endif 135ad2056f2SAlexander Leidinger ltp->tv_sec = ntp->tv_sec; 136ad2056f2SAlexander Leidinger ltp->tv_nsec = ntp->tv_nsec; 13719e252baSAlexander Leidinger 13819e252baSAlexander Leidinger LIN_SDT_PROBE0(time, native_to_linux_timespec, return); 1390670e972SDmitry Chagin return (0); 140ad2056f2SAlexander Leidinger } 141ad2056f2SAlexander Leidinger 14268098228SDmitry Chagin int 143ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp) 144ad2056f2SAlexander Leidinger { 14519e252baSAlexander Leidinger 14619e252baSAlexander Leidinger LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp); 14719e252baSAlexander Leidinger 1482ac9dcedSDmitry Chagin if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999) { 14919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL); 15077424f41SJung-uk Kim return (EINVAL); 15119e252baSAlexander Leidinger } 152ad2056f2SAlexander Leidinger ntp->tv_sec = ltp->tv_sec; 153ad2056f2SAlexander Leidinger ntp->tv_nsec = ltp->tv_nsec; 15477424f41SJung-uk Kim 15519e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0); 15677424f41SJung-uk Kim return (0); 157ad2056f2SAlexander Leidinger } 158ad2056f2SAlexander Leidinger 15916ac71bcSDmitry Chagin int 160dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp) 161dd93b628SDmitry Chagin { 162dd93b628SDmitry Chagin int error; 163dd93b628SDmitry Chagin 164dd93b628SDmitry Chagin error = native_to_linux_timespec(<p->it_interval, &ntp->it_interval); 165dd93b628SDmitry Chagin if (error == 0) 166dd93b628SDmitry Chagin error = native_to_linux_timespec(<p->it_value, &ntp->it_interval); 167dd93b628SDmitry Chagin return (error); 168dd93b628SDmitry Chagin } 169dd93b628SDmitry Chagin 170dd93b628SDmitry Chagin int 171dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp) 172dd93b628SDmitry Chagin { 173dd93b628SDmitry Chagin int error; 174dd93b628SDmitry Chagin 175dd93b628SDmitry Chagin error = linux_to_native_timespec(&ntp->it_interval, <p->it_interval); 176dd93b628SDmitry Chagin if (error == 0) 177dd93b628SDmitry Chagin error = linux_to_native_timespec(&ntp->it_value, <p->it_value); 178dd93b628SDmitry Chagin return (error); 179dd93b628SDmitry Chagin } 180dd93b628SDmitry Chagin 181dd93b628SDmitry Chagin int 182ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l) 183ad2056f2SAlexander Leidinger { 18419e252baSAlexander Leidinger 18519e252baSAlexander Leidinger LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l); 18619e252baSAlexander Leidinger 1872711aba9SDmitry Chagin if (l < 0) { 1882711aba9SDmitry Chagin /* cpu-clock */ 1892711aba9SDmitry Chagin if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD) 1902711aba9SDmitry Chagin return (EINVAL); 1912711aba9SDmitry Chagin if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX) 1922711aba9SDmitry Chagin return (EINVAL); 1932711aba9SDmitry Chagin 1942711aba9SDmitry Chagin if (LINUX_CPUCLOCK_PERTHREAD(l)) 1952711aba9SDmitry Chagin *n = CLOCK_THREAD_CPUTIME_ID; 1962711aba9SDmitry Chagin else 1972711aba9SDmitry Chagin *n = CLOCK_PROCESS_CPUTIME_ID; 1982711aba9SDmitry Chagin return (0); 1992711aba9SDmitry Chagin } 2002711aba9SDmitry Chagin 201ad2056f2SAlexander Leidinger switch (l) { 202ad2056f2SAlexander Leidinger case LINUX_CLOCK_REALTIME: 203ad2056f2SAlexander Leidinger *n = CLOCK_REALTIME; 204ad2056f2SAlexander Leidinger break; 205ad2056f2SAlexander Leidinger case LINUX_CLOCK_MONOTONIC: 206ad2056f2SAlexander Leidinger *n = CLOCK_MONOTONIC; 207ad2056f2SAlexander Leidinger break; 2087bc05ae6SDmitry Chagin case LINUX_CLOCK_PROCESS_CPUTIME_ID: 2097bc05ae6SDmitry Chagin *n = CLOCK_PROCESS_CPUTIME_ID; 2107bc05ae6SDmitry Chagin break; 2117bc05ae6SDmitry Chagin case LINUX_CLOCK_THREAD_CPUTIME_ID: 2127bc05ae6SDmitry Chagin *n = CLOCK_THREAD_CPUTIME_ID; 2137bc05ae6SDmitry Chagin break; 2142711aba9SDmitry Chagin case LINUX_CLOCK_REALTIME_COARSE: 2152711aba9SDmitry Chagin *n = CLOCK_REALTIME_FAST; 2162711aba9SDmitry Chagin break; 2172711aba9SDmitry Chagin case LINUX_CLOCK_MONOTONIC_COARSE: 2182711aba9SDmitry Chagin *n = CLOCK_MONOTONIC_FAST; 2192711aba9SDmitry Chagin break; 2202711aba9SDmitry Chagin case LINUX_CLOCK_BOOTTIME: 22125ada637SDmitry Chagin *n = CLOCK_UPTIME; 22225ada637SDmitry Chagin break; 22325ada637SDmitry Chagin case LINUX_CLOCK_MONOTONIC_RAW: 2242711aba9SDmitry Chagin case LINUX_CLOCK_REALTIME_ALARM: 2252711aba9SDmitry Chagin case LINUX_CLOCK_BOOTTIME_ALARM: 2262711aba9SDmitry Chagin case LINUX_CLOCK_SGI_CYCLE: 2272711aba9SDmitry Chagin case LINUX_CLOCK_TAI: 22819e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, 22919e252baSAlexander Leidinger unsupported_clockid, l); 23019e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); 23119e252baSAlexander Leidinger return (EINVAL); 23277424f41SJung-uk Kim default: 23319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, 23419e252baSAlexander Leidinger unknown_clockid, l); 23519e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); 23677424f41SJung-uk Kim return (EINVAL); 237ad2056f2SAlexander Leidinger } 238ad2056f2SAlexander Leidinger 23919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0); 24077424f41SJung-uk Kim return (0); 241ad2056f2SAlexander Leidinger } 242ad2056f2SAlexander Leidinger 243ad2056f2SAlexander Leidinger int 244f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags) 245f0f58384SDmitry Chagin { 246f0f58384SDmitry Chagin 247f0f58384SDmitry Chagin if (flags & ~LINUX_TIMER_ABSTIME) 248f0f58384SDmitry Chagin return (EINVAL); 249f0f58384SDmitry Chagin *nflags = 0; 250f0f58384SDmitry Chagin if (flags & LINUX_TIMER_ABSTIME) 251f0f58384SDmitry Chagin *nflags |= TIMER_ABSTIME; 252f0f58384SDmitry Chagin return (0); 253f0f58384SDmitry Chagin } 254f0f58384SDmitry Chagin 255f0f58384SDmitry Chagin int 256ad2056f2SAlexander Leidinger linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args) 257ad2056f2SAlexander Leidinger { 258ad2056f2SAlexander Leidinger struct l_timespec lts; 259ad2056f2SAlexander Leidinger struct timespec tp; 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 26819e252baSAlexander Leidinger LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp); 26919e252baSAlexander Leidinger 270ad2056f2SAlexander Leidinger error = linux_to_native_clockid(&nwhich, args->which); 27119e252baSAlexander Leidinger if (error != 0) { 272*4afe4faeSEdward Tomasz Napierala linux_msg(curthread, 273*4afe4faeSEdward Tomasz Napierala "unsupported clock_gettime clockid %d", args->which); 27419e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error, 27519e252baSAlexander Leidinger error); 27619e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 27777424f41SJung-uk Kim return (error); 27819e252baSAlexander Leidinger } 2792711aba9SDmitry Chagin 2802711aba9SDmitry Chagin switch (nwhich) { 2812711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 2827bc05ae6SDmitry Chagin if (args->which < 0) { 2832711aba9SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 2842711aba9SDmitry Chagin pid = LINUX_CPUCLOCK_ID(args->which); 2857bc05ae6SDmitry Chagin } else { 2867bc05ae6SDmitry Chagin clockwhich = LINUX_CPUCLOCK_SCHED; 2877bc05ae6SDmitry Chagin pid = 0; 2887bc05ae6SDmitry Chagin } 2892711aba9SDmitry Chagin if (pid == 0) { 2902711aba9SDmitry Chagin p = td->td_proc; 2912711aba9SDmitry Chagin PROC_LOCK(p); 2922711aba9SDmitry Chagin } else { 2932711aba9SDmitry Chagin error = pget(pid, PGET_CANSEE, &p); 2942711aba9SDmitry Chagin if (error != 0) 2952711aba9SDmitry Chagin return (EINVAL); 2962711aba9SDmitry Chagin } 2972711aba9SDmitry Chagin switch (clockwhich) { 2982711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 2992711aba9SDmitry Chagin PROC_STATLOCK(p); 3002711aba9SDmitry Chagin calcru(p, &ru.ru_utime, &ru.ru_stime); 3012711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3022711aba9SDmitry Chagin PROC_UNLOCK(p); 3032711aba9SDmitry Chagin timevaladd(&ru.ru_utime, &ru.ru_stime); 3042711aba9SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 3052711aba9SDmitry Chagin break; 3062711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 3072711aba9SDmitry Chagin PROC_STATLOCK(p); 3082711aba9SDmitry Chagin calcru(p, &ru.ru_utime, &ru.ru_stime); 3092711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3102711aba9SDmitry Chagin PROC_UNLOCK(p); 3112711aba9SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 3122711aba9SDmitry Chagin break; 3132711aba9SDmitry Chagin case LINUX_CPUCLOCK_SCHED: 3147bc05ae6SDmitry Chagin kern_process_cputime(p, &tp); 3152711aba9SDmitry Chagin PROC_UNLOCK(p); 3162711aba9SDmitry Chagin break; 3172711aba9SDmitry Chagin default: 3182711aba9SDmitry Chagin PROC_UNLOCK(p); 3192711aba9SDmitry Chagin return (EINVAL); 3202711aba9SDmitry Chagin } 3212711aba9SDmitry Chagin 3222711aba9SDmitry Chagin break; 3232711aba9SDmitry Chagin 3242711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 3257bc05ae6SDmitry Chagin if (args->which < 0) { 3262711aba9SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 3272711aba9SDmitry Chagin tid = LINUX_CPUCLOCK_ID(args->which); 3287bc05ae6SDmitry Chagin } else { 3297bc05ae6SDmitry Chagin clockwhich = LINUX_CPUCLOCK_SCHED; 3307bc05ae6SDmitry Chagin tid = 0; 3317bc05ae6SDmitry Chagin } 3327bc05ae6SDmitry Chagin p = td->td_proc; 3332711aba9SDmitry Chagin if (tid == 0) { 3342711aba9SDmitry Chagin targettd = td; 3352711aba9SDmitry Chagin PROC_LOCK(p); 3362711aba9SDmitry Chagin } else { 3377bc05ae6SDmitry Chagin targettd = linux_tdfind(td, tid, p->p_pid); 3382711aba9SDmitry Chagin if (targettd == NULL) 3392711aba9SDmitry Chagin return (EINVAL); 3402711aba9SDmitry Chagin } 3412711aba9SDmitry Chagin switch (clockwhich) { 3422711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 3432711aba9SDmitry Chagin PROC_STATLOCK(p); 3442711aba9SDmitry Chagin thread_lock(targettd); 3452711aba9SDmitry Chagin rufetchtd(targettd, &ru); 3462711aba9SDmitry Chagin thread_unlock(targettd); 3472711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3482711aba9SDmitry Chagin PROC_UNLOCK(p); 3492711aba9SDmitry Chagin timevaladd(&ru.ru_utime, &ru.ru_stime); 3502711aba9SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 3512711aba9SDmitry Chagin break; 3522711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 3532711aba9SDmitry Chagin PROC_STATLOCK(p); 3542711aba9SDmitry Chagin thread_lock(targettd); 3552711aba9SDmitry Chagin rufetchtd(targettd, &ru); 3562711aba9SDmitry Chagin thread_unlock(targettd); 3572711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3582711aba9SDmitry Chagin PROC_UNLOCK(p); 3592711aba9SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 3602711aba9SDmitry Chagin break; 3612711aba9SDmitry Chagin case LINUX_CPUCLOCK_SCHED: 3627bc05ae6SDmitry Chagin if (td == targettd) 3637bc05ae6SDmitry Chagin targettd = NULL; 3647bc05ae6SDmitry Chagin kern_thread_cputime(targettd, &tp); 3652711aba9SDmitry Chagin PROC_UNLOCK(p); 3662711aba9SDmitry Chagin break; 3672711aba9SDmitry Chagin default: 3682711aba9SDmitry Chagin PROC_UNLOCK(p); 3692711aba9SDmitry Chagin return (EINVAL); 3702711aba9SDmitry Chagin } 3712711aba9SDmitry Chagin break; 3722711aba9SDmitry Chagin 3732711aba9SDmitry Chagin default: 3742711aba9SDmitry Chagin error = kern_clock_gettime(td, nwhich, &tp); 3752711aba9SDmitry Chagin break; 3762711aba9SDmitry Chagin } 37719e252baSAlexander Leidinger if (error != 0) { 37819e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error); 37919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 38077424f41SJung-uk Kim return (error); 38119e252baSAlexander Leidinger } 3820670e972SDmitry Chagin error = native_to_linux_timespec(<s, &tp); 3830670e972SDmitry Chagin if (error != 0) 3840670e972SDmitry Chagin return (error); 38519e252baSAlexander Leidinger error = copyout(<s, args->tp, sizeof lts); 38619e252baSAlexander Leidinger if (error != 0) 38719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error); 38819e252baSAlexander Leidinger 38919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 39019e252baSAlexander Leidinger return (error); 391ad2056f2SAlexander Leidinger } 392ad2056f2SAlexander Leidinger 393ad2056f2SAlexander Leidinger int 394ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args) 395ad2056f2SAlexander Leidinger { 396ad2056f2SAlexander Leidinger struct timespec ts; 397ad2056f2SAlexander Leidinger struct l_timespec lts; 398ad2056f2SAlexander Leidinger int error; 3992506c761SDmitry Chagin clockid_t nwhich; 400ad2056f2SAlexander Leidinger 40119e252baSAlexander Leidinger LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp); 402ad2056f2SAlexander Leidinger 40319e252baSAlexander Leidinger error = linux_to_native_clockid(&nwhich, args->which); 40419e252baSAlexander Leidinger if (error != 0) { 405*4afe4faeSEdward Tomasz Napierala linux_msg(curthread, 406*4afe4faeSEdward Tomasz Napierala "unsupported clock_settime clockid %d", args->which); 40719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error, 40819e252baSAlexander Leidinger error); 40919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 41019e252baSAlexander Leidinger return (error); 41119e252baSAlexander Leidinger } 41219e252baSAlexander Leidinger error = copyin(args->tp, <s, sizeof lts); 41319e252baSAlexander Leidinger if (error != 0) { 41419e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error); 41519e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 41619e252baSAlexander Leidinger return (error); 41719e252baSAlexander Leidinger } 41819e252baSAlexander Leidinger error = linux_to_native_timespec(&ts, <s); 41919e252baSAlexander Leidinger if (error != 0) { 42019e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error, 42119e252baSAlexander Leidinger error); 42219e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 42319e252baSAlexander Leidinger return (error); 42419e252baSAlexander Leidinger } 42519e252baSAlexander Leidinger 42619e252baSAlexander Leidinger error = kern_clock_settime(td, nwhich, &ts); 42719e252baSAlexander Leidinger if (error != 0) 42819e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error); 42919e252baSAlexander Leidinger 43019e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 43119e252baSAlexander Leidinger return (error); 432ad2056f2SAlexander Leidinger } 433ad2056f2SAlexander Leidinger 434ad2056f2SAlexander Leidinger int 435ad2056f2SAlexander Leidinger linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args) 436ad2056f2SAlexander Leidinger { 4372711aba9SDmitry Chagin struct proc *p; 438ad2056f2SAlexander Leidinger struct timespec ts; 439ad2056f2SAlexander Leidinger struct l_timespec lts; 4402711aba9SDmitry Chagin int error, clockwhich; 4412506c761SDmitry Chagin clockid_t nwhich; 4422711aba9SDmitry Chagin pid_t pid; 4432711aba9SDmitry Chagin lwpid_t tid; 444ad2056f2SAlexander Leidinger 44519e252baSAlexander Leidinger LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp); 44619e252baSAlexander Leidinger 447ad2056f2SAlexander Leidinger error = linux_to_native_clockid(&nwhich, args->which); 44819e252baSAlexander Leidinger if (error != 0) { 449*4afe4faeSEdward Tomasz Napierala linux_msg(curthread, 450*4afe4faeSEdward Tomasz Napierala "unsupported clock_getres clockid %d", args->which); 45119e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error, 45219e252baSAlexander Leidinger error); 45319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 45477424f41SJung-uk Kim return (error); 45519e252baSAlexander Leidinger } 4562711aba9SDmitry Chagin 4572711aba9SDmitry Chagin /* 4582711aba9SDmitry Chagin * Check user supplied clock id in case of per-process 4592711aba9SDmitry Chagin * or thread-specific cpu-time clock. 4602711aba9SDmitry Chagin */ 4617bc05ae6SDmitry Chagin if (args->which < 0) { 4622711aba9SDmitry Chagin switch (nwhich) { 4632711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 4642711aba9SDmitry Chagin tid = LINUX_CPUCLOCK_ID(args->which); 4652711aba9SDmitry Chagin if (tid != 0) { 4662711aba9SDmitry Chagin p = td->td_proc; 4677bc05ae6SDmitry Chagin if (linux_tdfind(td, tid, p->p_pid) == NULL) 4687bc05ae6SDmitry Chagin return (EINVAL); 4692711aba9SDmitry Chagin PROC_UNLOCK(p); 4702711aba9SDmitry Chagin } 4712711aba9SDmitry Chagin break; 4722711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 4732711aba9SDmitry Chagin pid = LINUX_CPUCLOCK_ID(args->which); 4742711aba9SDmitry Chagin if (pid != 0) { 4752711aba9SDmitry Chagin error = pget(pid, PGET_CANSEE, &p); 4762711aba9SDmitry Chagin if (error != 0) 4772711aba9SDmitry Chagin return (EINVAL); 4782711aba9SDmitry Chagin PROC_UNLOCK(p); 4792711aba9SDmitry Chagin } 4802711aba9SDmitry Chagin break; 4812711aba9SDmitry Chagin } 4827bc05ae6SDmitry Chagin } 4832711aba9SDmitry Chagin 4842711aba9SDmitry Chagin if (args->tp == NULL) { 4852711aba9SDmitry Chagin LIN_SDT_PROBE0(time, linux_clock_getres, nullcall); 4862711aba9SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_getres, return, 0); 4872711aba9SDmitry Chagin return (0); 4882711aba9SDmitry Chagin } 4892711aba9SDmitry Chagin 4902711aba9SDmitry Chagin switch (nwhich) { 4912711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 4922711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 4932711aba9SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 4947bc05ae6SDmitry Chagin /* 4957bc05ae6SDmitry Chagin * In both cases (when the clock id obtained by a call to 4967bc05ae6SDmitry Chagin * clock_getcpuclockid() or using the clock 4977bc05ae6SDmitry Chagin * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision 4987bc05ae6SDmitry Chagin * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock. 4997bc05ae6SDmitry Chagin * 5007bc05ae6SDmitry Chagin * See Linux posix_cpu_clock_getres() implementation. 5017bc05ae6SDmitry Chagin */ 5027bc05ae6SDmitry Chagin if (args->which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) { 5037bc05ae6SDmitry Chagin ts.tv_sec = 0; 5047bc05ae6SDmitry Chagin ts.tv_nsec = 1; 5057bc05ae6SDmitry Chagin goto out; 5067bc05ae6SDmitry Chagin } 5077bc05ae6SDmitry Chagin 5082711aba9SDmitry Chagin switch (clockwhich) { 5092711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 5102711aba9SDmitry Chagin nwhich = CLOCK_PROF; 5112711aba9SDmitry Chagin break; 5122711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 5132711aba9SDmitry Chagin nwhich = CLOCK_VIRTUAL; 5142711aba9SDmitry Chagin break; 5152711aba9SDmitry Chagin default: 5162711aba9SDmitry Chagin return (EINVAL); 5172711aba9SDmitry Chagin } 5182711aba9SDmitry Chagin break; 5192711aba9SDmitry Chagin 5202711aba9SDmitry Chagin default: 5212711aba9SDmitry Chagin break; 5222711aba9SDmitry Chagin } 523ad2056f2SAlexander Leidinger error = kern_clock_getres(td, nwhich, &ts); 52419e252baSAlexander Leidinger if (error != 0) { 52519e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error); 52619e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 52777424f41SJung-uk Kim return (error); 52819e252baSAlexander Leidinger } 5297bc05ae6SDmitry Chagin 5307bc05ae6SDmitry Chagin out: 5310670e972SDmitry Chagin error = native_to_linux_timespec(<s, &ts); 5320670e972SDmitry Chagin if (error != 0) 5330670e972SDmitry Chagin return (error); 53419e252baSAlexander Leidinger error = copyout(<s, args->tp, sizeof lts); 53519e252baSAlexander Leidinger if (error != 0) 53619e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error); 53719e252baSAlexander Leidinger 53819e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 53919e252baSAlexander Leidinger return (error); 54077424f41SJung-uk Kim } 54177424f41SJung-uk Kim 54277424f41SJung-uk Kim int 54377424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args) 54477424f41SJung-uk Kim { 54577424f41SJung-uk Kim struct timespec *rmtp; 54677424f41SJung-uk Kim struct l_timespec lrqts, lrmts; 54777424f41SJung-uk Kim struct timespec rqts, rmts; 5485c2748d5SDmitry Chagin int error, error2; 54977424f41SJung-uk Kim 55019e252baSAlexander Leidinger LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp); 55119e252baSAlexander Leidinger 55277424f41SJung-uk Kim error = copyin(args->rqtp, &lrqts, sizeof lrqts); 55319e252baSAlexander Leidinger if (error != 0) { 55419e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error); 55519e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 55677424f41SJung-uk Kim return (error); 55719e252baSAlexander Leidinger } 55877424f41SJung-uk Kim 55977424f41SJung-uk Kim if (args->rmtp != NULL) 56077424f41SJung-uk Kim rmtp = &rmts; 56177424f41SJung-uk Kim else 56277424f41SJung-uk Kim rmtp = NULL; 56377424f41SJung-uk Kim 56477424f41SJung-uk Kim error = linux_to_native_timespec(&rqts, &lrqts); 56519e252baSAlexander Leidinger if (error != 0) { 56619e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error); 56719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 56877424f41SJung-uk Kim return (error); 56919e252baSAlexander Leidinger } 57077424f41SJung-uk Kim error = kern_nanosleep(td, &rqts, rmtp); 5714cf66812SEric van Gyzen if (error == EINTR && args->rmtp != NULL) { 5720670e972SDmitry Chagin error2 = native_to_linux_timespec(&lrmts, rmtp); 5730670e972SDmitry Chagin if (error2 != 0) 5740670e972SDmitry Chagin return (error2); 5755c2748d5SDmitry Chagin error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 5765c2748d5SDmitry Chagin if (error2 != 0) { 57719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error, 5785c2748d5SDmitry Chagin error2); 5795c2748d5SDmitry Chagin LIN_SDT_PROBE1(time, linux_nanosleep, return, error2); 5805c2748d5SDmitry Chagin return (error2); 58177424f41SJung-uk Kim } 58219e252baSAlexander Leidinger } 58377424f41SJung-uk Kim 5845c2748d5SDmitry Chagin LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 5855c2748d5SDmitry Chagin return (error); 586ad2056f2SAlexander Leidinger } 587ad2056f2SAlexander Leidinger 588ad2056f2SAlexander Leidinger int 589ad2056f2SAlexander Leidinger linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args) 590ad2056f2SAlexander Leidinger { 591ad2056f2SAlexander Leidinger struct timespec *rmtp; 592ad2056f2SAlexander Leidinger struct l_timespec lrqts, lrmts; 593ad2056f2SAlexander Leidinger struct timespec rqts, rmts; 594f0f58384SDmitry Chagin int error, error2, flags; 595f0f58384SDmitry Chagin clockid_t clockid; 596ad2056f2SAlexander Leidinger 59719e252baSAlexander Leidinger LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which, 59819e252baSAlexander Leidinger args->flags, args->rqtp, args->rmtp); 599ad2056f2SAlexander Leidinger 600f0f58384SDmitry Chagin error = linux_to_native_timerflags(&flags, args->flags); 601f0f58384SDmitry Chagin if (error != 0) { 60219e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags, 60319e252baSAlexander Leidinger args->flags); 604f0f58384SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 605f0f58384SDmitry Chagin return (error); 60619e252baSAlexander Leidinger } 60719e252baSAlexander Leidinger 608f0f58384SDmitry Chagin error = linux_to_native_clockid(&clockid, args->which); 609f0f58384SDmitry Chagin if (error != 0) { 610*4afe4faeSEdward Tomasz Napierala linux_msg(curthread, 611*4afe4faeSEdward Tomasz Napierala "unsupported clock_nanosleep clockid %d", args->which); 61219e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid, 61319e252baSAlexander Leidinger args->which); 614f0f58384SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 615f0f58384SDmitry Chagin return (error); 61619e252baSAlexander Leidinger } 617ad2056f2SAlexander Leidinger 6185c2748d5SDmitry Chagin error = copyin(args->rqtp, &lrqts, sizeof(lrqts)); 61919e252baSAlexander Leidinger if (error != 0) { 62019e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error, 62119e252baSAlexander Leidinger error); 62219e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 62377424f41SJung-uk Kim return (error); 62419e252baSAlexander Leidinger } 625ad2056f2SAlexander Leidinger 626ad2056f2SAlexander Leidinger if (args->rmtp != NULL) 627ad2056f2SAlexander Leidinger rmtp = &rmts; 628ad2056f2SAlexander Leidinger else 629ad2056f2SAlexander Leidinger rmtp = NULL; 630ad2056f2SAlexander Leidinger 63177424f41SJung-uk Kim error = linux_to_native_timespec(&rqts, &lrqts); 63219e252baSAlexander Leidinger if (error != 0) { 63319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error, 63419e252baSAlexander Leidinger error); 63519e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 63677424f41SJung-uk Kim return (error); 63719e252baSAlexander Leidinger } 638f0f58384SDmitry Chagin error = kern_clock_nanosleep(td, clockid, flags, &rqts, rmtp); 639f0f58384SDmitry Chagin if (error == EINTR && (flags & TIMER_ABSTIME) == 0 && 640f0f58384SDmitry Chagin args->rmtp != NULL) { 6410670e972SDmitry Chagin error2 = native_to_linux_timespec(&lrmts, rmtp); 6420670e972SDmitry Chagin if (error2 != 0) 6430670e972SDmitry Chagin return (error2); 6445c2748d5SDmitry Chagin error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 6455c2748d5SDmitry Chagin if (error2 != 0) { 6465c2748d5SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep, 6475c2748d5SDmitry Chagin copyout_error, error2); 6485c2748d5SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep, 6495c2748d5SDmitry Chagin return, error2); 6505c2748d5SDmitry Chagin return (error2); 6515c2748d5SDmitry Chagin } 6525c2748d5SDmitry Chagin } 6535c2748d5SDmitry Chagin 65419e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 65577424f41SJung-uk Kim return (error); 65619e252baSAlexander Leidinger } 657