1ad2056f2SAlexander Leidinger /* $NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */ 2ad2056f2SAlexander Leidinger 3ad2056f2SAlexander Leidinger /*- 47f2d13d6SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-NetBSD 57f2d13d6SPedro F. Giffuni * 6ad2056f2SAlexander Leidinger * Copyright (c) 2001 The NetBSD Foundation, Inc. 7ad2056f2SAlexander Leidinger * All rights reserved. 8ad2056f2SAlexander Leidinger * 9ad2056f2SAlexander Leidinger * This code is derived from software contributed to The NetBSD Foundation 10ad2056f2SAlexander Leidinger * by Emmanuel Dreyfus. 11ad2056f2SAlexander Leidinger * 12ad2056f2SAlexander Leidinger * Redistribution and use in source and binary forms, with or without 13ad2056f2SAlexander Leidinger * modification, are permitted provided that the following conditions 14ad2056f2SAlexander Leidinger * are met: 15ad2056f2SAlexander Leidinger * 1. Redistributions of source code must retain the above copyright 16ad2056f2SAlexander Leidinger * notice, this list of conditions and the following disclaimer. 17ad2056f2SAlexander Leidinger * 2. Redistributions in binary form must reproduce the above copyright 18ad2056f2SAlexander Leidinger * notice, this list of conditions and the following disclaimer in the 19ad2056f2SAlexander Leidinger * documentation and/or other materials provided with the distribution. 20ad2056f2SAlexander Leidinger * 21ad2056f2SAlexander Leidinger * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 22ad2056f2SAlexander Leidinger * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 23ad2056f2SAlexander Leidinger * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24ad2056f2SAlexander Leidinger * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 25ad2056f2SAlexander Leidinger * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26ad2056f2SAlexander Leidinger * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27ad2056f2SAlexander Leidinger * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28ad2056f2SAlexander Leidinger * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29ad2056f2SAlexander Leidinger * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30ad2056f2SAlexander Leidinger * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31ad2056f2SAlexander Leidinger * POSSIBILITY OF SUCH DAMAGE. 32ad2056f2SAlexander Leidinger */ 33ad2056f2SAlexander Leidinger 34ad2056f2SAlexander Leidinger #include <sys/cdefs.h> 35ad2056f2SAlexander Leidinger __FBSDID("$FreeBSD$"); 36ad2056f2SAlexander Leidinger #if 0 37ad2056f2SAlexander Leidinger __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $"); 38ad2056f2SAlexander Leidinger #endif 39ad2056f2SAlexander Leidinger 40ad2056f2SAlexander Leidinger #include "opt_compat.h" 41ad2056f2SAlexander Leidinger 42ad2056f2SAlexander Leidinger #include <sys/param.h> 4319e252baSAlexander Leidinger #include <sys/kernel.h> 442711aba9SDmitry Chagin #include <sys/lock.h> 45ad2056f2SAlexander Leidinger #include <sys/ucred.h> 460670e972SDmitry Chagin #include <sys/limits.h> 47ad2056f2SAlexander Leidinger #include <sys/mount.h> 482711aba9SDmitry Chagin #include <sys/mutex.h> 492711aba9SDmitry Chagin #include <sys/resourcevar.h> 5019e252baSAlexander Leidinger #include <sys/sdt.h> 51ad2056f2SAlexander Leidinger #include <sys/signal.h> 52ad2056f2SAlexander Leidinger #include <sys/stdint.h> 53ad2056f2SAlexander Leidinger #include <sys/syscallsubr.h> 54ad2056f2SAlexander Leidinger #include <sys/sysproto.h> 55ad2056f2SAlexander Leidinger #include <sys/time.h> 56ad2056f2SAlexander Leidinger #include <sys/systm.h> 57ad2056f2SAlexander Leidinger #include <sys/proc.h> 58ad2056f2SAlexander Leidinger 59ad2056f2SAlexander Leidinger #ifdef COMPAT_LINUX32 60ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h> 61ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h> 62ad2056f2SAlexander Leidinger #else 63ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h> 64ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h> 65ad2056f2SAlexander Leidinger #endif 66ad2056f2SAlexander Leidinger 6719e252baSAlexander Leidinger #include <compat/linux/linux_dtrace.h> 687bc05ae6SDmitry Chagin #include <compat/linux/linux_misc.h> 692711aba9SDmitry Chagin #include <compat/linux/linux_timer.h> 704afe4faeSEdward Tomasz Napierala #include <compat/linux/linux_util.h> 7119e252baSAlexander Leidinger 7219e252baSAlexander Leidinger /* DTrace init */ 7319e252baSAlexander Leidinger LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); 7419e252baSAlexander Leidinger 7519e252baSAlexander Leidinger /** 7619e252baSAlexander Leidinger * DTrace probes in this module. 7719e252baSAlexander Leidinger */ 7819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid, 7919e252baSAlexander Leidinger "clockid_t"); 8019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid, 8119e252baSAlexander Leidinger "clockid_t"); 8299b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_gettime, conversion_error, "int"); 8319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int"); 8419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int"); 8599b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 8699b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, gettime_error, "int"); 8799b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, copyout_error, "int"); 8899b6f430SDmitry Chagin #endif 8919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int"); 9019f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, settime_error, "int"); 9119f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, conversion_error, "int"); 9219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int"); 9319f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 9419f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, conversion_error, "int"); 9519f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, copyin_error, "int"); 9619f9a0e4SDmitry Chagin #endif 97187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE0(time, linux_common_clock_getres, nullcall); 98187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, conversion_error, "int"); 99187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, getres_error, "int"); 10019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int"); 101187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 102187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres_time64, copyout_error, "int"); 103187715a4SDmitry Chagin #endif 10419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int"); 10519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int"); 10619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int"); 10719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int"); 10819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int"); 10919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int"); 110*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int"); 111*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int"); 112*6501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 113*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, conversion_error, "int"); 114*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int"); 115*6501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int"); 116*6501370aSDmitry Chagin #endif 11719e252baSAlexander Leidinger 11899b6f430SDmitry Chagin static int linux_common_clock_gettime(struct thread *, clockid_t, 11999b6f430SDmitry Chagin struct timespec *); 12019f9a0e4SDmitry Chagin static int linux_common_clock_settime(struct thread *, clockid_t, 12119f9a0e4SDmitry Chagin struct timespec *); 122187715a4SDmitry Chagin static int linux_common_clock_getres(struct thread *, clockid_t, 123187715a4SDmitry Chagin struct timespec *); 124*6501370aSDmitry Chagin static int linux_common_clock_nanosleep(struct thread *, clockid_t, 125*6501370aSDmitry Chagin l_int, struct timespec *, struct timespec *); 12699b6f430SDmitry Chagin 1270670e972SDmitry Chagin int 128ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp) 129ad2056f2SAlexander Leidinger { 13019e252baSAlexander Leidinger 1310670e972SDmitry Chagin #ifdef COMPAT_LINUX32 13271b50d08SDmitry Chagin if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN) 1330670e972SDmitry Chagin return (EOVERFLOW); 1340670e972SDmitry Chagin #endif 135ad2056f2SAlexander Leidinger ltp->tv_sec = ntp->tv_sec; 136ad2056f2SAlexander Leidinger ltp->tv_nsec = ntp->tv_nsec; 13719e252baSAlexander Leidinger 1380670e972SDmitry Chagin return (0); 139ad2056f2SAlexander Leidinger } 140ad2056f2SAlexander Leidinger 14168098228SDmitry Chagin int 142ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp) 143ad2056f2SAlexander Leidinger { 14419e252baSAlexander Leidinger 1455e8caee2SEdward Tomasz Napierala if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999) 14677424f41SJung-uk Kim return (EINVAL); 147ad2056f2SAlexander Leidinger ntp->tv_sec = ltp->tv_sec; 148ad2056f2SAlexander Leidinger ntp->tv_nsec = ltp->tv_nsec; 14977424f41SJung-uk Kim 15077424f41SJung-uk Kim return (0); 151ad2056f2SAlexander Leidinger } 152ad2056f2SAlexander Leidinger 153bfcce1a9SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 154bfcce1a9SDmitry Chagin int 155bfcce1a9SDmitry Chagin native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp) 156bfcce1a9SDmitry Chagin { 157bfcce1a9SDmitry Chagin 158bfcce1a9SDmitry Chagin ltp64->tv_sec = ntp->tv_sec; 159bfcce1a9SDmitry Chagin ltp64->tv_nsec = ntp->tv_nsec; 160bfcce1a9SDmitry Chagin 161bfcce1a9SDmitry Chagin return (0); 162bfcce1a9SDmitry Chagin } 163bfcce1a9SDmitry Chagin 164bfcce1a9SDmitry Chagin int 165bfcce1a9SDmitry Chagin linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64) 166bfcce1a9SDmitry Chagin { 167bfcce1a9SDmitry Chagin 168bfcce1a9SDmitry Chagin if (ltp64->tv_sec < 0 || ltp64->tv_nsec < 0 || ltp64->tv_nsec > 999999999) 169bfcce1a9SDmitry Chagin return (EINVAL); 170bfcce1a9SDmitry Chagin ntp->tv_sec = ltp64->tv_sec; 171bfcce1a9SDmitry Chagin ntp->tv_nsec = ltp64->tv_nsec; 172bfcce1a9SDmitry Chagin 173bfcce1a9SDmitry Chagin return (0); 174bfcce1a9SDmitry Chagin } 175bfcce1a9SDmitry Chagin #endif 176bfcce1a9SDmitry Chagin 17716ac71bcSDmitry Chagin int 178dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp) 179dd93b628SDmitry Chagin { 180dd93b628SDmitry Chagin int error; 181dd93b628SDmitry Chagin 182dd93b628SDmitry Chagin error = native_to_linux_timespec(<p->it_interval, &ntp->it_interval); 183dd93b628SDmitry Chagin if (error == 0) 184dd93b628SDmitry Chagin error = native_to_linux_timespec(<p->it_value, &ntp->it_interval); 185dd93b628SDmitry Chagin return (error); 186dd93b628SDmitry Chagin } 187dd93b628SDmitry Chagin 188dd93b628SDmitry Chagin int 189dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp) 190dd93b628SDmitry Chagin { 191dd93b628SDmitry Chagin int error; 192dd93b628SDmitry Chagin 193dd93b628SDmitry Chagin error = linux_to_native_timespec(&ntp->it_interval, <p->it_interval); 194dd93b628SDmitry Chagin if (error == 0) 195dd93b628SDmitry Chagin error = linux_to_native_timespec(&ntp->it_value, <p->it_value); 196dd93b628SDmitry Chagin return (error); 197dd93b628SDmitry Chagin } 198dd93b628SDmitry Chagin 199dd93b628SDmitry Chagin int 200ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l) 201ad2056f2SAlexander Leidinger { 20219e252baSAlexander Leidinger 2032711aba9SDmitry Chagin if (l < 0) { 2042711aba9SDmitry Chagin /* cpu-clock */ 2052711aba9SDmitry Chagin if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD) 2062711aba9SDmitry Chagin return (EINVAL); 2072711aba9SDmitry Chagin if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX) 2082711aba9SDmitry Chagin return (EINVAL); 2092711aba9SDmitry Chagin 2102711aba9SDmitry Chagin if (LINUX_CPUCLOCK_PERTHREAD(l)) 2112711aba9SDmitry Chagin *n = CLOCK_THREAD_CPUTIME_ID; 2122711aba9SDmitry Chagin else 2132711aba9SDmitry Chagin *n = CLOCK_PROCESS_CPUTIME_ID; 2142711aba9SDmitry Chagin return (0); 2152711aba9SDmitry Chagin } 2162711aba9SDmitry Chagin 217ad2056f2SAlexander Leidinger switch (l) { 218ad2056f2SAlexander Leidinger case LINUX_CLOCK_REALTIME: 219ad2056f2SAlexander Leidinger *n = CLOCK_REALTIME; 220ad2056f2SAlexander Leidinger break; 221ad2056f2SAlexander Leidinger case LINUX_CLOCK_MONOTONIC: 222ad2056f2SAlexander Leidinger *n = CLOCK_MONOTONIC; 223ad2056f2SAlexander Leidinger break; 2247bc05ae6SDmitry Chagin case LINUX_CLOCK_PROCESS_CPUTIME_ID: 2257bc05ae6SDmitry Chagin *n = CLOCK_PROCESS_CPUTIME_ID; 2267bc05ae6SDmitry Chagin break; 2277bc05ae6SDmitry Chagin case LINUX_CLOCK_THREAD_CPUTIME_ID: 2287bc05ae6SDmitry Chagin *n = CLOCK_THREAD_CPUTIME_ID; 2297bc05ae6SDmitry Chagin break; 2302711aba9SDmitry Chagin case LINUX_CLOCK_REALTIME_COARSE: 2312711aba9SDmitry Chagin *n = CLOCK_REALTIME_FAST; 2322711aba9SDmitry Chagin break; 2332711aba9SDmitry Chagin case LINUX_CLOCK_MONOTONIC_COARSE: 234e37db348SAlexander Leidinger case LINUX_CLOCK_MONOTONIC_RAW: 2352711aba9SDmitry Chagin *n = CLOCK_MONOTONIC_FAST; 2362711aba9SDmitry Chagin break; 2372711aba9SDmitry Chagin case LINUX_CLOCK_BOOTTIME: 23825ada637SDmitry Chagin *n = CLOCK_UPTIME; 23925ada637SDmitry Chagin break; 2402711aba9SDmitry Chagin case LINUX_CLOCK_REALTIME_ALARM: 2412711aba9SDmitry Chagin case LINUX_CLOCK_BOOTTIME_ALARM: 2422711aba9SDmitry Chagin case LINUX_CLOCK_SGI_CYCLE: 2432711aba9SDmitry Chagin case LINUX_CLOCK_TAI: 24419e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, 24519e252baSAlexander Leidinger unsupported_clockid, l); 24619e252baSAlexander Leidinger return (EINVAL); 24777424f41SJung-uk Kim default: 24819e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, 24919e252baSAlexander Leidinger unknown_clockid, l); 25077424f41SJung-uk Kim return (EINVAL); 251ad2056f2SAlexander Leidinger } 252ad2056f2SAlexander Leidinger 25377424f41SJung-uk Kim return (0); 254ad2056f2SAlexander Leidinger } 255ad2056f2SAlexander Leidinger 256ad2056f2SAlexander Leidinger int 257f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags) 258f0f58384SDmitry Chagin { 259f0f58384SDmitry Chagin 260f0f58384SDmitry Chagin if (flags & ~LINUX_TIMER_ABSTIME) 261f0f58384SDmitry Chagin return (EINVAL); 262f0f58384SDmitry Chagin *nflags = 0; 263f0f58384SDmitry Chagin if (flags & LINUX_TIMER_ABSTIME) 264f0f58384SDmitry Chagin *nflags |= TIMER_ABSTIME; 265f0f58384SDmitry Chagin return (0); 266f0f58384SDmitry Chagin } 267f0f58384SDmitry Chagin 26899b6f430SDmitry Chagin static int 26999b6f430SDmitry Chagin linux_common_clock_gettime(struct thread *td, clockid_t which, 27099b6f430SDmitry Chagin struct timespec *tp) 271ad2056f2SAlexander Leidinger { 2722711aba9SDmitry Chagin struct rusage ru; 2732711aba9SDmitry Chagin struct thread *targettd; 2742711aba9SDmitry Chagin struct proc *p; 2752711aba9SDmitry Chagin int error, clockwhich; 2762506c761SDmitry Chagin clockid_t nwhich; 2772711aba9SDmitry Chagin pid_t pid; 2782711aba9SDmitry Chagin lwpid_t tid; 279ad2056f2SAlexander Leidinger 28099b6f430SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 28119e252baSAlexander Leidinger if (error != 0) { 2824afe4faeSEdward Tomasz Napierala linux_msg(curthread, 28399b6f430SDmitry Chagin "unsupported clock_gettime clockid %d", which); 28499b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_gettime, 28599b6f430SDmitry Chagin conversion_error, error); 28677424f41SJung-uk Kim return (error); 28719e252baSAlexander Leidinger } 2882711aba9SDmitry Chagin 2892711aba9SDmitry Chagin switch (nwhich) { 2902711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 29199b6f430SDmitry Chagin if (which < 0) { 29299b6f430SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 29399b6f430SDmitry Chagin pid = LINUX_CPUCLOCK_ID(which); 2947bc05ae6SDmitry Chagin } else { 2957bc05ae6SDmitry Chagin clockwhich = LINUX_CPUCLOCK_SCHED; 2967bc05ae6SDmitry Chagin pid = 0; 2977bc05ae6SDmitry Chagin } 2982711aba9SDmitry Chagin if (pid == 0) { 2992711aba9SDmitry Chagin p = td->td_proc; 3002711aba9SDmitry Chagin PROC_LOCK(p); 3012711aba9SDmitry Chagin } else { 3022711aba9SDmitry Chagin error = pget(pid, PGET_CANSEE, &p); 3032711aba9SDmitry Chagin if (error != 0) 3042711aba9SDmitry Chagin return (EINVAL); 3052711aba9SDmitry Chagin } 3062711aba9SDmitry Chagin switch (clockwhich) { 3072711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 3082711aba9SDmitry Chagin PROC_STATLOCK(p); 3092711aba9SDmitry Chagin calcru(p, &ru.ru_utime, &ru.ru_stime); 3102711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3112711aba9SDmitry Chagin PROC_UNLOCK(p); 3122711aba9SDmitry Chagin timevaladd(&ru.ru_utime, &ru.ru_stime); 31399b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 3142711aba9SDmitry Chagin break; 3152711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 3162711aba9SDmitry Chagin PROC_STATLOCK(p); 3172711aba9SDmitry Chagin calcru(p, &ru.ru_utime, &ru.ru_stime); 3182711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3192711aba9SDmitry Chagin PROC_UNLOCK(p); 32099b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 3212711aba9SDmitry Chagin break; 3222711aba9SDmitry Chagin case LINUX_CPUCLOCK_SCHED: 32399b6f430SDmitry Chagin kern_process_cputime(p, tp); 3242711aba9SDmitry Chagin PROC_UNLOCK(p); 3252711aba9SDmitry Chagin break; 3262711aba9SDmitry Chagin default: 3272711aba9SDmitry Chagin PROC_UNLOCK(p); 3282711aba9SDmitry Chagin return (EINVAL); 3292711aba9SDmitry Chagin } 3302711aba9SDmitry Chagin 3312711aba9SDmitry Chagin break; 3322711aba9SDmitry Chagin 3332711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 33499b6f430SDmitry Chagin if (which < 0) { 33599b6f430SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 33699b6f430SDmitry Chagin tid = LINUX_CPUCLOCK_ID(which); 3377bc05ae6SDmitry Chagin } else { 3387bc05ae6SDmitry Chagin clockwhich = LINUX_CPUCLOCK_SCHED; 3397bc05ae6SDmitry Chagin tid = 0; 3407bc05ae6SDmitry Chagin } 3417bc05ae6SDmitry Chagin p = td->td_proc; 3422711aba9SDmitry Chagin if (tid == 0) { 3432711aba9SDmitry Chagin targettd = td; 3442711aba9SDmitry Chagin PROC_LOCK(p); 3452711aba9SDmitry Chagin } else { 3467bc05ae6SDmitry Chagin targettd = linux_tdfind(td, tid, p->p_pid); 3472711aba9SDmitry Chagin if (targettd == NULL) 3482711aba9SDmitry Chagin return (EINVAL); 3492711aba9SDmitry Chagin } 3502711aba9SDmitry Chagin switch (clockwhich) { 3512711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 3522711aba9SDmitry Chagin PROC_STATLOCK(p); 3532711aba9SDmitry Chagin thread_lock(targettd); 3542711aba9SDmitry Chagin rufetchtd(targettd, &ru); 3552711aba9SDmitry Chagin thread_unlock(targettd); 3562711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3572711aba9SDmitry Chagin PROC_UNLOCK(p); 3582711aba9SDmitry Chagin timevaladd(&ru.ru_utime, &ru.ru_stime); 35999b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 3602711aba9SDmitry Chagin break; 3612711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 3622711aba9SDmitry Chagin PROC_STATLOCK(p); 3632711aba9SDmitry Chagin thread_lock(targettd); 3642711aba9SDmitry Chagin rufetchtd(targettd, &ru); 3652711aba9SDmitry Chagin thread_unlock(targettd); 3662711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3672711aba9SDmitry Chagin PROC_UNLOCK(p); 36899b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 3692711aba9SDmitry Chagin break; 3702711aba9SDmitry Chagin case LINUX_CPUCLOCK_SCHED: 3717bc05ae6SDmitry Chagin if (td == targettd) 3727bc05ae6SDmitry Chagin targettd = NULL; 37399b6f430SDmitry Chagin kern_thread_cputime(targettd, tp); 3742711aba9SDmitry Chagin PROC_UNLOCK(p); 3752711aba9SDmitry Chagin break; 3762711aba9SDmitry Chagin default: 3772711aba9SDmitry Chagin PROC_UNLOCK(p); 3782711aba9SDmitry Chagin return (EINVAL); 3792711aba9SDmitry Chagin } 3802711aba9SDmitry Chagin break; 3812711aba9SDmitry Chagin 3822711aba9SDmitry Chagin default: 38399b6f430SDmitry Chagin error = kern_clock_gettime(td, nwhich, tp); 3842711aba9SDmitry Chagin break; 3852711aba9SDmitry Chagin } 38699b6f430SDmitry Chagin 38799b6f430SDmitry Chagin return (error); 38899b6f430SDmitry Chagin } 38999b6f430SDmitry Chagin 39099b6f430SDmitry Chagin int 39199b6f430SDmitry Chagin linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args) 39299b6f430SDmitry Chagin { 39399b6f430SDmitry Chagin struct l_timespec lts; 39499b6f430SDmitry Chagin struct timespec tp; 39599b6f430SDmitry Chagin int error; 39699b6f430SDmitry Chagin 39799b6f430SDmitry Chagin error = linux_common_clock_gettime(td, args->which, &tp); 39819e252baSAlexander Leidinger if (error != 0) { 39919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error); 40077424f41SJung-uk Kim return (error); 40119e252baSAlexander Leidinger } 4020670e972SDmitry Chagin error = native_to_linux_timespec(<s, &tp); 4030670e972SDmitry Chagin if (error != 0) 4040670e972SDmitry Chagin return (error); 40599b6f430SDmitry Chagin error = copyout(<s, args->tp, sizeof(lts)); 40619e252baSAlexander Leidinger if (error != 0) 40719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error); 40819e252baSAlexander Leidinger 40919e252baSAlexander Leidinger return (error); 410ad2056f2SAlexander Leidinger } 411ad2056f2SAlexander Leidinger 41299b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 41399b6f430SDmitry Chagin int 41499b6f430SDmitry Chagin linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args) 41599b6f430SDmitry Chagin { 41699b6f430SDmitry Chagin struct l_timespec64 lts; 41799b6f430SDmitry Chagin struct timespec tp; 41899b6f430SDmitry Chagin int error; 41999b6f430SDmitry Chagin 42099b6f430SDmitry Chagin error = linux_common_clock_gettime(td, args->which, &tp); 42199b6f430SDmitry Chagin if (error != 0) { 42299b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error); 42399b6f430SDmitry Chagin return (error); 42499b6f430SDmitry Chagin } 42599b6f430SDmitry Chagin error = native_to_linux_timespec64(<s, &tp); 42699b6f430SDmitry Chagin if (error != 0) 42799b6f430SDmitry Chagin return (error); 42899b6f430SDmitry Chagin error = copyout(<s, args->tp, sizeof(lts)); 42999b6f430SDmitry Chagin if (error != 0) 43099b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error); 43199b6f430SDmitry Chagin 43299b6f430SDmitry Chagin return (error); 43399b6f430SDmitry Chagin } 43499b6f430SDmitry Chagin #endif 43599b6f430SDmitry Chagin 43619f9a0e4SDmitry Chagin static int 43719f9a0e4SDmitry Chagin linux_common_clock_settime(struct thread *td, clockid_t which, 43819f9a0e4SDmitry Chagin struct timespec *ts) 43919f9a0e4SDmitry Chagin { 44019f9a0e4SDmitry Chagin int error; 44119f9a0e4SDmitry Chagin clockid_t nwhich; 44219f9a0e4SDmitry Chagin 44319f9a0e4SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 44419f9a0e4SDmitry Chagin if (error != 0) { 44519f9a0e4SDmitry Chagin linux_msg(curthread, 44619f9a0e4SDmitry Chagin "unsupported clock_settime clockid %d", which); 44719f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error, 44819f9a0e4SDmitry Chagin error); 44919f9a0e4SDmitry Chagin return (error); 45019f9a0e4SDmitry Chagin } 45119f9a0e4SDmitry Chagin 45219f9a0e4SDmitry Chagin error = kern_clock_settime(td, nwhich, ts); 45319f9a0e4SDmitry Chagin if (error != 0) 45419f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_settime, 45519f9a0e4SDmitry Chagin settime_error, error); 45619f9a0e4SDmitry Chagin 45719f9a0e4SDmitry Chagin return (error); 45819f9a0e4SDmitry Chagin } 45919f9a0e4SDmitry Chagin 460ad2056f2SAlexander Leidinger int 461ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args) 462ad2056f2SAlexander Leidinger { 463ad2056f2SAlexander Leidinger struct timespec ts; 464ad2056f2SAlexander Leidinger struct l_timespec lts; 465ad2056f2SAlexander Leidinger int error; 466ad2056f2SAlexander Leidinger 46719f9a0e4SDmitry Chagin error = copyin(args->tp, <s, sizeof(lts)); 46819e252baSAlexander Leidinger if (error != 0) { 46919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error); 47019e252baSAlexander Leidinger return (error); 47119e252baSAlexander Leidinger } 47219e252baSAlexander Leidinger error = linux_to_native_timespec(&ts, <s); 47319f9a0e4SDmitry Chagin if (error != 0) 47419e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error, 47519e252baSAlexander Leidinger error); 47619f9a0e4SDmitry Chagin 47719f9a0e4SDmitry Chagin return (linux_common_clock_settime(td, args->which, &ts)); 47819e252baSAlexander Leidinger } 47919e252baSAlexander Leidinger 48019f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 48119f9a0e4SDmitry Chagin int 48219f9a0e4SDmitry Chagin linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args) 48319f9a0e4SDmitry Chagin { 48419f9a0e4SDmitry Chagin struct timespec ts; 48519f9a0e4SDmitry Chagin struct l_timespec64 lts; 48619f9a0e4SDmitry Chagin int error; 48719f9a0e4SDmitry Chagin 48819f9a0e4SDmitry Chagin error = copyin(args->tp, <s, sizeof(lts)); 48919f9a0e4SDmitry Chagin if (error != 0) { 49019f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error); 49119f9a0e4SDmitry Chagin return (error); 49219f9a0e4SDmitry Chagin } 49319f9a0e4SDmitry Chagin error = linux_to_native_timespec64(&ts, <s); 49419e252baSAlexander Leidinger if (error != 0) 49519f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_settime64, conversion_error, 49619f9a0e4SDmitry Chagin error); 49719f9a0e4SDmitry Chagin return (linux_common_clock_settime(td, args->which, &ts)); 498ad2056f2SAlexander Leidinger } 49919f9a0e4SDmitry Chagin #endif 500ad2056f2SAlexander Leidinger 501187715a4SDmitry Chagin static int 502187715a4SDmitry Chagin linux_common_clock_getres(struct thread *td, clockid_t which, 503187715a4SDmitry Chagin struct timespec *ts) 504ad2056f2SAlexander Leidinger { 5052711aba9SDmitry Chagin struct proc *p; 5062711aba9SDmitry Chagin int error, clockwhich; 5072506c761SDmitry Chagin clockid_t nwhich; 5082711aba9SDmitry Chagin pid_t pid; 5092711aba9SDmitry Chagin lwpid_t tid; 510ad2056f2SAlexander Leidinger 511187715a4SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 51219e252baSAlexander Leidinger if (error != 0) { 5134afe4faeSEdward Tomasz Napierala linux_msg(curthread, 514187715a4SDmitry Chagin "unsupported clock_getres clockid %d", which); 515187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_getres, 516187715a4SDmitry Chagin conversion_error, error); 51777424f41SJung-uk Kim return (error); 51819e252baSAlexander Leidinger } 5192711aba9SDmitry Chagin 5202711aba9SDmitry Chagin /* 5212711aba9SDmitry Chagin * Check user supplied clock id in case of per-process 5222711aba9SDmitry Chagin * or thread-specific cpu-time clock. 5232711aba9SDmitry Chagin */ 524187715a4SDmitry Chagin if (which < 0) { 5252711aba9SDmitry Chagin switch (nwhich) { 5262711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 527187715a4SDmitry Chagin tid = LINUX_CPUCLOCK_ID(which); 5282711aba9SDmitry Chagin if (tid != 0) { 5292711aba9SDmitry Chagin p = td->td_proc; 5307bc05ae6SDmitry Chagin if (linux_tdfind(td, tid, p->p_pid) == NULL) 5317bc05ae6SDmitry Chagin return (EINVAL); 5322711aba9SDmitry Chagin PROC_UNLOCK(p); 5332711aba9SDmitry Chagin } 5342711aba9SDmitry Chagin break; 5352711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 536187715a4SDmitry Chagin pid = LINUX_CPUCLOCK_ID(which); 5372711aba9SDmitry Chagin if (pid != 0) { 5382711aba9SDmitry Chagin error = pget(pid, PGET_CANSEE, &p); 5392711aba9SDmitry Chagin if (error != 0) 5402711aba9SDmitry Chagin return (EINVAL); 5412711aba9SDmitry Chagin PROC_UNLOCK(p); 5422711aba9SDmitry Chagin } 5432711aba9SDmitry Chagin break; 5442711aba9SDmitry Chagin } 5457bc05ae6SDmitry Chagin } 5462711aba9SDmitry Chagin 547187715a4SDmitry Chagin if (ts == NULL) { 548187715a4SDmitry Chagin LIN_SDT_PROBE0(time, linux_common_clock_getres, nullcall); 5492711aba9SDmitry Chagin return (0); 5502711aba9SDmitry Chagin } 5512711aba9SDmitry Chagin 5522711aba9SDmitry Chagin switch (nwhich) { 5532711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 5542711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 555187715a4SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 5567bc05ae6SDmitry Chagin /* 5577bc05ae6SDmitry Chagin * In both cases (when the clock id obtained by a call to 5587bc05ae6SDmitry Chagin * clock_getcpuclockid() or using the clock 5597bc05ae6SDmitry Chagin * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision 5607bc05ae6SDmitry Chagin * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock. 5617bc05ae6SDmitry Chagin * 5627bc05ae6SDmitry Chagin * See Linux posix_cpu_clock_getres() implementation. 5637bc05ae6SDmitry Chagin */ 564187715a4SDmitry Chagin if (which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) { 565187715a4SDmitry Chagin ts->tv_sec = 0; 566187715a4SDmitry Chagin ts->tv_nsec = 1; 5677bc05ae6SDmitry Chagin goto out; 5687bc05ae6SDmitry Chagin } 5697bc05ae6SDmitry Chagin 5702711aba9SDmitry Chagin switch (clockwhich) { 5712711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 5722711aba9SDmitry Chagin nwhich = CLOCK_PROF; 5732711aba9SDmitry Chagin break; 5742711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 5752711aba9SDmitry Chagin nwhich = CLOCK_VIRTUAL; 5762711aba9SDmitry Chagin break; 5772711aba9SDmitry Chagin default: 5782711aba9SDmitry Chagin return (EINVAL); 5792711aba9SDmitry Chagin } 5802711aba9SDmitry Chagin break; 5812711aba9SDmitry Chagin 5822711aba9SDmitry Chagin default: 5832711aba9SDmitry Chagin break; 5842711aba9SDmitry Chagin } 585187715a4SDmitry Chagin error = kern_clock_getres(td, nwhich, ts); 58619e252baSAlexander Leidinger if (error != 0) { 587187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_getres, 588187715a4SDmitry Chagin getres_error, error); 58977424f41SJung-uk Kim return (error); 59019e252baSAlexander Leidinger } 5917bc05ae6SDmitry Chagin 5927bc05ae6SDmitry Chagin out: 593187715a4SDmitry Chagin return (error); 594187715a4SDmitry Chagin } 595187715a4SDmitry Chagin 596187715a4SDmitry Chagin int 597187715a4SDmitry Chagin linux_clock_getres(struct thread *td, 598187715a4SDmitry Chagin struct linux_clock_getres_args *args) 599187715a4SDmitry Chagin { 600187715a4SDmitry Chagin struct timespec ts; 601187715a4SDmitry Chagin struct l_timespec lts; 602187715a4SDmitry Chagin int error; 603187715a4SDmitry Chagin 604187715a4SDmitry Chagin error = linux_common_clock_getres(td, args->which, &ts); 605187715a4SDmitry Chagin if (error != 0 || args->tp == NULL) 606187715a4SDmitry Chagin return (error); 607187715a4SDmitry Chagin 6080670e972SDmitry Chagin error = native_to_linux_timespec(<s, &ts); 6090670e972SDmitry Chagin if (error != 0) 6100670e972SDmitry Chagin return (error); 611187715a4SDmitry Chagin error = copyout(<s, args->tp, sizeof(lts)); 61219e252baSAlexander Leidinger if (error != 0) 613187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_getres, 614187715a4SDmitry Chagin copyout_error, error); 61519e252baSAlexander Leidinger return (error); 61677424f41SJung-uk Kim } 61777424f41SJung-uk Kim 618187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 619187715a4SDmitry Chagin int 620187715a4SDmitry Chagin linux_clock_getres_time64(struct thread *td, 621187715a4SDmitry Chagin struct linux_clock_getres_time64_args *args) 622187715a4SDmitry Chagin { 623187715a4SDmitry Chagin struct timespec ts; 624187715a4SDmitry Chagin struct l_timespec64 lts; 625187715a4SDmitry Chagin int error; 626187715a4SDmitry Chagin 627187715a4SDmitry Chagin error = linux_common_clock_getres(td, args->which, &ts); 628187715a4SDmitry Chagin if (error != 0 || args->tp == NULL) 629187715a4SDmitry Chagin return (error); 630187715a4SDmitry Chagin 631187715a4SDmitry Chagin error = native_to_linux_timespec64(<s, &ts); 632187715a4SDmitry Chagin if (error != 0) 633187715a4SDmitry Chagin return (error); 634187715a4SDmitry Chagin error = copyout(<s, args->tp, sizeof(lts)); 635187715a4SDmitry Chagin if (error != 0) 636187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_getres_time64, 637187715a4SDmitry Chagin copyout_error, error); 638187715a4SDmitry Chagin return (error); 639187715a4SDmitry Chagin } 640187715a4SDmitry Chagin #endif 641187715a4SDmitry Chagin 64277424f41SJung-uk Kim int 64377424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args) 64477424f41SJung-uk Kim { 64577424f41SJung-uk Kim struct timespec *rmtp; 64677424f41SJung-uk Kim struct l_timespec lrqts, lrmts; 64777424f41SJung-uk Kim struct timespec rqts, rmts; 6485c2748d5SDmitry Chagin int error, error2; 64977424f41SJung-uk Kim 65077424f41SJung-uk Kim error = copyin(args->rqtp, &lrqts, sizeof lrqts); 65119e252baSAlexander Leidinger if (error != 0) { 65219e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error); 65377424f41SJung-uk Kim return (error); 65419e252baSAlexander Leidinger } 65577424f41SJung-uk Kim 65677424f41SJung-uk Kim if (args->rmtp != NULL) 65777424f41SJung-uk Kim rmtp = &rmts; 65877424f41SJung-uk Kim else 65977424f41SJung-uk Kim rmtp = NULL; 66077424f41SJung-uk Kim 66177424f41SJung-uk Kim error = linux_to_native_timespec(&rqts, &lrqts); 66219e252baSAlexander Leidinger if (error != 0) { 66319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error); 66477424f41SJung-uk Kim return (error); 66519e252baSAlexander Leidinger } 66677424f41SJung-uk Kim error = kern_nanosleep(td, &rqts, rmtp); 6674cf66812SEric van Gyzen if (error == EINTR && args->rmtp != NULL) { 6680670e972SDmitry Chagin error2 = native_to_linux_timespec(&lrmts, rmtp); 6690670e972SDmitry Chagin if (error2 != 0) 6700670e972SDmitry Chagin return (error2); 6715c2748d5SDmitry Chagin error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 6725c2748d5SDmitry Chagin if (error2 != 0) { 67319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error, 6745c2748d5SDmitry Chagin error2); 6755c2748d5SDmitry Chagin return (error2); 67677424f41SJung-uk Kim } 67719e252baSAlexander Leidinger } 67877424f41SJung-uk Kim 6795c2748d5SDmitry Chagin return (error); 680ad2056f2SAlexander Leidinger } 681ad2056f2SAlexander Leidinger 682*6501370aSDmitry Chagin static int 683*6501370aSDmitry Chagin linux_common_clock_nanosleep(struct thread *td, clockid_t which, 684*6501370aSDmitry Chagin l_int lflags, struct timespec *rqtp, struct timespec *rmtp) 685*6501370aSDmitry Chagin { 686*6501370aSDmitry Chagin int error, flags; 687*6501370aSDmitry Chagin clockid_t clockid; 688*6501370aSDmitry Chagin 689*6501370aSDmitry Chagin error = linux_to_native_timerflags(&flags, lflags); 690*6501370aSDmitry Chagin if (error != 0) { 691*6501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_nanosleep, 692*6501370aSDmitry Chagin unsupported_flags, lflags); 693*6501370aSDmitry Chagin return (error); 694*6501370aSDmitry Chagin } 695*6501370aSDmitry Chagin 696*6501370aSDmitry Chagin error = linux_to_native_clockid(&clockid, which); 697*6501370aSDmitry Chagin if (error != 0) { 698*6501370aSDmitry Chagin linux_msg(curthread, 699*6501370aSDmitry Chagin "unsupported clock_nanosleep clockid %d", which); 700*6501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_nanosleep, 701*6501370aSDmitry Chagin unsupported_clockid, which); 702*6501370aSDmitry Chagin return (error); 703*6501370aSDmitry Chagin } 704*6501370aSDmitry Chagin 705*6501370aSDmitry Chagin return (kern_clock_nanosleep(td, clockid, flags, rqtp, rmtp)); 706*6501370aSDmitry Chagin } 707*6501370aSDmitry Chagin 708ad2056f2SAlexander Leidinger int 709*6501370aSDmitry Chagin linux_clock_nanosleep(struct thread *td, 710*6501370aSDmitry Chagin struct linux_clock_nanosleep_args *args) 711ad2056f2SAlexander Leidinger { 712ad2056f2SAlexander Leidinger struct timespec *rmtp; 713ad2056f2SAlexander Leidinger struct l_timespec lrqts, lrmts; 714ad2056f2SAlexander Leidinger struct timespec rqts, rmts; 715*6501370aSDmitry Chagin int error, error2; 716ad2056f2SAlexander Leidinger 7175c2748d5SDmitry Chagin error = copyin(args->rqtp, &lrqts, sizeof(lrqts)); 71819e252baSAlexander Leidinger if (error != 0) { 71919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error, 72019e252baSAlexander Leidinger error); 72177424f41SJung-uk Kim return (error); 72219e252baSAlexander Leidinger } 723ad2056f2SAlexander Leidinger 724*6501370aSDmitry Chagin error = linux_to_native_timespec(&rqts, &lrqts); 725*6501370aSDmitry Chagin if (error != 0) { 726*6501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error, 727*6501370aSDmitry Chagin error); 728*6501370aSDmitry Chagin return (error); 729*6501370aSDmitry Chagin } 730*6501370aSDmitry Chagin 731ad2056f2SAlexander Leidinger if (args->rmtp != NULL) 732ad2056f2SAlexander Leidinger rmtp = &rmts; 733ad2056f2SAlexander Leidinger else 734ad2056f2SAlexander Leidinger rmtp = NULL; 735ad2056f2SAlexander Leidinger 736*6501370aSDmitry Chagin error = linux_common_clock_nanosleep(td, args->which, args->flags, 737*6501370aSDmitry Chagin &rqts, rmtp); 738*6501370aSDmitry Chagin if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 && 739f0f58384SDmitry Chagin args->rmtp != NULL) { 7400670e972SDmitry Chagin error2 = native_to_linux_timespec(&lrmts, rmtp); 7410670e972SDmitry Chagin if (error2 != 0) 7420670e972SDmitry Chagin return (error2); 7435c2748d5SDmitry Chagin error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 7445c2748d5SDmitry Chagin if (error2 != 0) { 7455c2748d5SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep, 7465c2748d5SDmitry Chagin copyout_error, error2); 7475c2748d5SDmitry Chagin return (error2); 7485c2748d5SDmitry Chagin } 7495c2748d5SDmitry Chagin } 75077424f41SJung-uk Kim return (error); 75119e252baSAlexander Leidinger } 752*6501370aSDmitry Chagin 753*6501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 754*6501370aSDmitry Chagin int 755*6501370aSDmitry Chagin linux_clock_nanosleep_time64(struct thread *td, 756*6501370aSDmitry Chagin struct linux_clock_nanosleep_time64_args *args) 757*6501370aSDmitry Chagin { 758*6501370aSDmitry Chagin struct timespec *rmtp; 759*6501370aSDmitry Chagin struct l_timespec64 lrqts, lrmts; 760*6501370aSDmitry Chagin struct timespec rqts, rmts; 761*6501370aSDmitry Chagin int error, error2; 762*6501370aSDmitry Chagin 763*6501370aSDmitry Chagin error = copyin(args->rqtp, &lrqts, sizeof(lrqts)); 764*6501370aSDmitry Chagin if (error != 0) { 765*6501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64, 766*6501370aSDmitry Chagin copyin_error, error); 767*6501370aSDmitry Chagin return (error); 768*6501370aSDmitry Chagin } 769*6501370aSDmitry Chagin 770*6501370aSDmitry Chagin error = linux_to_native_timespec64(&rqts, &lrqts); 771*6501370aSDmitry Chagin if (error != 0) { 772*6501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64, 773*6501370aSDmitry Chagin conversion_error, error); 774*6501370aSDmitry Chagin return (error); 775*6501370aSDmitry Chagin } 776*6501370aSDmitry Chagin 777*6501370aSDmitry Chagin if (args->rmtp != NULL) 778*6501370aSDmitry Chagin rmtp = &rmts; 779*6501370aSDmitry Chagin else 780*6501370aSDmitry Chagin rmtp = NULL; 781*6501370aSDmitry Chagin 782*6501370aSDmitry Chagin error = linux_common_clock_nanosleep(td, args->which, args->flags, 783*6501370aSDmitry Chagin &rqts, rmtp); 784*6501370aSDmitry Chagin if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 && 785*6501370aSDmitry Chagin args->rmtp != NULL) { 786*6501370aSDmitry Chagin error2 = native_to_linux_timespec64(&lrmts, rmtp); 787*6501370aSDmitry Chagin if (error2 != 0) 788*6501370aSDmitry Chagin return (error2); 789*6501370aSDmitry Chagin error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 790*6501370aSDmitry Chagin if (error2 != 0) { 791*6501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64, 792*6501370aSDmitry Chagin copyout_error, error2); 793*6501370aSDmitry Chagin return (error2); 794*6501370aSDmitry Chagin } 795*6501370aSDmitry Chagin } 796*6501370aSDmitry Chagin return (error); 797*6501370aSDmitry Chagin } 798*6501370aSDmitry Chagin #endif 799