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 <sys/param.h> 410670e972SDmitry Chagin #include <sys/limits.h> 42d8e53d94SDmitry Chagin #include <sys/lock.h> 432711aba9SDmitry Chagin #include <sys/mutex.h> 44ad2056f2SAlexander Leidinger #include <sys/proc.h> 45d8e53d94SDmitry Chagin #include <sys/resourcevar.h> 46d8e53d94SDmitry Chagin #include <sys/syscallsubr.h> 47d8e53d94SDmitry Chagin #include <sys/time.h> 48ad2056f2SAlexander Leidinger 49ad2056f2SAlexander Leidinger #ifdef COMPAT_LINUX32 50ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h> 51ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h> 52ad2056f2SAlexander Leidinger #else 53ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h> 54ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h> 55ad2056f2SAlexander Leidinger #endif 56ad2056f2SAlexander Leidinger 5719e252baSAlexander Leidinger #include <compat/linux/linux_dtrace.h> 587bc05ae6SDmitry Chagin #include <compat/linux/linux_misc.h> 59*c8a79231SDmitry Chagin #include <compat/linux/linux_time.h> 604afe4faeSEdward Tomasz Napierala #include <compat/linux/linux_util.h> 6119e252baSAlexander Leidinger 6219e252baSAlexander Leidinger /* DTrace init */ 6319e252baSAlexander Leidinger LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); 6419e252baSAlexander Leidinger 6519e252baSAlexander Leidinger /** 6619e252baSAlexander Leidinger * DTrace probes in this module. 6719e252baSAlexander Leidinger */ 6819e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid, 6919e252baSAlexander Leidinger "clockid_t"); 7019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid, 7119e252baSAlexander Leidinger "clockid_t"); 7299b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_gettime, conversion_error, "int"); 7319e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int"); 7419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int"); 7599b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 7699b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, gettime_error, "int"); 7799b6f430SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, copyout_error, "int"); 7899b6f430SDmitry Chagin #endif 7919e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int"); 8019f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, settime_error, "int"); 8119f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, conversion_error, "int"); 8219e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int"); 8319f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 8419f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, conversion_error, "int"); 8519f9a0e4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, copyin_error, "int"); 8619f9a0e4SDmitry Chagin #endif 87187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE0(time, linux_common_clock_getres, nullcall); 88187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, conversion_error, "int"); 89187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, getres_error, "int"); 9019e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int"); 91187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 92187715a4SDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres_time64, copyout_error, "int"); 93187715a4SDmitry Chagin #endif 9419e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int"); 9519e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int"); 9619e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int"); 9719e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int"); 986501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int"); 996501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int"); 1006501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 1016501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int"); 1026501370aSDmitry Chagin LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int"); 1036501370aSDmitry Chagin #endif 10419e252baSAlexander Leidinger 10599b6f430SDmitry Chagin static int linux_common_clock_gettime(struct thread *, clockid_t, 10699b6f430SDmitry Chagin struct timespec *); 10719f9a0e4SDmitry Chagin static int linux_common_clock_settime(struct thread *, clockid_t, 10819f9a0e4SDmitry Chagin struct timespec *); 109187715a4SDmitry Chagin static int linux_common_clock_getres(struct thread *, clockid_t, 110187715a4SDmitry Chagin struct timespec *); 1116501370aSDmitry Chagin static int linux_common_clock_nanosleep(struct thread *, clockid_t, 1126501370aSDmitry Chagin l_int, struct timespec *, struct timespec *); 11399b6f430SDmitry Chagin 1140670e972SDmitry Chagin int 115ad2056f2SAlexander Leidinger native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp) 116ad2056f2SAlexander Leidinger { 11719e252baSAlexander Leidinger 1180670e972SDmitry Chagin #ifdef COMPAT_LINUX32 11971b50d08SDmitry Chagin if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN) 1200670e972SDmitry Chagin return (EOVERFLOW); 1210670e972SDmitry Chagin #endif 122ad2056f2SAlexander Leidinger ltp->tv_sec = ntp->tv_sec; 123ad2056f2SAlexander Leidinger ltp->tv_nsec = ntp->tv_nsec; 12419e252baSAlexander Leidinger 1250670e972SDmitry Chagin return (0); 126ad2056f2SAlexander Leidinger } 127ad2056f2SAlexander Leidinger 12868098228SDmitry Chagin int 129ad2056f2SAlexander Leidinger linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp) 130ad2056f2SAlexander Leidinger { 13119e252baSAlexander Leidinger 13291e7bdcdSDmitry Chagin if (!timespecvalid_interval(ltp)) 13377424f41SJung-uk Kim return (EINVAL); 134ad2056f2SAlexander Leidinger ntp->tv_sec = ltp->tv_sec; 135ad2056f2SAlexander Leidinger ntp->tv_nsec = ltp->tv_nsec; 13677424f41SJung-uk Kim 13777424f41SJung-uk Kim return (0); 138ad2056f2SAlexander Leidinger } 139ad2056f2SAlexander Leidinger 1409a9482f8SDmitry Chagin int 1419a9482f8SDmitry Chagin linux_put_timespec(struct timespec *ntp, struct l_timespec *ltp) 1429a9482f8SDmitry Chagin { 1439a9482f8SDmitry Chagin struct l_timespec lts; 1449a9482f8SDmitry Chagin int error; 1459a9482f8SDmitry Chagin 1469a9482f8SDmitry Chagin error = native_to_linux_timespec(<s, ntp); 1479a9482f8SDmitry Chagin if (error != 0) 1489a9482f8SDmitry Chagin return (error); 1499a9482f8SDmitry Chagin return (copyout(<s, ltp, sizeof(lts))); 1509a9482f8SDmitry Chagin } 1519a9482f8SDmitry Chagin 152707e567aSDmitry Chagin int 153707e567aSDmitry Chagin linux_get_timespec(struct timespec *ntp, const struct l_timespec *ultp) 154707e567aSDmitry Chagin { 155707e567aSDmitry Chagin struct l_timespec lts; 156707e567aSDmitry Chagin int error; 157707e567aSDmitry Chagin 158707e567aSDmitry Chagin error = copyin(ultp, <s, sizeof(lts)); 159707e567aSDmitry Chagin if (error != 0) 160707e567aSDmitry Chagin return (error); 161707e567aSDmitry Chagin return (linux_to_native_timespec(ntp, <s)); 162707e567aSDmitry Chagin } 163707e567aSDmitry Chagin 164bfcce1a9SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 165bfcce1a9SDmitry Chagin int 166bfcce1a9SDmitry Chagin native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp) 167bfcce1a9SDmitry Chagin { 168bfcce1a9SDmitry Chagin 169bfcce1a9SDmitry Chagin ltp64->tv_sec = ntp->tv_sec; 170bfcce1a9SDmitry Chagin ltp64->tv_nsec = ntp->tv_nsec; 171bfcce1a9SDmitry Chagin 172bfcce1a9SDmitry Chagin return (0); 173bfcce1a9SDmitry Chagin } 174bfcce1a9SDmitry Chagin 175bfcce1a9SDmitry Chagin int 176bfcce1a9SDmitry Chagin linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64) 177bfcce1a9SDmitry Chagin { 178bfcce1a9SDmitry Chagin 1793dc2a067SDmitry Chagin #if defined(__i386__) 1803dc2a067SDmitry Chagin /* i386 time_t is still 32-bit */ 1813dc2a067SDmitry Chagin if (ltp64->tv_sec > INT_MAX || ltp64->tv_sec < INT_MIN) 1823dc2a067SDmitry Chagin return (EOVERFLOW); 1833dc2a067SDmitry Chagin #endif 1841579b320SDmitry Chagin /* Zero out the padding in compat mode. */ 1851579b320SDmitry Chagin ntp->tv_nsec = ltp64->tv_nsec & 0xFFFFFFFFUL; 186bfcce1a9SDmitry Chagin ntp->tv_sec = ltp64->tv_sec; 1871579b320SDmitry Chagin 1881579b320SDmitry Chagin if (!timespecvalid_interval(ntp)) 1891579b320SDmitry Chagin return (EINVAL); 190bfcce1a9SDmitry Chagin 191bfcce1a9SDmitry Chagin return (0); 192bfcce1a9SDmitry Chagin } 1939a9482f8SDmitry Chagin 1949a9482f8SDmitry Chagin int 1959a9482f8SDmitry Chagin linux_put_timespec64(struct timespec *ntp, struct l_timespec64 *ltp) 1969a9482f8SDmitry Chagin { 1979a9482f8SDmitry Chagin struct l_timespec64 lts; 1989a9482f8SDmitry Chagin int error; 1999a9482f8SDmitry Chagin 2009a9482f8SDmitry Chagin error = native_to_linux_timespec64(<s, ntp); 2019a9482f8SDmitry Chagin if (error != 0) 2029a9482f8SDmitry Chagin return (error); 2039a9482f8SDmitry Chagin return (copyout(<s, ltp, sizeof(lts))); 2049a9482f8SDmitry Chagin } 205707e567aSDmitry Chagin 206707e567aSDmitry Chagin int 207707e567aSDmitry Chagin linux_get_timespec64(struct timespec *ntp, const struct l_timespec64 *ultp) 208707e567aSDmitry Chagin { 209707e567aSDmitry Chagin struct l_timespec64 lts; 210707e567aSDmitry Chagin int error; 211707e567aSDmitry Chagin 212707e567aSDmitry Chagin error = copyin(ultp, <s, sizeof(lts)); 213707e567aSDmitry Chagin if (error != 0) 214707e567aSDmitry Chagin return (error); 215707e567aSDmitry Chagin return (linux_to_native_timespec64(ntp, <s)); 216707e567aSDmitry Chagin } 217bfcce1a9SDmitry Chagin #endif 218bfcce1a9SDmitry Chagin 21916ac71bcSDmitry Chagin int 220dd93b628SDmitry Chagin native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp) 221dd93b628SDmitry Chagin { 222dd93b628SDmitry Chagin int error; 223dd93b628SDmitry Chagin 224dd93b628SDmitry Chagin error = native_to_linux_timespec(<p->it_interval, &ntp->it_interval); 225dd93b628SDmitry Chagin if (error == 0) 2260938d04aSDmitry Chagin error = native_to_linux_timespec(<p->it_value, &ntp->it_value); 227dd93b628SDmitry Chagin return (error); 228dd93b628SDmitry Chagin } 229dd93b628SDmitry Chagin 230dd93b628SDmitry Chagin int 231dd93b628SDmitry Chagin linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp) 232dd93b628SDmitry Chagin { 233dd93b628SDmitry Chagin int error; 234dd93b628SDmitry Chagin 235dd93b628SDmitry Chagin error = linux_to_native_timespec(&ntp->it_interval, <p->it_interval); 236dd93b628SDmitry Chagin if (error == 0) 237dd93b628SDmitry Chagin error = linux_to_native_timespec(&ntp->it_value, <p->it_value); 238dd93b628SDmitry Chagin return (error); 239dd93b628SDmitry Chagin } 240dd93b628SDmitry Chagin 241783c1bd8SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 242783c1bd8SDmitry Chagin int 243783c1bd8SDmitry Chagin linux_to_native_itimerspec64(struct itimerspec *ntp, struct l_itimerspec64 *ltp) 244783c1bd8SDmitry Chagin { 245783c1bd8SDmitry Chagin int error; 246783c1bd8SDmitry Chagin 247783c1bd8SDmitry Chagin error = linux_to_native_timespec64(&ntp->it_interval, <p->it_interval); 248783c1bd8SDmitry Chagin if (error == 0) 249783c1bd8SDmitry Chagin error = linux_to_native_timespec64(&ntp->it_value, <p->it_value); 250783c1bd8SDmitry Chagin return (error); 251783c1bd8SDmitry Chagin } 252783c1bd8SDmitry Chagin 253783c1bd8SDmitry Chagin int 254783c1bd8SDmitry Chagin native_to_linux_itimerspec64(struct l_itimerspec64 *ltp, struct itimerspec *ntp) 255783c1bd8SDmitry Chagin { 256783c1bd8SDmitry Chagin int error; 257783c1bd8SDmitry Chagin 258783c1bd8SDmitry Chagin error = native_to_linux_timespec64(<p->it_interval, &ntp->it_interval); 259783c1bd8SDmitry Chagin if (error == 0) 260783c1bd8SDmitry Chagin error = native_to_linux_timespec64(<p->it_value, &ntp->it_value); 261783c1bd8SDmitry Chagin return (error); 262783c1bd8SDmitry Chagin } 263783c1bd8SDmitry Chagin #endif 264783c1bd8SDmitry Chagin 265dd93b628SDmitry Chagin int 266ad2056f2SAlexander Leidinger linux_to_native_clockid(clockid_t *n, clockid_t l) 267ad2056f2SAlexander Leidinger { 26819e252baSAlexander Leidinger 2692711aba9SDmitry Chagin if (l < 0) { 2702711aba9SDmitry Chagin /* cpu-clock */ 271452f4636SDmitry Chagin if (LINUX_CPUCLOCK_WHICH(l) == LINUX_CLOCKFD) { 272452f4636SDmitry Chagin LIN_SDT_PROBE1(time, linux_to_native_clockid, 273452f4636SDmitry Chagin unsupported_clockid, l); 274452f4636SDmitry Chagin return (ENOTSUP); 275452f4636SDmitry Chagin } 276539fadb4SDmitry Chagin if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD_MASK) 2772711aba9SDmitry Chagin return (EINVAL); 2782711aba9SDmitry Chagin 2792711aba9SDmitry Chagin if (LINUX_CPUCLOCK_PERTHREAD(l)) 2802711aba9SDmitry Chagin *n = CLOCK_THREAD_CPUTIME_ID; 2812711aba9SDmitry Chagin else 2822711aba9SDmitry Chagin *n = CLOCK_PROCESS_CPUTIME_ID; 2832711aba9SDmitry Chagin return (0); 2842711aba9SDmitry Chagin } 2852711aba9SDmitry Chagin 286ad2056f2SAlexander Leidinger switch (l) { 287ad2056f2SAlexander Leidinger case LINUX_CLOCK_REALTIME: 288ad2056f2SAlexander Leidinger *n = CLOCK_REALTIME; 289ad2056f2SAlexander Leidinger break; 290ad2056f2SAlexander Leidinger case LINUX_CLOCK_MONOTONIC: 291ad2056f2SAlexander Leidinger *n = CLOCK_MONOTONIC; 292ad2056f2SAlexander Leidinger break; 2937bc05ae6SDmitry Chagin case LINUX_CLOCK_PROCESS_CPUTIME_ID: 2947bc05ae6SDmitry Chagin *n = CLOCK_PROCESS_CPUTIME_ID; 2957bc05ae6SDmitry Chagin break; 2967bc05ae6SDmitry Chagin case LINUX_CLOCK_THREAD_CPUTIME_ID: 2977bc05ae6SDmitry Chagin *n = CLOCK_THREAD_CPUTIME_ID; 2987bc05ae6SDmitry Chagin break; 2992711aba9SDmitry Chagin case LINUX_CLOCK_REALTIME_COARSE: 3002711aba9SDmitry Chagin *n = CLOCK_REALTIME_FAST; 3012711aba9SDmitry Chagin break; 3022711aba9SDmitry Chagin case LINUX_CLOCK_MONOTONIC_COARSE: 303e37db348SAlexander Leidinger case LINUX_CLOCK_MONOTONIC_RAW: 3042711aba9SDmitry Chagin *n = CLOCK_MONOTONIC_FAST; 3052711aba9SDmitry Chagin break; 3062711aba9SDmitry Chagin case LINUX_CLOCK_BOOTTIME: 30725ada637SDmitry Chagin *n = CLOCK_UPTIME; 30825ada637SDmitry Chagin break; 3092711aba9SDmitry Chagin case LINUX_CLOCK_REALTIME_ALARM: 3102711aba9SDmitry Chagin case LINUX_CLOCK_BOOTTIME_ALARM: 3112711aba9SDmitry Chagin case LINUX_CLOCK_SGI_CYCLE: 3122711aba9SDmitry Chagin case LINUX_CLOCK_TAI: 31319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, 31419e252baSAlexander Leidinger unsupported_clockid, l); 315452f4636SDmitry Chagin return (ENOTSUP); 31677424f41SJung-uk Kim default: 31719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_to_native_clockid, 31819e252baSAlexander Leidinger unknown_clockid, l); 319452f4636SDmitry Chagin return (ENOTSUP); 320ad2056f2SAlexander Leidinger } 321ad2056f2SAlexander Leidinger 32277424f41SJung-uk Kim return (0); 323ad2056f2SAlexander Leidinger } 324ad2056f2SAlexander Leidinger 325ad2056f2SAlexander Leidinger int 326f0f58384SDmitry Chagin linux_to_native_timerflags(int *nflags, int flags) 327f0f58384SDmitry Chagin { 328f0f58384SDmitry Chagin 329f0f58384SDmitry Chagin if (flags & ~LINUX_TIMER_ABSTIME) 330f0f58384SDmitry Chagin return (EINVAL); 331f0f58384SDmitry Chagin *nflags = 0; 332f0f58384SDmitry Chagin if (flags & LINUX_TIMER_ABSTIME) 333f0f58384SDmitry Chagin *nflags |= TIMER_ABSTIME; 334f0f58384SDmitry Chagin return (0); 335f0f58384SDmitry Chagin } 336f0f58384SDmitry Chagin 33799b6f430SDmitry Chagin static int 33899b6f430SDmitry Chagin linux_common_clock_gettime(struct thread *td, clockid_t which, 33999b6f430SDmitry Chagin struct timespec *tp) 340ad2056f2SAlexander Leidinger { 3412711aba9SDmitry Chagin struct rusage ru; 3422711aba9SDmitry Chagin struct thread *targettd; 3432711aba9SDmitry Chagin struct proc *p; 3442711aba9SDmitry Chagin int error, clockwhich; 3452506c761SDmitry Chagin clockid_t nwhich; 3462711aba9SDmitry Chagin pid_t pid; 3472711aba9SDmitry Chagin lwpid_t tid; 348ad2056f2SAlexander Leidinger 34999b6f430SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 35019e252baSAlexander Leidinger if (error != 0) { 3514afe4faeSEdward Tomasz Napierala linux_msg(curthread, 35299b6f430SDmitry Chagin "unsupported clock_gettime clockid %d", which); 35399b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_gettime, 35499b6f430SDmitry Chagin conversion_error, error); 35577424f41SJung-uk Kim return (error); 35619e252baSAlexander Leidinger } 3572711aba9SDmitry Chagin 3582711aba9SDmitry Chagin switch (nwhich) { 3592711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 36099b6f430SDmitry Chagin if (which < 0) { 36199b6f430SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 36299b6f430SDmitry Chagin pid = LINUX_CPUCLOCK_ID(which); 3637bc05ae6SDmitry Chagin } else { 3647bc05ae6SDmitry Chagin clockwhich = LINUX_CPUCLOCK_SCHED; 3657bc05ae6SDmitry Chagin pid = 0; 3667bc05ae6SDmitry Chagin } 3672711aba9SDmitry Chagin if (pid == 0) { 3682711aba9SDmitry Chagin p = td->td_proc; 3692711aba9SDmitry Chagin PROC_LOCK(p); 3702711aba9SDmitry Chagin } else { 3712711aba9SDmitry Chagin error = pget(pid, PGET_CANSEE, &p); 3722711aba9SDmitry Chagin if (error != 0) 3732711aba9SDmitry Chagin return (EINVAL); 3742711aba9SDmitry Chagin } 3752711aba9SDmitry Chagin switch (clockwhich) { 3762711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 3772711aba9SDmitry Chagin PROC_STATLOCK(p); 3782711aba9SDmitry Chagin calcru(p, &ru.ru_utime, &ru.ru_stime); 3792711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3802711aba9SDmitry Chagin PROC_UNLOCK(p); 3812711aba9SDmitry Chagin timevaladd(&ru.ru_utime, &ru.ru_stime); 38299b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 3832711aba9SDmitry Chagin break; 3842711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 3852711aba9SDmitry Chagin PROC_STATLOCK(p); 3862711aba9SDmitry Chagin calcru(p, &ru.ru_utime, &ru.ru_stime); 3872711aba9SDmitry Chagin PROC_STATUNLOCK(p); 3882711aba9SDmitry Chagin PROC_UNLOCK(p); 38999b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 3902711aba9SDmitry Chagin break; 3912711aba9SDmitry Chagin case LINUX_CPUCLOCK_SCHED: 39299b6f430SDmitry Chagin kern_process_cputime(p, tp); 3932711aba9SDmitry Chagin PROC_UNLOCK(p); 3942711aba9SDmitry Chagin break; 3952711aba9SDmitry Chagin default: 3962711aba9SDmitry Chagin PROC_UNLOCK(p); 3972711aba9SDmitry Chagin return (EINVAL); 3982711aba9SDmitry Chagin } 3992711aba9SDmitry Chagin 4002711aba9SDmitry Chagin break; 4012711aba9SDmitry Chagin 4022711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 40399b6f430SDmitry Chagin if (which < 0) { 40499b6f430SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 40599b6f430SDmitry Chagin tid = LINUX_CPUCLOCK_ID(which); 4067bc05ae6SDmitry Chagin } else { 4077bc05ae6SDmitry Chagin clockwhich = LINUX_CPUCLOCK_SCHED; 4087bc05ae6SDmitry Chagin tid = 0; 4097bc05ae6SDmitry Chagin } 4107bc05ae6SDmitry Chagin p = td->td_proc; 4112711aba9SDmitry Chagin if (tid == 0) { 4122711aba9SDmitry Chagin targettd = td; 4132711aba9SDmitry Chagin PROC_LOCK(p); 4142711aba9SDmitry Chagin } else { 4157bc05ae6SDmitry Chagin targettd = linux_tdfind(td, tid, p->p_pid); 4162711aba9SDmitry Chagin if (targettd == NULL) 4172711aba9SDmitry Chagin return (EINVAL); 4182711aba9SDmitry Chagin } 4192711aba9SDmitry Chagin switch (clockwhich) { 4202711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 4212711aba9SDmitry Chagin PROC_STATLOCK(p); 4222711aba9SDmitry Chagin thread_lock(targettd); 4232711aba9SDmitry Chagin rufetchtd(targettd, &ru); 4242711aba9SDmitry Chagin thread_unlock(targettd); 4252711aba9SDmitry Chagin PROC_STATUNLOCK(p); 4262711aba9SDmitry Chagin PROC_UNLOCK(p); 4272711aba9SDmitry Chagin timevaladd(&ru.ru_utime, &ru.ru_stime); 42899b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 4292711aba9SDmitry Chagin break; 4302711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 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); 43799b6f430SDmitry Chagin TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp); 4382711aba9SDmitry Chagin break; 4392711aba9SDmitry Chagin case LINUX_CPUCLOCK_SCHED: 4407bc05ae6SDmitry Chagin if (td == targettd) 4417bc05ae6SDmitry Chagin targettd = NULL; 44299b6f430SDmitry Chagin kern_thread_cputime(targettd, tp); 4432711aba9SDmitry Chagin PROC_UNLOCK(p); 4442711aba9SDmitry Chagin break; 4452711aba9SDmitry Chagin default: 4462711aba9SDmitry Chagin PROC_UNLOCK(p); 4472711aba9SDmitry Chagin return (EINVAL); 4482711aba9SDmitry Chagin } 4492711aba9SDmitry Chagin break; 4502711aba9SDmitry Chagin 4512711aba9SDmitry Chagin default: 45299b6f430SDmitry Chagin error = kern_clock_gettime(td, nwhich, tp); 4532711aba9SDmitry Chagin break; 4542711aba9SDmitry Chagin } 45599b6f430SDmitry Chagin 45699b6f430SDmitry Chagin return (error); 45799b6f430SDmitry Chagin } 45899b6f430SDmitry Chagin 45999b6f430SDmitry Chagin int 46099b6f430SDmitry Chagin linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args) 46199b6f430SDmitry Chagin { 46299b6f430SDmitry Chagin struct timespec tp; 46399b6f430SDmitry Chagin int error; 46499b6f430SDmitry Chagin 46599b6f430SDmitry Chagin error = linux_common_clock_gettime(td, args->which, &tp); 46619e252baSAlexander Leidinger if (error != 0) { 46719e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error); 46877424f41SJung-uk Kim return (error); 46919e252baSAlexander Leidinger } 4709a9482f8SDmitry Chagin error = linux_put_timespec(&tp, args->tp); 47119e252baSAlexander Leidinger if (error != 0) 47219e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error); 47319e252baSAlexander Leidinger 47419e252baSAlexander Leidinger return (error); 475ad2056f2SAlexander Leidinger } 476ad2056f2SAlexander Leidinger 47799b6f430SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 47899b6f430SDmitry Chagin int 47999b6f430SDmitry Chagin linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args) 48099b6f430SDmitry Chagin { 48199b6f430SDmitry Chagin struct timespec tp; 48299b6f430SDmitry Chagin int error; 48399b6f430SDmitry Chagin 48499b6f430SDmitry Chagin error = linux_common_clock_gettime(td, args->which, &tp); 48599b6f430SDmitry Chagin if (error != 0) { 48699b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error); 48799b6f430SDmitry Chagin return (error); 48899b6f430SDmitry Chagin } 4899a9482f8SDmitry Chagin error = linux_put_timespec64(&tp, args->tp); 49099b6f430SDmitry Chagin if (error != 0) 49199b6f430SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error); 49299b6f430SDmitry Chagin 49399b6f430SDmitry Chagin return (error); 49499b6f430SDmitry Chagin } 49599b6f430SDmitry Chagin #endif 49699b6f430SDmitry Chagin 49719f9a0e4SDmitry Chagin static int 49819f9a0e4SDmitry Chagin linux_common_clock_settime(struct thread *td, clockid_t which, 49919f9a0e4SDmitry Chagin struct timespec *ts) 50019f9a0e4SDmitry Chagin { 50119f9a0e4SDmitry Chagin int error; 50219f9a0e4SDmitry Chagin clockid_t nwhich; 50319f9a0e4SDmitry Chagin 50419f9a0e4SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 50519f9a0e4SDmitry Chagin if (error != 0) { 50619f9a0e4SDmitry Chagin linux_msg(curthread, 50719f9a0e4SDmitry Chagin "unsupported clock_settime clockid %d", which); 50819f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error, 50919f9a0e4SDmitry Chagin error); 51019f9a0e4SDmitry Chagin return (error); 51119f9a0e4SDmitry Chagin } 51219f9a0e4SDmitry Chagin 51319f9a0e4SDmitry Chagin error = kern_clock_settime(td, nwhich, ts); 51419f9a0e4SDmitry Chagin if (error != 0) 51519f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_settime, 51619f9a0e4SDmitry Chagin settime_error, error); 51719f9a0e4SDmitry Chagin 51819f9a0e4SDmitry Chagin return (error); 51919f9a0e4SDmitry Chagin } 52019f9a0e4SDmitry Chagin 521ad2056f2SAlexander Leidinger int 522ad2056f2SAlexander Leidinger linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args) 523ad2056f2SAlexander Leidinger { 524ad2056f2SAlexander Leidinger struct timespec ts; 525ad2056f2SAlexander Leidinger int error; 526ad2056f2SAlexander Leidinger 527707e567aSDmitry Chagin error = linux_get_timespec(&ts, args->tp); 52819e252baSAlexander Leidinger if (error != 0) { 52919e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error); 53019e252baSAlexander Leidinger return (error); 53119e252baSAlexander Leidinger } 53219f9a0e4SDmitry Chagin return (linux_common_clock_settime(td, args->which, &ts)); 53319e252baSAlexander Leidinger } 53419e252baSAlexander Leidinger 53519f9a0e4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 53619f9a0e4SDmitry Chagin int 53719f9a0e4SDmitry Chagin linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args) 53819f9a0e4SDmitry Chagin { 53919f9a0e4SDmitry Chagin struct timespec ts; 54019f9a0e4SDmitry Chagin int error; 54119f9a0e4SDmitry Chagin 542707e567aSDmitry Chagin error = linux_get_timespec64(&ts, args->tp); 54319f9a0e4SDmitry Chagin if (error != 0) { 54419f9a0e4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error); 54519f9a0e4SDmitry Chagin return (error); 54619f9a0e4SDmitry Chagin } 54719f9a0e4SDmitry Chagin return (linux_common_clock_settime(td, args->which, &ts)); 548ad2056f2SAlexander Leidinger } 54919f9a0e4SDmitry Chagin #endif 550ad2056f2SAlexander Leidinger 551187715a4SDmitry Chagin static int 552187715a4SDmitry Chagin linux_common_clock_getres(struct thread *td, clockid_t which, 553187715a4SDmitry Chagin struct timespec *ts) 554ad2056f2SAlexander Leidinger { 5552711aba9SDmitry Chagin struct proc *p; 5562711aba9SDmitry Chagin int error, clockwhich; 5572506c761SDmitry Chagin clockid_t nwhich; 5582711aba9SDmitry Chagin pid_t pid; 5592711aba9SDmitry Chagin lwpid_t tid; 560ad2056f2SAlexander Leidinger 561187715a4SDmitry Chagin error = linux_to_native_clockid(&nwhich, which); 56219e252baSAlexander Leidinger if (error != 0) { 5634afe4faeSEdward Tomasz Napierala linux_msg(curthread, 564187715a4SDmitry Chagin "unsupported clock_getres clockid %d", which); 565187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_getres, 566187715a4SDmitry Chagin conversion_error, error); 56777424f41SJung-uk Kim return (error); 56819e252baSAlexander Leidinger } 5692711aba9SDmitry Chagin 5702711aba9SDmitry Chagin /* 5712711aba9SDmitry Chagin * Check user supplied clock id in case of per-process 5722711aba9SDmitry Chagin * or thread-specific cpu-time clock. 5732711aba9SDmitry Chagin */ 574187715a4SDmitry Chagin if (which < 0) { 5752711aba9SDmitry Chagin switch (nwhich) { 5762711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 577187715a4SDmitry Chagin tid = LINUX_CPUCLOCK_ID(which); 5782711aba9SDmitry Chagin if (tid != 0) { 5792711aba9SDmitry Chagin p = td->td_proc; 5807bc05ae6SDmitry Chagin if (linux_tdfind(td, tid, p->p_pid) == NULL) 5817bc05ae6SDmitry Chagin return (EINVAL); 5822711aba9SDmitry Chagin PROC_UNLOCK(p); 5832711aba9SDmitry Chagin } 5842711aba9SDmitry Chagin break; 5852711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 586187715a4SDmitry Chagin pid = LINUX_CPUCLOCK_ID(which); 5872711aba9SDmitry Chagin if (pid != 0) { 5882711aba9SDmitry Chagin error = pget(pid, PGET_CANSEE, &p); 5892711aba9SDmitry Chagin if (error != 0) 5902711aba9SDmitry Chagin return (EINVAL); 5912711aba9SDmitry Chagin PROC_UNLOCK(p); 5922711aba9SDmitry Chagin } 5932711aba9SDmitry Chagin break; 5942711aba9SDmitry Chagin } 5957bc05ae6SDmitry Chagin } 5962711aba9SDmitry Chagin 597187715a4SDmitry Chagin if (ts == NULL) { 598187715a4SDmitry Chagin LIN_SDT_PROBE0(time, linux_common_clock_getres, nullcall); 5992711aba9SDmitry Chagin return (0); 6002711aba9SDmitry Chagin } 6012711aba9SDmitry Chagin 6022711aba9SDmitry Chagin switch (nwhich) { 6032711aba9SDmitry Chagin case CLOCK_THREAD_CPUTIME_ID: 6042711aba9SDmitry Chagin case CLOCK_PROCESS_CPUTIME_ID: 605187715a4SDmitry Chagin clockwhich = LINUX_CPUCLOCK_WHICH(which); 6067bc05ae6SDmitry Chagin /* 6077bc05ae6SDmitry Chagin * In both cases (when the clock id obtained by a call to 6087bc05ae6SDmitry Chagin * clock_getcpuclockid() or using the clock 6097bc05ae6SDmitry Chagin * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision 6107bc05ae6SDmitry Chagin * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock. 6117bc05ae6SDmitry Chagin * 6127bc05ae6SDmitry Chagin * See Linux posix_cpu_clock_getres() implementation. 6137bc05ae6SDmitry Chagin */ 614187715a4SDmitry Chagin if (which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) { 615187715a4SDmitry Chagin ts->tv_sec = 0; 616187715a4SDmitry Chagin ts->tv_nsec = 1; 6177bc05ae6SDmitry Chagin goto out; 6187bc05ae6SDmitry Chagin } 6197bc05ae6SDmitry Chagin 6202711aba9SDmitry Chagin switch (clockwhich) { 6212711aba9SDmitry Chagin case LINUX_CPUCLOCK_PROF: 6222711aba9SDmitry Chagin nwhich = CLOCK_PROF; 6232711aba9SDmitry Chagin break; 6242711aba9SDmitry Chagin case LINUX_CPUCLOCK_VIRT: 6252711aba9SDmitry Chagin nwhich = CLOCK_VIRTUAL; 6262711aba9SDmitry Chagin break; 6272711aba9SDmitry Chagin default: 6282711aba9SDmitry Chagin return (EINVAL); 6292711aba9SDmitry Chagin } 6302711aba9SDmitry Chagin break; 6312711aba9SDmitry Chagin 6322711aba9SDmitry Chagin default: 6332711aba9SDmitry Chagin break; 6342711aba9SDmitry Chagin } 635187715a4SDmitry Chagin error = kern_clock_getres(td, nwhich, ts); 63619e252baSAlexander Leidinger if (error != 0) { 637187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_getres, 638187715a4SDmitry Chagin getres_error, error); 63977424f41SJung-uk Kim return (error); 64019e252baSAlexander Leidinger } 6417bc05ae6SDmitry Chagin 6427bc05ae6SDmitry Chagin out: 643187715a4SDmitry Chagin return (error); 644187715a4SDmitry Chagin } 645187715a4SDmitry Chagin 646187715a4SDmitry Chagin int 647187715a4SDmitry Chagin linux_clock_getres(struct thread *td, 648187715a4SDmitry Chagin struct linux_clock_getres_args *args) 649187715a4SDmitry Chagin { 650187715a4SDmitry Chagin struct timespec ts; 651187715a4SDmitry Chagin int error; 652187715a4SDmitry Chagin 653187715a4SDmitry Chagin error = linux_common_clock_getres(td, args->which, &ts); 654187715a4SDmitry Chagin if (error != 0 || args->tp == NULL) 655187715a4SDmitry Chagin return (error); 6569a9482f8SDmitry Chagin error = linux_put_timespec(&ts, args->tp); 65719e252baSAlexander Leidinger if (error != 0) 658187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_getres, 659187715a4SDmitry Chagin copyout_error, error); 66019e252baSAlexander Leidinger return (error); 66177424f41SJung-uk Kim } 66277424f41SJung-uk Kim 663187715a4SDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 664187715a4SDmitry Chagin int 665187715a4SDmitry Chagin linux_clock_getres_time64(struct thread *td, 666187715a4SDmitry Chagin struct linux_clock_getres_time64_args *args) 667187715a4SDmitry Chagin { 668187715a4SDmitry Chagin struct timespec ts; 669187715a4SDmitry Chagin int error; 670187715a4SDmitry Chagin 671187715a4SDmitry Chagin error = linux_common_clock_getres(td, args->which, &ts); 672187715a4SDmitry Chagin if (error != 0 || args->tp == NULL) 673187715a4SDmitry Chagin return (error); 6749a9482f8SDmitry Chagin error = linux_put_timespec64(&ts, args->tp); 675187715a4SDmitry Chagin if (error != 0) 676187715a4SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_getres_time64, 677187715a4SDmitry Chagin copyout_error, error); 678187715a4SDmitry Chagin return (error); 679187715a4SDmitry Chagin } 680187715a4SDmitry Chagin #endif 681187715a4SDmitry Chagin 68277424f41SJung-uk Kim int 68377424f41SJung-uk Kim linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args) 68477424f41SJung-uk Kim { 68577424f41SJung-uk Kim struct timespec *rmtp; 68677424f41SJung-uk Kim struct timespec rqts, rmts; 6875c2748d5SDmitry Chagin int error, error2; 68877424f41SJung-uk Kim 689707e567aSDmitry Chagin error = linux_get_timespec(&rqts, args->rqtp); 69019e252baSAlexander Leidinger if (error != 0) { 69119e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error); 69277424f41SJung-uk Kim return (error); 69319e252baSAlexander Leidinger } 69477424f41SJung-uk Kim if (args->rmtp != NULL) 69577424f41SJung-uk Kim rmtp = &rmts; 69677424f41SJung-uk Kim else 69777424f41SJung-uk Kim rmtp = NULL; 69877424f41SJung-uk Kim 69977424f41SJung-uk Kim error = kern_nanosleep(td, &rqts, rmtp); 7004cf66812SEric van Gyzen if (error == EINTR && args->rmtp != NULL) { 7019a9482f8SDmitry Chagin error2 = linux_put_timespec(rmtp, args->rmtp); 7025c2748d5SDmitry Chagin if (error2 != 0) { 70319e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error, 7045c2748d5SDmitry Chagin error2); 7055c2748d5SDmitry Chagin return (error2); 70677424f41SJung-uk Kim } 70719e252baSAlexander Leidinger } 70877424f41SJung-uk Kim 7095c2748d5SDmitry Chagin return (error); 710ad2056f2SAlexander Leidinger } 711ad2056f2SAlexander Leidinger 7126501370aSDmitry Chagin static int 7136501370aSDmitry Chagin linux_common_clock_nanosleep(struct thread *td, clockid_t which, 7146501370aSDmitry Chagin l_int lflags, struct timespec *rqtp, struct timespec *rmtp) 7156501370aSDmitry Chagin { 7166501370aSDmitry Chagin int error, flags; 7176501370aSDmitry Chagin clockid_t clockid; 7186501370aSDmitry Chagin 7196501370aSDmitry Chagin error = linux_to_native_timerflags(&flags, lflags); 7206501370aSDmitry Chagin if (error != 0) { 7216501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_nanosleep, 7226501370aSDmitry Chagin unsupported_flags, lflags); 7236501370aSDmitry Chagin return (error); 7246501370aSDmitry Chagin } 7256501370aSDmitry Chagin 7266501370aSDmitry Chagin error = linux_to_native_clockid(&clockid, which); 7276501370aSDmitry Chagin if (error != 0) { 7286501370aSDmitry Chagin linux_msg(curthread, 7296501370aSDmitry Chagin "unsupported clock_nanosleep clockid %d", which); 7306501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_common_clock_nanosleep, 7316501370aSDmitry Chagin unsupported_clockid, which); 7326501370aSDmitry Chagin return (error); 7336501370aSDmitry Chagin } 73466e73ce7SDmitry Chagin if (clockid == CLOCK_THREAD_CPUTIME_ID) 73566e73ce7SDmitry Chagin return (ENOTSUP); 7366501370aSDmitry Chagin 7376501370aSDmitry Chagin return (kern_clock_nanosleep(td, clockid, flags, rqtp, rmtp)); 7386501370aSDmitry Chagin } 7396501370aSDmitry Chagin 740ad2056f2SAlexander Leidinger int 7416501370aSDmitry Chagin linux_clock_nanosleep(struct thread *td, 7426501370aSDmitry Chagin struct linux_clock_nanosleep_args *args) 743ad2056f2SAlexander Leidinger { 744ad2056f2SAlexander Leidinger struct timespec *rmtp; 745ad2056f2SAlexander Leidinger struct timespec rqts, rmts; 7466501370aSDmitry Chagin int error, error2; 747ad2056f2SAlexander Leidinger 748707e567aSDmitry Chagin error = linux_get_timespec(&rqts, args->rqtp); 74919e252baSAlexander Leidinger if (error != 0) { 75019e252baSAlexander Leidinger LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error, 75119e252baSAlexander Leidinger error); 75277424f41SJung-uk Kim return (error); 75319e252baSAlexander Leidinger } 754ad2056f2SAlexander Leidinger if (args->rmtp != NULL) 755ad2056f2SAlexander Leidinger rmtp = &rmts; 756ad2056f2SAlexander Leidinger else 757ad2056f2SAlexander Leidinger rmtp = NULL; 758ad2056f2SAlexander Leidinger 7596501370aSDmitry Chagin error = linux_common_clock_nanosleep(td, args->which, args->flags, 7606501370aSDmitry Chagin &rqts, rmtp); 7616501370aSDmitry Chagin if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 && 762f0f58384SDmitry Chagin args->rmtp != NULL) { 7639a9482f8SDmitry Chagin error2 = linux_put_timespec(rmtp, args->rmtp); 7645c2748d5SDmitry Chagin if (error2 != 0) { 7655c2748d5SDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep, 7665c2748d5SDmitry Chagin copyout_error, error2); 7675c2748d5SDmitry Chagin return (error2); 7685c2748d5SDmitry Chagin } 7695c2748d5SDmitry Chagin } 77077424f41SJung-uk Kim return (error); 77119e252baSAlexander Leidinger } 7726501370aSDmitry Chagin 7736501370aSDmitry Chagin #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) 7746501370aSDmitry Chagin int 7756501370aSDmitry Chagin linux_clock_nanosleep_time64(struct thread *td, 7766501370aSDmitry Chagin struct linux_clock_nanosleep_time64_args *args) 7776501370aSDmitry Chagin { 7786501370aSDmitry Chagin struct timespec *rmtp; 7796501370aSDmitry Chagin struct timespec rqts, rmts; 7806501370aSDmitry Chagin int error, error2; 7816501370aSDmitry Chagin 782707e567aSDmitry Chagin error = linux_get_timespec64(&rqts, args->rqtp); 7836501370aSDmitry Chagin if (error != 0) { 7846501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64, 7856501370aSDmitry Chagin copyin_error, error); 7866501370aSDmitry Chagin return (error); 7876501370aSDmitry Chagin } 7886501370aSDmitry Chagin if (args->rmtp != NULL) 7896501370aSDmitry Chagin rmtp = &rmts; 7906501370aSDmitry Chagin else 7916501370aSDmitry Chagin rmtp = NULL; 7926501370aSDmitry Chagin 7936501370aSDmitry Chagin error = linux_common_clock_nanosleep(td, args->which, args->flags, 7946501370aSDmitry Chagin &rqts, rmtp); 7956501370aSDmitry Chagin if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 && 7966501370aSDmitry Chagin args->rmtp != NULL) { 7979a9482f8SDmitry Chagin error2 = linux_put_timespec64(rmtp, args->rmtp); 7986501370aSDmitry Chagin if (error2 != 0) { 7996501370aSDmitry Chagin LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64, 8006501370aSDmitry Chagin copyout_error, error2); 8016501370aSDmitry Chagin return (error2); 8026501370aSDmitry Chagin } 8036501370aSDmitry Chagin } 8046501370aSDmitry Chagin return (error); 8056501370aSDmitry Chagin } 8066501370aSDmitry Chagin #endif 807