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