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, copyout_error, "int"); 10519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int"); 10619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int"); 10719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int"); 1086501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int"); 1096501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int"); 1106501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1116501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int"); 1126501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int"); 1136501370aSDmitry Chagin #endif 11419e252baSAlexander Leidinger 11599b6f430SDmitry Chagin static int linux_common_clock_gettime(struct thread *, clockid_t, 11699b6f430SDmitry Chagin struct timespec *); 11719f9a0e4SDmitry Chagin static int linux_common_clock_settime(struct thread *, clockid_t, 11819f9a0e4SDmitry Chagin struct timespec *); 119187715a4SDmitry Chagin static int linux_common_clock_getres(struct thread *, clockid_t, 120187715a4SDmitry Chagin struct timespec *); 1216501370aSDmitry Chagin static int linux_common_clock_nanosleep(struct thread *, clockid_t, 1226501370aSDmitry Chagin l_int, struct timespec *, struct timespec *); 12399b6f430SDmitry Chagin 1240670e972SDmitry Chagin int 125ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp) 126ad2056f2SAlexander Leidinger { 12719e252baSAlexander Leidinger 1280670e972SDmitry Chagin #ifdef COMPAT_LINUX32 12971b50d08SDmitry Chagin if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN) 1300670e972SDmitry Chagin return (EOVERFLOW); 1310670e972SDmitry Chagin #endif 132ad2056f2SAlexander Leidinger ltp->tv_sec = ntp->tv_sec; 133ad2056f2SAlexander Leidinger ltp->tv_nsec = ntp->tv_nsec; 13419e252baSAlexander Leidinger 1350670e972SDmitry Chagin return (0); 136ad2056f2SAlexander Leidinger } 137ad2056f2SAlexander Leidinger 13868098228SDmitry Chagin int 139ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp) 140ad2056f2SAlexander Leidinger { 14119e252baSAlexander Leidinger 14291e7bdcdSDmitry Chagin if (!timespecvalid_interval(ltp)) 14377424f41SJung-uk Kim return (EINVAL); 144ad2056f2SAlexander Leidinger ntp->tv_sec = ltp->tv_sec; 145ad2056f2SAlexander Leidinger ntp->tv_nsec = ltp->tv_nsec; 14677424f41SJung-uk Kim 14777424f41SJung-uk Kim return (0); 148ad2056f2SAlexander Leidinger } 149ad2056f2SAlexander Leidinger 1509a9482f8SDmitry Chagin int 1519a9482f8SDmitry Chagin linux_put_timespec(struct timespec *ntp, struct l_timespec *ltp) 1529a9482f8SDmitry Chagin { 1539a9482f8SDmitry Chagin struct l_timespec lts; 1549a9482f8SDmitry Chagin int error; 1559a9482f8SDmitry Chagin 1569a9482f8SDmitry Chagin error = native_to_linux_timespec(<s, ntp); 1579a9482f8SDmitry Chagin if (error != 0) 1589a9482f8SDmitry Chagin return (error); 1599a9482f8SDmitry Chagin return (copyout(<s, ltp, sizeof(lts))); 1609a9482f8SDmitry Chagin } 1619a9482f8SDmitry Chagin 162707e567aSDmitry Chagin int 163707e567aSDmitry Chagin linux_get_timespec(struct timespec *ntp, const struct l_timespec *ultp) 164707e567aSDmitry Chagin { 165707e567aSDmitry Chagin struct l_timespec lts; 166707e567aSDmitry Chagin int error; 167707e567aSDmitry Chagin 168707e567aSDmitry Chagin error = copyin(ultp, <s, sizeof(lts)); 169707e567aSDmitry Chagin if (error != 0) 170707e567aSDmitry Chagin return (error); 171707e567aSDmitry Chagin return (linux_to_native_timespec(ntp, <s)); 172707e567aSDmitry Chagin } 173707e567aSDmitry Chagin 174bfcce1a9SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 175bfcce1a9SDmitry Chagin int 176bfcce1a9SDmitry Chagin native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp) 177bfcce1a9SDmitry Chagin { 178bfcce1a9SDmitry Chagin 179bfcce1a9SDmitry Chagin ltp64->tv_sec = ntp->tv_sec; 180bfcce1a9SDmitry Chagin ltp64->tv_nsec = ntp->tv_nsec; 181bfcce1a9SDmitry Chagin 182bfcce1a9SDmitry Chagin return (0); 183bfcce1a9SDmitry Chagin } 184bfcce1a9SDmitry Chagin 185bfcce1a9SDmitry Chagin int 186bfcce1a9SDmitry Chagin linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64) 187bfcce1a9SDmitry Chagin { 188bfcce1a9SDmitry Chagin 1893dc2a067SDmitry Chagin #if defined(__i386__) 1903dc2a067SDmitry Chagin /* i386 time_t is still 32-bit */ 1913dc2a067SDmitry Chagin if (ltp64->tv_sec > INT_MAX || ltp64->tv_sec < INT_MIN) 1923dc2a067SDmitry Chagin return (EOVERFLOW); 1933dc2a067SDmitry Chagin #endif 1941579b320SDmitry Chagin /* Zero out the padding in compat mode. */ 1951579b320SDmitry Chagin ntp->tv_nsec = ltp64->tv_nsec & 0xFFFFFFFFUL; 196bfcce1a9SDmitry Chagin ntp->tv_sec = ltp64->tv_sec; 1971579b320SDmitry Chagin 1981579b320SDmitry Chagin if (!timespecvalid_interval(ntp)) 1991579b320SDmitry Chagin return (EINVAL); 200bfcce1a9SDmitry Chagin 201bfcce1a9SDmitry Chagin return (0); 202bfcce1a9SDmitry Chagin } 2039a9482f8SDmitry Chagin 2049a9482f8SDmitry Chagin int 2059a9482f8SDmitry Chagin linux_put_timespec64(struct timespec *ntp, struct l_timespec64 *ltp) 2069a9482f8SDmitry Chagin { 2079a9482f8SDmitry Chagin struct l_timespec64 lts; 2089a9482f8SDmitry Chagin int error; 2099a9482f8SDmitry Chagin 2109a9482f8SDmitry Chagin error = native_to_linux_timespec64(<s, ntp); 2119a9482f8SDmitry Chagin if (error != 0) 2129a9482f8SDmitry Chagin return (error); 2139a9482f8SDmitry Chagin return (copyout(<s, ltp, sizeof(lts))); 2149a9482f8SDmitry Chagin } 215707e567aSDmitry Chagin 216707e567aSDmitry Chagin int 217707e567aSDmitry Chagin linux_get_timespec64(struct timespec *ntp, const struct l_timespec64 *ultp) 218707e567aSDmitry Chagin { 219707e567aSDmitry Chagin struct l_timespec64 lts; 220707e567aSDmitry Chagin int error; 221707e567aSDmitry Chagin 222707e567aSDmitry Chagin error = copyin(ultp, <s, sizeof(lts)); 223707e567aSDmitry Chagin if (error != 0) 224707e567aSDmitry Chagin return (error); 225707e567aSDmitry Chagin return (linux_to_native_timespec64(ntp, <s)); 226707e567aSDmitry Chagin } 227bfcce1a9SDmitry Chagin #endif 228bfcce1a9SDmitry Chagin 22916ac71bcSDmitry Chagin int 230dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp) 231dd93b628SDmitry Chagin { 232dd93b628SDmitry Chagin int error; 233dd93b628SDmitry Chagin 234dd93b628SDmitry Chagin error = native_to_linux_timespec(<p->it_interval, &ntp->it_interval); 235dd93b628SDmitry Chagin if (error == 0) 2360938d04aSDmitry Chagin error = native_to_linux_timespec(<p->it_value, &ntp->it_value); 237dd93b628SDmitry Chagin return (error); 238dd93b628SDmitry Chagin } 239dd93b628SDmitry Chagin 240dd93b628SDmitry Chagin int 241dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp) 242dd93b628SDmitry Chagin { 243dd93b628SDmitry Chagin int error; 244dd93b628SDmitry Chagin 245dd93b628SDmitry Chagin error = linux_to_native_timespec(&ntp->it_interval, <p->it_interval); 246dd93b628SDmitry Chagin if (error == 0) 247dd93b628SDmitry Chagin error = linux_to_native_timespec(&ntp->it_value, <p->it_value); 248dd93b628SDmitry Chagin return (error); 249dd93b628SDmitry Chagin } 250dd93b628SDmitry Chagin 251783c1bd8SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 252783c1bd8SDmitry Chagin int 253783c1bd8SDmitry Chagin linux_to_native_itimerspec64(struct itimerspec *ntp, struct l_itimerspec64 *ltp) 254783c1bd8SDmitry Chagin { 255783c1bd8SDmitry Chagin int error; 256783c1bd8SDmitry Chagin 257783c1bd8SDmitry Chagin error = linux_to_native_timespec64(&ntp->it_interval, <p->it_interval); 258783c1bd8SDmitry Chagin if (error == 0) 259783c1bd8SDmitry Chagin error = linux_to_native_timespec64(&ntp->it_value, <p->it_value); 260783c1bd8SDmitry Chagin return (error); 261783c1bd8SDmitry Chagin } 262783c1bd8SDmitry Chagin 263783c1bd8SDmitry Chagin int 264783c1bd8SDmitry Chagin native_to_linux_itimerspec64(struct l_itimerspec64 *ltp, struct itimerspec *ntp) 265783c1bd8SDmitry Chagin { 266783c1bd8SDmitry Chagin int error; 267783c1bd8SDmitry Chagin 268783c1bd8SDmitry Chagin error = native_to_linux_timespec64(<p->it_interval, &ntp->it_interval); 269783c1bd8SDmitry Chagin if (error == 0) 270783c1bd8SDmitry Chagin error = native_to_linux_timespec64(<p->it_value, &ntp->it_value); 271783c1bd8SDmitry Chagin return (error); 272783c1bd8SDmitry Chagin } 273783c1bd8SDmitry Chagin #endif 274783c1bd8SDmitry Chagin 275dd93b628SDmitry Chagin int 276ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l) 277ad2056f2SAlexander Leidinger { 27819e252baSAlexander Leidinger 2792711aba9SDmitry Chagin if (l < 0) { 2802711aba9SDmitry Chagin /* cpu-clock */ 281*452f4636SDmitry Chagin if (LINUX_CPUCLOCK_WHICH(l) == LINUX_CLOCKFD) { 282*452f4636SDmitry Chagin LIN_SDT_PROBE1(time, linux_to_native_clockid, 283*452f4636SDmitry Chagin unsupported_clockid, l); 284*452f4636SDmitry Chagin return (ENOTSUP); 285*452f4636SDmitry Chagin } 2862711aba9SDmitry Chagin if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX) 2872711aba9SDmitry Chagin return (EINVAL); 2882711aba9SDmitry Chagin 2892711aba9SDmitry Chagin if (LINUX_CPUCLOCK_PERTHREAD(l)) 2902711aba9SDmitry Chagin *n = CLOCK_THREAD_CPUTIME_ID; 2912711aba9SDmitry Chagin else 2922711aba9SDmitry Chagin *n = CLOCK_PROCESS_CPUTIME_ID; 2932711aba9SDmitry Chagin return (0); 2942711aba9SDmitry Chagin } 2952711aba9SDmitry Chagin 296ad2056f2SAlexander Leidinger switch (l) { 297ad2056f2SAlexander Leidinger case LINUX_CLOCK_REALTIME: 298ad2056f2SAlexander Leidinger *n = CLOCK_REALTIME; 299ad2056f2SAlexander Leidinger break; 300ad2056f2SAlexander Leidinger case LINUX_CLOCK_MONOTONIC: 301ad2056f2SAlexander Leidinger *n = CLOCK_MONOTONIC; 302ad2056f2SAlexander Leidinger break; 3037bc05ae6SDmitry Chagin case LINUX_CLOCK_PROCESS_CPUTIME_ID: 3047bc05ae6SDmitry Chagin *n = CLOCK_PROCESS_CPUTIME_ID; 3057bc05ae6SDmitry Chagin break; 3067bc05ae6SDmitry Chagin case LINUX_CLOCK_THREAD_CPUTIME_ID: 3077bc05ae6SDmitry Chagin *n = CLOCK_THREAD_CPUTIME_ID; 3087bc05ae6SDmitry Chagin break; 3092711aba9SDmitry Chagin case LINUX_CLOCK_REALTIME_COARSE: 3102711aba9SDmitry Chagin *n = CLOCK_REALTIME_FAST; 3112711aba9SDmitry Chagin break; 3122711aba9SDmitry Chagin case LINUX_CLOCK_MONOTONIC_COARSE: 313e37db348SAlexander Leidinger case LINUX_CLOCK_MONOTONIC_RAW: 3142711aba9SDmitry Chagin *n = CLOCK_MONOTONIC_FAST; 3152711aba9SDmitry Chagin break; 3162711aba9SDmitry Chagin case LINUX_CLOCK_BOOTTIME: 31725ada637SDmitry Chagin *n = CLOCK_UPTIME; 31825ada637SDmitry Chagin break; 3192711aba9SDmitry Chagin case LINUX_CLOCK_REALTIME_ALARM: 3202711aba9SDmitry Chagin case LINUX_CLOCK_BOOTTIME_ALARM: 3212711aba9SDmitry Chagin case LINUX_CLOCK_SGI_CYCLE: 3222711aba9SDmitry Chagin case LINUX_CLOCK_TAI: 32319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, 32419e252baSAlexander Leidinger unsupported_clockid, l); 325*452f4636SDmitry Chagin return (ENOTSUP); 32677424f41SJung-uk Kim default: 32719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, 32819e252baSAlexander Leidinger unknown_clockid, l); 329*452f4636SDmitry Chagin return (ENOTSUP); 330ad2056f2SAlexander Leidinger } 331ad2056f2SAlexander Leidinger 33277424f41SJung-uk Kim return (0); 333ad2056f2SAlexander Leidinger } 334ad2056f2SAlexander Leidinger 335ad2056f2SAlexander Leidinger int 336f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags) 337f0f58384SDmitry Chagin { 338f0f58384SDmitry Chagin 339f0f58384SDmitry Chagin if (flags & ~LINUX_TIMER_ABSTIME) 340f0f58384SDmitry Chagin return (EINVAL); 341f0f58384SDmitry Chagin *nflags = 0; 342f0f58384SDmitry Chagin if (flags & LINUX_TIMER_ABSTIME) 343f0f58384SDmitry Chagin *nflags |= TIMER_ABSTIME; 344f0f58384SDmitry Chagin return (0); 345f0f58384SDmitry Chagin } 346f0f58384SDmitry Chagin 34799b6f430SDmitry Chagin static int 34899b6f430SDmitry Chagin linux_common_clock_gettime(struct thread *td, clockid_t which, 34999b6f430SDmitry Chagin struct timespec *tp) 350ad2056f2SAlexander Leidinger { 3512711aba9SDmitry Chagin struct rusage ru; 3522711aba9SDmitry Chagin struct thread *targettd; 3532711aba9SDmitry Chagin struct proc *p; 3542711aba9SDmitry Chagin int error, clockwhich; 3552506c761SDmitry Chagin clockid_t nwhich; 3562711aba9SDmitry Chagin pid_t pid; 3572711aba9SDmitry Chagin lwpid_t tid; 358ad2056f2SAlexander Leidinger 35999b6f430SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 36019e252baSAlexander Leidinger if (error != 0) { 3614afe4faeSEdward Tomasz Napierala linux_msg(curthread, 36299b6f430SDmitry Chagin "unsupported clock_gettime clockid %d", which); 36399b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_gettime, 36499b6f430SDmitry Chagin conversion_error, error); 36577424f41SJung-uk Kim return (error); 36619e252baSAlexander Leidinger } 3672711aba9SDmitry Chagin 3682711aba9SDmitry Chagin switch (nwhich) { 3692711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 37099b6f430SDmitry Chagin if (which < 0) { 37199b6f430SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 37299b6f430SDmitry Chagin pid = LINUX_CPUCLOCK_ID(which); 3737bc05ae6SDmitry Chagin } else { 3747bc05ae6SDmitry Chagin clockwhich = LINUX_CPUCLOCK_SCHED; 3757bc05ae6SDmitry Chagin pid = 0; 3767bc05ae6SDmitry Chagin } 3772711aba9SDmitry Chagin if (pid == 0) { 3782711aba9SDmitry Chagin p = td->td_proc; 3792711aba9SDmitry Chagin PROC_LOCK(p); 3802711aba9SDmitry Chagin } else { 3812711aba9SDmitry Chagin error = pget(pid, PGET_CANSEE, &p); 3822711aba9SDmitry Chagin if (error != 0) 3832711aba9SDmitry Chagin return (EINVAL); 3842711aba9SDmitry Chagin } 3852711aba9SDmitry Chagin switch (clockwhich) { 3862711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 3872711aba9SDmitry Chagin PROC_STATLOCK(p); 3882711aba9SDmitry Chagin calcru(p, &ru.ru_utime, &ru.ru_stime); 3892711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3902711aba9SDmitry Chagin PROC_UNLOCK(p); 3912711aba9SDmitry Chagin timevaladd(&ru.ru_utime, &ru.ru_stime); 39299b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 3932711aba9SDmitry Chagin break; 3942711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 3952711aba9SDmitry Chagin PROC_STATLOCK(p); 3962711aba9SDmitry Chagin calcru(p, &ru.ru_utime, &ru.ru_stime); 3972711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3982711aba9SDmitry Chagin PROC_UNLOCK(p); 39999b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 4002711aba9SDmitry Chagin break; 4012711aba9SDmitry Chagin case LINUX_CPUCLOCK_SCHED: 40299b6f430SDmitry Chagin kern_process_cputime(p, tp); 4032711aba9SDmitry Chagin PROC_UNLOCK(p); 4042711aba9SDmitry Chagin break; 4052711aba9SDmitry Chagin default: 4062711aba9SDmitry Chagin PROC_UNLOCK(p); 4072711aba9SDmitry Chagin return (EINVAL); 4082711aba9SDmitry Chagin } 4092711aba9SDmitry Chagin 4102711aba9SDmitry Chagin break; 4112711aba9SDmitry Chagin 4122711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 41399b6f430SDmitry Chagin if (which < 0) { 41499b6f430SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 41599b6f430SDmitry Chagin tid = LINUX_CPUCLOCK_ID(which); 4167bc05ae6SDmitry Chagin } else { 4177bc05ae6SDmitry Chagin clockwhich = LINUX_CPUCLOCK_SCHED; 4187bc05ae6SDmitry Chagin tid = 0; 4197bc05ae6SDmitry Chagin } 4207bc05ae6SDmitry Chagin p = td->td_proc; 4212711aba9SDmitry Chagin if (tid == 0) { 4222711aba9SDmitry Chagin targettd = td; 4232711aba9SDmitry Chagin PROC_LOCK(p); 4242711aba9SDmitry Chagin } else { 4257bc05ae6SDmitry Chagin targettd = linux_tdfind(td, tid, p->p_pid); 4262711aba9SDmitry Chagin if (targettd == NULL) 4272711aba9SDmitry Chagin return (EINVAL); 4282711aba9SDmitry Chagin } 4292711aba9SDmitry Chagin switch (clockwhich) { 4302711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 4312711aba9SDmitry Chagin PROC_STATLOCK(p); 4322711aba9SDmitry Chagin thread_lock(targettd); 4332711aba9SDmitry Chagin rufetchtd(targettd, &ru); 4342711aba9SDmitry Chagin thread_unlock(targettd); 4352711aba9SDmitry Chagin PROC_STATUNLOCK(p); 4362711aba9SDmitry Chagin PROC_UNLOCK(p); 4372711aba9SDmitry Chagin timevaladd(&ru.ru_utime, &ru.ru_stime); 43899b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 4392711aba9SDmitry Chagin break; 4402711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 4412711aba9SDmitry Chagin PROC_STATLOCK(p); 4422711aba9SDmitry Chagin thread_lock(targettd); 4432711aba9SDmitry Chagin rufetchtd(targettd, &ru); 4442711aba9SDmitry Chagin thread_unlock(targettd); 4452711aba9SDmitry Chagin PROC_STATUNLOCK(p); 4462711aba9SDmitry Chagin PROC_UNLOCK(p); 44799b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 4482711aba9SDmitry Chagin break; 4492711aba9SDmitry Chagin case LINUX_CPUCLOCK_SCHED: 4507bc05ae6SDmitry Chagin if (td == targettd) 4517bc05ae6SDmitry Chagin targettd = NULL; 45299b6f430SDmitry Chagin kern_thread_cputime(targettd, tp); 4532711aba9SDmitry Chagin PROC_UNLOCK(p); 4542711aba9SDmitry Chagin break; 4552711aba9SDmitry Chagin default: 4562711aba9SDmitry Chagin PROC_UNLOCK(p); 4572711aba9SDmitry Chagin return (EINVAL); 4582711aba9SDmitry Chagin } 4592711aba9SDmitry Chagin break; 4602711aba9SDmitry Chagin 4612711aba9SDmitry Chagin default: 46299b6f430SDmitry Chagin error = kern_clock_gettime(td, nwhich, tp); 4632711aba9SDmitry Chagin break; 4642711aba9SDmitry Chagin } 46599b6f430SDmitry Chagin 46699b6f430SDmitry Chagin return (error); 46799b6f430SDmitry Chagin } 46899b6f430SDmitry Chagin 46999b6f430SDmitry Chagin int 47099b6f430SDmitry Chagin linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args) 47199b6f430SDmitry Chagin { 47299b6f430SDmitry Chagin struct timespec tp; 47399b6f430SDmitry Chagin int error; 47499b6f430SDmitry Chagin 47599b6f430SDmitry Chagin error = linux_common_clock_gettime(td, args->which, &tp); 47619e252baSAlexander Leidinger if (error != 0) { 47719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error); 47877424f41SJung-uk Kim return (error); 47919e252baSAlexander Leidinger } 4809a9482f8SDmitry Chagin error = linux_put_timespec(&tp, args->tp); 48119e252baSAlexander Leidinger if (error != 0) 48219e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error); 48319e252baSAlexander Leidinger 48419e252baSAlexander Leidinger return (error); 485ad2056f2SAlexander Leidinger } 486ad2056f2SAlexander Leidinger 48799b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 48899b6f430SDmitry Chagin int 48999b6f430SDmitry Chagin linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args) 49099b6f430SDmitry Chagin { 49199b6f430SDmitry Chagin struct timespec tp; 49299b6f430SDmitry Chagin int error; 49399b6f430SDmitry Chagin 49499b6f430SDmitry Chagin error = linux_common_clock_gettime(td, args->which, &tp); 49599b6f430SDmitry Chagin if (error != 0) { 49699b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error); 49799b6f430SDmitry Chagin return (error); 49899b6f430SDmitry Chagin } 4999a9482f8SDmitry Chagin error = linux_put_timespec64(&tp, args->tp); 50099b6f430SDmitry Chagin if (error != 0) 50199b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error); 50299b6f430SDmitry Chagin 50399b6f430SDmitry Chagin return (error); 50499b6f430SDmitry Chagin } 50599b6f430SDmitry Chagin #endif 50699b6f430SDmitry Chagin 50719f9a0e4SDmitry Chagin static int 50819f9a0e4SDmitry Chagin linux_common_clock_settime(struct thread *td, clockid_t which, 50919f9a0e4SDmitry Chagin struct timespec *ts) 51019f9a0e4SDmitry Chagin { 51119f9a0e4SDmitry Chagin int error; 51219f9a0e4SDmitry Chagin clockid_t nwhich; 51319f9a0e4SDmitry Chagin 51419f9a0e4SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 51519f9a0e4SDmitry Chagin if (error != 0) { 51619f9a0e4SDmitry Chagin linux_msg(curthread, 51719f9a0e4SDmitry Chagin "unsupported clock_settime clockid %d", which); 51819f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error, 51919f9a0e4SDmitry Chagin error); 52019f9a0e4SDmitry Chagin return (error); 52119f9a0e4SDmitry Chagin } 52219f9a0e4SDmitry Chagin 52319f9a0e4SDmitry Chagin error = kern_clock_settime(td, nwhich, ts); 52419f9a0e4SDmitry Chagin if (error != 0) 52519f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_settime, 52619f9a0e4SDmitry Chagin settime_error, error); 52719f9a0e4SDmitry Chagin 52819f9a0e4SDmitry Chagin return (error); 52919f9a0e4SDmitry Chagin } 53019f9a0e4SDmitry Chagin 531ad2056f2SAlexander Leidinger int 532ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args) 533ad2056f2SAlexander Leidinger { 534ad2056f2SAlexander Leidinger struct timespec ts; 535ad2056f2SAlexander Leidinger int error; 536ad2056f2SAlexander Leidinger 537707e567aSDmitry Chagin error = linux_get_timespec(&ts, args->tp); 53819e252baSAlexander Leidinger if (error != 0) { 53919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error); 54019e252baSAlexander Leidinger return (error); 54119e252baSAlexander Leidinger } 54219f9a0e4SDmitry Chagin return (linux_common_clock_settime(td, args->which, &ts)); 54319e252baSAlexander Leidinger } 54419e252baSAlexander Leidinger 54519f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 54619f9a0e4SDmitry Chagin int 54719f9a0e4SDmitry Chagin linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args) 54819f9a0e4SDmitry Chagin { 54919f9a0e4SDmitry Chagin struct timespec ts; 55019f9a0e4SDmitry Chagin int error; 55119f9a0e4SDmitry Chagin 552707e567aSDmitry Chagin error = linux_get_timespec64(&ts, args->tp); 55319f9a0e4SDmitry Chagin if (error != 0) { 55419f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error); 55519f9a0e4SDmitry Chagin return (error); 55619f9a0e4SDmitry Chagin } 55719f9a0e4SDmitry Chagin return (linux_common_clock_settime(td, args->which, &ts)); 558ad2056f2SAlexander Leidinger } 55919f9a0e4SDmitry Chagin #endif 560ad2056f2SAlexander Leidinger 561187715a4SDmitry Chagin static int 562187715a4SDmitry Chagin linux_common_clock_getres(struct thread *td, clockid_t which, 563187715a4SDmitry Chagin struct timespec *ts) 564ad2056f2SAlexander Leidinger { 5652711aba9SDmitry Chagin struct proc *p; 5662711aba9SDmitry Chagin int error, clockwhich; 5672506c761SDmitry Chagin clockid_t nwhich; 5682711aba9SDmitry Chagin pid_t pid; 5692711aba9SDmitry Chagin lwpid_t tid; 570ad2056f2SAlexander Leidinger 571187715a4SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 57219e252baSAlexander Leidinger if (error != 0) { 5734afe4faeSEdward Tomasz Napierala linux_msg(curthread, 574187715a4SDmitry Chagin "unsupported clock_getres clockid %d", which); 575187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_getres, 576187715a4SDmitry Chagin conversion_error, error); 57777424f41SJung-uk Kim return (error); 57819e252baSAlexander Leidinger } 5792711aba9SDmitry Chagin 5802711aba9SDmitry Chagin /* 5812711aba9SDmitry Chagin * Check user supplied clock id in case of per-process 5822711aba9SDmitry Chagin * or thread-specific cpu-time clock. 5832711aba9SDmitry Chagin */ 584187715a4SDmitry Chagin if (which < 0) { 5852711aba9SDmitry Chagin switch (nwhich) { 5862711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 587187715a4SDmitry Chagin tid = LINUX_CPUCLOCK_ID(which); 5882711aba9SDmitry Chagin if (tid != 0) { 5892711aba9SDmitry Chagin p = td->td_proc; 5907bc05ae6SDmitry Chagin if (linux_tdfind(td, tid, p->p_pid) == NULL) 5917bc05ae6SDmitry Chagin return (EINVAL); 5922711aba9SDmitry Chagin PROC_UNLOCK(p); 5932711aba9SDmitry Chagin } 5942711aba9SDmitry Chagin break; 5952711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 596187715a4SDmitry Chagin pid = LINUX_CPUCLOCK_ID(which); 5972711aba9SDmitry Chagin if (pid != 0) { 5982711aba9SDmitry Chagin error = pget(pid, PGET_CANSEE, &p); 5992711aba9SDmitry Chagin if (error != 0) 6002711aba9SDmitry Chagin return (EINVAL); 6012711aba9SDmitry Chagin PROC_UNLOCK(p); 6022711aba9SDmitry Chagin } 6032711aba9SDmitry Chagin break; 6042711aba9SDmitry Chagin } 6057bc05ae6SDmitry Chagin } 6062711aba9SDmitry Chagin 607187715a4SDmitry Chagin if (ts == NULL) { 608187715a4SDmitry Chagin LIN_SDT_PROBE0(time, linux_common_clock_getres, nullcall); 6092711aba9SDmitry Chagin return (0); 6102711aba9SDmitry Chagin } 6112711aba9SDmitry Chagin 6122711aba9SDmitry Chagin switch (nwhich) { 6132711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 6142711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 615187715a4SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 6167bc05ae6SDmitry Chagin /* 6177bc05ae6SDmitry Chagin * In both cases (when the clock id obtained by a call to 6187bc05ae6SDmitry Chagin * clock_getcpuclockid() or using the clock 6197bc05ae6SDmitry Chagin * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision 6207bc05ae6SDmitry Chagin * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock. 6217bc05ae6SDmitry Chagin * 6227bc05ae6SDmitry Chagin * See Linux posix_cpu_clock_getres() implementation. 6237bc05ae6SDmitry Chagin */ 624187715a4SDmitry Chagin if (which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) { 625187715a4SDmitry Chagin ts->tv_sec = 0; 626187715a4SDmitry Chagin ts->tv_nsec = 1; 6277bc05ae6SDmitry Chagin goto out; 6287bc05ae6SDmitry Chagin } 6297bc05ae6SDmitry Chagin 6302711aba9SDmitry Chagin switch (clockwhich) { 6312711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 6322711aba9SDmitry Chagin nwhich = CLOCK_PROF; 6332711aba9SDmitry Chagin break; 6342711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 6352711aba9SDmitry Chagin nwhich = CLOCK_VIRTUAL; 6362711aba9SDmitry Chagin break; 6372711aba9SDmitry Chagin default: 6382711aba9SDmitry Chagin return (EINVAL); 6392711aba9SDmitry Chagin } 6402711aba9SDmitry Chagin break; 6412711aba9SDmitry Chagin 6422711aba9SDmitry Chagin default: 6432711aba9SDmitry Chagin break; 6442711aba9SDmitry Chagin } 645187715a4SDmitry Chagin error = kern_clock_getres(td, nwhich, ts); 64619e252baSAlexander Leidinger if (error != 0) { 647187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_getres, 648187715a4SDmitry Chagin getres_error, error); 64977424f41SJung-uk Kim return (error); 65019e252baSAlexander Leidinger } 6517bc05ae6SDmitry Chagin 6527bc05ae6SDmitry Chagin out: 653187715a4SDmitry Chagin return (error); 654187715a4SDmitry Chagin } 655187715a4SDmitry Chagin 656187715a4SDmitry Chagin int 657187715a4SDmitry Chagin linux_clock_getres(struct thread *td, 658187715a4SDmitry Chagin struct linux_clock_getres_args *args) 659187715a4SDmitry Chagin { 660187715a4SDmitry Chagin struct timespec ts; 661187715a4SDmitry Chagin int error; 662187715a4SDmitry Chagin 663187715a4SDmitry Chagin error = linux_common_clock_getres(td, args->which, &ts); 664187715a4SDmitry Chagin if (error != 0 || args->tp == NULL) 665187715a4SDmitry Chagin return (error); 6669a9482f8SDmitry Chagin error = linux_put_timespec(&ts, args->tp); 66719e252baSAlexander Leidinger if (error != 0) 668187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_getres, 669187715a4SDmitry Chagin copyout_error, error); 67019e252baSAlexander Leidinger return (error); 67177424f41SJung-uk Kim } 67277424f41SJung-uk Kim 673187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 674187715a4SDmitry Chagin int 675187715a4SDmitry Chagin linux_clock_getres_time64(struct thread *td, 676187715a4SDmitry Chagin struct linux_clock_getres_time64_args *args) 677187715a4SDmitry Chagin { 678187715a4SDmitry Chagin struct timespec ts; 679187715a4SDmitry Chagin int error; 680187715a4SDmitry Chagin 681187715a4SDmitry Chagin error = linux_common_clock_getres(td, args->which, &ts); 682187715a4SDmitry Chagin if (error != 0 || args->tp == NULL) 683187715a4SDmitry Chagin return (error); 6849a9482f8SDmitry Chagin error = linux_put_timespec64(&ts, args->tp); 685187715a4SDmitry Chagin if (error != 0) 686187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_getres_time64, 687187715a4SDmitry Chagin copyout_error, error); 688187715a4SDmitry Chagin return (error); 689187715a4SDmitry Chagin } 690187715a4SDmitry Chagin #endif 691187715a4SDmitry Chagin 69277424f41SJung-uk Kim int 69377424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args) 69477424f41SJung-uk Kim { 69577424f41SJung-uk Kim struct timespec *rmtp; 69677424f41SJung-uk Kim struct timespec rqts, rmts; 6975c2748d5SDmitry Chagin int error, error2; 69877424f41SJung-uk Kim 699707e567aSDmitry Chagin error = linux_get_timespec(&rqts, args->rqtp); 70019e252baSAlexander Leidinger if (error != 0) { 70119e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error); 70277424f41SJung-uk Kim return (error); 70319e252baSAlexander Leidinger } 70477424f41SJung-uk Kim if (args->rmtp != NULL) 70577424f41SJung-uk Kim rmtp = &rmts; 70677424f41SJung-uk Kim else 70777424f41SJung-uk Kim rmtp = NULL; 70877424f41SJung-uk Kim 70977424f41SJung-uk Kim error = kern_nanosleep(td, &rqts, rmtp); 7104cf66812SEric van Gyzen if (error == EINTR && args->rmtp != NULL) { 7119a9482f8SDmitry Chagin error2 = linux_put_timespec(rmtp, args->rmtp); 7125c2748d5SDmitry Chagin if (error2 != 0) { 71319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error, 7145c2748d5SDmitry Chagin error2); 7155c2748d5SDmitry Chagin return (error2); 71677424f41SJung-uk Kim } 71719e252baSAlexander Leidinger } 71877424f41SJung-uk Kim 7195c2748d5SDmitry Chagin return (error); 720ad2056f2SAlexander Leidinger } 721ad2056f2SAlexander Leidinger 7226501370aSDmitry Chagin static int 7236501370aSDmitry Chagin linux_common_clock_nanosleep(struct thread *td, clockid_t which, 7246501370aSDmitry Chagin l_int lflags, struct timespec *rqtp, struct timespec *rmtp) 7256501370aSDmitry Chagin { 7266501370aSDmitry Chagin int error, flags; 7276501370aSDmitry Chagin clockid_t clockid; 7286501370aSDmitry Chagin 7296501370aSDmitry Chagin error = linux_to_native_timerflags(&flags, lflags); 7306501370aSDmitry Chagin if (error != 0) { 7316501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_nanosleep, 7326501370aSDmitry Chagin unsupported_flags, lflags); 7336501370aSDmitry Chagin return (error); 7346501370aSDmitry Chagin } 7356501370aSDmitry Chagin 7366501370aSDmitry Chagin error = linux_to_native_clockid(&clockid, which); 7376501370aSDmitry Chagin if (error != 0) { 7386501370aSDmitry Chagin linux_msg(curthread, 7396501370aSDmitry Chagin "unsupported clock_nanosleep clockid %d", which); 7406501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_nanosleep, 7416501370aSDmitry Chagin unsupported_clockid, which); 7426501370aSDmitry Chagin return (error); 7436501370aSDmitry Chagin } 74466e73ce7SDmitry Chagin if (clockid == CLOCK_THREAD_CPUTIME_ID) 74566e73ce7SDmitry Chagin return (ENOTSUP); 7466501370aSDmitry Chagin 7476501370aSDmitry Chagin return (kern_clock_nanosleep(td, clockid, flags, rqtp, rmtp)); 7486501370aSDmitry Chagin } 7496501370aSDmitry Chagin 750ad2056f2SAlexander Leidinger int 7516501370aSDmitry Chagin linux_clock_nanosleep(struct thread *td, 7526501370aSDmitry Chagin struct linux_clock_nanosleep_args *args) 753ad2056f2SAlexander Leidinger { 754ad2056f2SAlexander Leidinger struct timespec *rmtp; 755ad2056f2SAlexander Leidinger struct timespec rqts, rmts; 7566501370aSDmitry Chagin int error, error2; 757ad2056f2SAlexander Leidinger 758707e567aSDmitry Chagin error = linux_get_timespec(&rqts, args->rqtp); 75919e252baSAlexander Leidinger if (error != 0) { 76019e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error, 76119e252baSAlexander Leidinger error); 76277424f41SJung-uk Kim return (error); 76319e252baSAlexander Leidinger } 764ad2056f2SAlexander Leidinger if (args->rmtp != NULL) 765ad2056f2SAlexander Leidinger rmtp = &rmts; 766ad2056f2SAlexander Leidinger else 767ad2056f2SAlexander Leidinger rmtp = NULL; 768ad2056f2SAlexander Leidinger 7696501370aSDmitry Chagin error = linux_common_clock_nanosleep(td, args->which, args->flags, 7706501370aSDmitry Chagin &rqts, rmtp); 7716501370aSDmitry Chagin if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 && 772f0f58384SDmitry Chagin args->rmtp != NULL) { 7739a9482f8SDmitry Chagin error2 = linux_put_timespec(rmtp, args->rmtp); 7745c2748d5SDmitry Chagin if (error2 != 0) { 7755c2748d5SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep, 7765c2748d5SDmitry Chagin copyout_error, error2); 7775c2748d5SDmitry Chagin return (error2); 7785c2748d5SDmitry Chagin } 7795c2748d5SDmitry Chagin } 78077424f41SJung-uk Kim return (error); 78119e252baSAlexander Leidinger } 7826501370aSDmitry Chagin 7836501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 7846501370aSDmitry Chagin int 7856501370aSDmitry Chagin linux_clock_nanosleep_time64(struct thread *td, 7866501370aSDmitry Chagin struct linux_clock_nanosleep_time64_args *args) 7876501370aSDmitry Chagin { 7886501370aSDmitry Chagin struct timespec *rmtp; 7896501370aSDmitry Chagin struct timespec rqts, rmts; 7906501370aSDmitry Chagin int error, error2; 7916501370aSDmitry Chagin 792707e567aSDmitry Chagin error = linux_get_timespec64(&rqts, args->rqtp); 7936501370aSDmitry Chagin if (error != 0) { 7946501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64, 7956501370aSDmitry Chagin copyin_error, error); 7966501370aSDmitry Chagin return (error); 7976501370aSDmitry Chagin } 7986501370aSDmitry Chagin if (args->rmtp != NULL) 7996501370aSDmitry Chagin rmtp = &rmts; 8006501370aSDmitry Chagin else 8016501370aSDmitry Chagin rmtp = NULL; 8026501370aSDmitry Chagin 8036501370aSDmitry Chagin error = linux_common_clock_nanosleep(td, args->which, args->flags, 8046501370aSDmitry Chagin &rqts, rmtp); 8056501370aSDmitry Chagin if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 && 8066501370aSDmitry Chagin args->rmtp != NULL) { 8079a9482f8SDmitry Chagin error2 = linux_put_timespec64(rmtp, args->rmtp); 8086501370aSDmitry Chagin if (error2 != 0) { 8096501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64, 8106501370aSDmitry Chagin copyout_error, error2); 8116501370aSDmitry Chagin return (error2); 8126501370aSDmitry Chagin } 8136501370aSDmitry Chagin } 8146501370aSDmitry Chagin return (error); 8156501370aSDmitry Chagin } 8166501370aSDmitry Chagin #endif 817