The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linux/linux_time.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */
    2 
    3 /*-
    4  * SPDX-License-Identifier: BSD-2-Clause-NetBSD
    5  *
    6  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    7  * All rights reserved.
    8  *
    9  * This code is derived from software contributed to The NetBSD Foundation
   10  * by Emmanuel Dreyfus.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31  * POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 #if 0
   37 __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $");
   38 #endif
   39 
   40 #include "opt_compat.h"
   41 
   42 #include <sys/param.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/ucred.h>
   46 #include <sys/limits.h>
   47 #include <sys/mount.h>
   48 #include <sys/mutex.h>
   49 #include <sys/resourcevar.h>
   50 #include <sys/sdt.h>
   51 #include <sys/signal.h>
   52 #include <sys/stdint.h>
   53 #include <sys/syscallsubr.h>
   54 #include <sys/sysproto.h>
   55 #include <sys/time.h>
   56 #include <sys/systm.h>
   57 #include <sys/proc.h>
   58 
   59 #ifdef COMPAT_LINUX32
   60 #include <machine/../linux32/linux.h>
   61 #include <machine/../linux32/linux32_proto.h>
   62 #else
   63 #include <machine/../linux/linux.h>
   64 #include <machine/../linux/linux_proto.h>
   65 #endif
   66 
   67 #include <compat/linux/linux_dtrace.h>
   68 #include <compat/linux/linux_misc.h>
   69 #include <compat/linux/linux_timer.h>
   70 #include <compat/linux/linux_util.h>
   71 
   72 /* DTrace init */
   73 LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
   74 
   75 /**
   76  * DTrace probes in this module.
   77  */
   78 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
   79     "clockid_t");
   80 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
   81     "clockid_t");
   82 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_gettime, conversion_error, "int");
   83 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
   84 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
   85 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
   86 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, gettime_error, "int");
   87 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime64, copyout_error, "int");
   88 #endif
   89 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
   90 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, settime_error, "int");
   91 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_settime, conversion_error, "int");
   92 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
   93 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
   94 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, conversion_error, "int");
   95 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime64, copyin_error, "int");
   96 #endif
   97 LIN_SDT_PROBE_DEFINE0(time, linux_common_clock_getres, nullcall);
   98 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, conversion_error, "int");
   99 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_getres, getres_error, "int");
  100 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
  101 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  102 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres_time64, copyout_error, "int");
  103 #endif
  104 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
  105 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
  106 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
  107 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
  108 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int");
  109 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int");
  110 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  111 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int");
  112 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int");
  113 #endif
  114 
  115 static int      linux_common_clock_gettime(struct thread *, clockid_t,
  116                     struct timespec *);
  117 static int      linux_common_clock_settime(struct thread *, clockid_t,
  118                     struct timespec *);
  119 static int      linux_common_clock_getres(struct thread *, clockid_t,
  120                     struct timespec *);
  121 static int      linux_common_clock_nanosleep(struct thread *, clockid_t,
  122                     l_int, struct timespec *, struct timespec *);
  123 
  124 int
  125 native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
  126 {
  127 
  128 #ifdef COMPAT_LINUX32
  129         if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN)
  130                 return (EOVERFLOW);
  131 #endif
  132         ltp->tv_sec = ntp->tv_sec;
  133         ltp->tv_nsec = ntp->tv_nsec;
  134 
  135         return (0);
  136 }
  137 
  138 int
  139 linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
  140 {
  141 
  142         if (!timespecvalid_interval(ltp))
  143                 return (EINVAL);
  144         ntp->tv_sec = ltp->tv_sec;
  145         ntp->tv_nsec = ltp->tv_nsec;
  146 
  147         return (0);
  148 }
  149 
  150 int
  151 linux_put_timespec(struct timespec *ntp, struct l_timespec *ltp)
  152 {
  153         struct l_timespec lts;
  154         int error;
  155 
  156         error = native_to_linux_timespec(&lts, ntp);
  157         if (error != 0)
  158                 return (error);
  159         return (copyout(&lts, ltp, sizeof(lts)));
  160 }
  161 
  162 int
  163 linux_get_timespec(struct timespec *ntp, const struct l_timespec *ultp)
  164 {
  165         struct l_timespec lts;
  166         int error;
  167 
  168         error = copyin(ultp, &lts, sizeof(lts));
  169         if (error != 0)
  170                 return (error);
  171         return (linux_to_native_timespec(ntp, &lts));
  172 }
  173 
  174 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  175 int
  176 native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
  177 {
  178 
  179         ltp64->tv_sec = ntp->tv_sec;
  180         ltp64->tv_nsec = ntp->tv_nsec;
  181 
  182         return (0);
  183 }
  184 
  185 int
  186 linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64)
  187 {
  188 
  189 #if defined(__i386__)
  190         /* i386 time_t is still 32-bit */
  191         if (ltp64->tv_sec > INT_MAX || ltp64->tv_sec < INT_MIN)
  192                 return (EOVERFLOW);
  193 #endif
  194         /* Zero out the padding in compat mode. */
  195         ntp->tv_nsec = ltp64->tv_nsec & 0xFFFFFFFFUL;
  196         ntp->tv_sec = ltp64->tv_sec;
  197 
  198         if (!timespecvalid_interval(ntp))
  199                 return (EINVAL);
  200 
  201         return (0);
  202 }
  203 
  204 int
  205 linux_put_timespec64(struct timespec *ntp, struct l_timespec64 *ltp)
  206 {
  207         struct l_timespec64 lts;
  208         int error;
  209 
  210         error = native_to_linux_timespec64(&lts, ntp);
  211         if (error != 0)
  212                 return (error);
  213         return (copyout(&lts, ltp, sizeof(lts)));
  214 }
  215 
  216 int
  217 linux_get_timespec64(struct timespec *ntp, const struct l_timespec64 *ultp)
  218 {
  219         struct l_timespec64 lts;
  220         int error;
  221 
  222         error = copyin(ultp, &lts, sizeof(lts));
  223         if (error != 0)
  224                 return (error);
  225         return (linux_to_native_timespec64(ntp, &lts));
  226 }
  227 #endif
  228 
  229 int
  230 native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
  231 {
  232         int error;
  233 
  234         error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
  235         if (error == 0)
  236                 error = native_to_linux_timespec(&ltp->it_value, &ntp->it_value);
  237         return (error);
  238 }
  239 
  240 int
  241 linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
  242 {
  243         int error;
  244 
  245         error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
  246         if (error == 0)
  247                 error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
  248         return (error);
  249 }
  250 
  251 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  252 int
  253 linux_to_native_itimerspec64(struct itimerspec *ntp, struct l_itimerspec64 *ltp)
  254 {
  255         int error;
  256 
  257         error = linux_to_native_timespec64(&ntp->it_interval, &ltp->it_interval);
  258         if (error == 0)
  259                 error = linux_to_native_timespec64(&ntp->it_value, &ltp->it_value);
  260         return (error);
  261 }
  262 
  263 int
  264 native_to_linux_itimerspec64(struct l_itimerspec64 *ltp, struct itimerspec *ntp)
  265 {
  266         int error;
  267 
  268         error = native_to_linux_timespec64(&ltp->it_interval, &ntp->it_interval);
  269         if (error == 0)
  270                 error = native_to_linux_timespec64(&ltp->it_value, &ntp->it_value);
  271         return (error);
  272 }
  273 #endif
  274 
  275 int
  276 linux_to_native_clockid(clockid_t *n, clockid_t l)
  277 {
  278 
  279         if (l < 0) {
  280                 /* cpu-clock */
  281                 if (LINUX_CPUCLOCK_WHICH(l) == LINUX_CLOCKFD) {
  282                         LIN_SDT_PROBE1(time, linux_to_native_clockid,
  283                             unsupported_clockid, l);
  284                         return (ENOTSUP);
  285                 }
  286                 if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD_MASK)
  287                         return (EINVAL);
  288 
  289                 if (LINUX_CPUCLOCK_PERTHREAD(l))
  290                         *n = CLOCK_THREAD_CPUTIME_ID;
  291                 else
  292                         *n = CLOCK_PROCESS_CPUTIME_ID;
  293                 return (0);
  294         }
  295 
  296         switch (l) {
  297         case LINUX_CLOCK_REALTIME:
  298                 *n = CLOCK_REALTIME;
  299                 break;
  300         case LINUX_CLOCK_MONOTONIC:
  301                 *n = CLOCK_MONOTONIC;
  302                 break;
  303         case LINUX_CLOCK_PROCESS_CPUTIME_ID:
  304                 *n = CLOCK_PROCESS_CPUTIME_ID;
  305                 break;
  306         case LINUX_CLOCK_THREAD_CPUTIME_ID:
  307                 *n = CLOCK_THREAD_CPUTIME_ID;
  308                 break;
  309         case LINUX_CLOCK_REALTIME_COARSE:
  310                 *n = CLOCK_REALTIME_FAST;
  311                 break;
  312         case LINUX_CLOCK_MONOTONIC_COARSE:
  313         case LINUX_CLOCK_MONOTONIC_RAW:
  314                 *n = CLOCK_MONOTONIC_FAST;
  315                 break;
  316         case LINUX_CLOCK_BOOTTIME:
  317                 *n = CLOCK_UPTIME;
  318                 break;
  319         case LINUX_CLOCK_REALTIME_ALARM:
  320         case LINUX_CLOCK_BOOTTIME_ALARM:
  321         case LINUX_CLOCK_SGI_CYCLE:
  322         case LINUX_CLOCK_TAI:
  323                 LIN_SDT_PROBE1(time, linux_to_native_clockid,
  324                     unsupported_clockid, l);
  325                 return (ENOTSUP);
  326         default:
  327                 LIN_SDT_PROBE1(time, linux_to_native_clockid,
  328                     unknown_clockid, l);
  329                 return (ENOTSUP);
  330         }
  331 
  332         return (0);
  333 }
  334 
  335 int
  336 linux_to_native_timerflags(int *nflags, int flags)
  337 {
  338 
  339         if (flags & ~LINUX_TIMER_ABSTIME)
  340                 return (EINVAL);
  341         *nflags = 0;
  342         if (flags & LINUX_TIMER_ABSTIME)
  343                 *nflags |= TIMER_ABSTIME;
  344         return (0);
  345 }
  346 
  347 static int
  348 linux_common_clock_gettime(struct thread *td, clockid_t which,
  349     struct timespec *tp)
  350 {
  351         struct rusage ru;
  352         struct thread *targettd;
  353         struct proc *p;
  354         int error, clockwhich;
  355         clockid_t nwhich;
  356         pid_t pid;
  357         lwpid_t tid;
  358 
  359         error = linux_to_native_clockid(&nwhich, which);
  360         if (error != 0) {
  361                 linux_msg(curthread,
  362                     "unsupported clock_gettime clockid %d", which);
  363                 LIN_SDT_PROBE1(time, linux_common_clock_gettime,
  364                     conversion_error, error);
  365                 return (error);
  366         }
  367 
  368         switch (nwhich) {
  369         case CLOCK_PROCESS_CPUTIME_ID:
  370                 if (which < 0) {
  371                         clockwhich = LINUX_CPUCLOCK_WHICH(which);
  372                         pid = LINUX_CPUCLOCK_ID(which);
  373                 } else {
  374                         clockwhich = LINUX_CPUCLOCK_SCHED;
  375                         pid = 0;
  376                 }
  377                 if (pid == 0) {
  378                         p = td->td_proc;
  379                         PROC_LOCK(p);
  380                 } else {
  381                         error = pget(pid, PGET_CANSEE, &p);
  382                         if (error != 0)
  383                                 return (EINVAL);
  384                 }
  385                 switch (clockwhich) {
  386                 case LINUX_CPUCLOCK_PROF:
  387                         PROC_STATLOCK(p);
  388                         calcru(p, &ru.ru_utime, &ru.ru_stime);
  389                         PROC_STATUNLOCK(p);
  390                         PROC_UNLOCK(p);
  391                         timevaladd(&ru.ru_utime, &ru.ru_stime);
  392                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
  393                         break;
  394                 case LINUX_CPUCLOCK_VIRT:
  395                         PROC_STATLOCK(p);
  396                         calcru(p, &ru.ru_utime, &ru.ru_stime);
  397                         PROC_STATUNLOCK(p);
  398                         PROC_UNLOCK(p);
  399                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
  400                         break;
  401                 case LINUX_CPUCLOCK_SCHED:
  402                         kern_process_cputime(p, tp);
  403                         PROC_UNLOCK(p);
  404                         break;
  405                 default:
  406                         PROC_UNLOCK(p);
  407                         return (EINVAL);
  408                 }
  409 
  410                 break;
  411 
  412         case CLOCK_THREAD_CPUTIME_ID:
  413                 if (which < 0) {
  414                         clockwhich = LINUX_CPUCLOCK_WHICH(which);
  415                         tid = LINUX_CPUCLOCK_ID(which);
  416                 } else {
  417                         clockwhich = LINUX_CPUCLOCK_SCHED;
  418                         tid = 0;
  419                 }
  420                 p = td->td_proc;
  421                 if (tid == 0) {
  422                         targettd = td;
  423                         PROC_LOCK(p);
  424                 } else {
  425                         targettd = linux_tdfind(td, tid, p->p_pid);
  426                         if (targettd == NULL)
  427                                 return (EINVAL);
  428                 }
  429                 switch (clockwhich) {
  430                 case LINUX_CPUCLOCK_PROF:
  431                         PROC_STATLOCK(p);
  432                         thread_lock(targettd);
  433                         rufetchtd(targettd, &ru);
  434                         thread_unlock(targettd);
  435                         PROC_STATUNLOCK(p);
  436                         PROC_UNLOCK(p);
  437                         timevaladd(&ru.ru_utime, &ru.ru_stime);
  438                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
  439                         break;
  440                 case LINUX_CPUCLOCK_VIRT:
  441                         PROC_STATLOCK(p);
  442                         thread_lock(targettd);
  443                         rufetchtd(targettd, &ru);
  444                         thread_unlock(targettd);
  445                         PROC_STATUNLOCK(p);
  446                         PROC_UNLOCK(p);
  447                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
  448                         break;
  449                 case LINUX_CPUCLOCK_SCHED:
  450                         if (td == targettd)
  451                                 targettd = NULL;
  452                         kern_thread_cputime(targettd, tp);
  453                         PROC_UNLOCK(p);
  454                         break;
  455                 default:
  456                         PROC_UNLOCK(p);
  457                         return (EINVAL);
  458                 }
  459                 break;
  460 
  461         default:
  462                 error = kern_clock_gettime(td, nwhich, tp);
  463                 break;
  464         }
  465 
  466         return (error);
  467 }
  468 
  469 int
  470 linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
  471 {
  472         struct timespec tp;
  473         int error;
  474 
  475         error = linux_common_clock_gettime(td, args->which, &tp);
  476         if (error != 0) {
  477                 LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
  478                 return (error);
  479         }
  480         error = linux_put_timespec(&tp, args->tp);
  481         if (error != 0)
  482                 LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
  483 
  484         return (error);
  485 }
  486 
  487 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  488 int
  489 linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args)
  490 {
  491         struct timespec tp;
  492         int error;
  493 
  494         error = linux_common_clock_gettime(td, args->which, &tp);
  495         if (error != 0) {
  496                 LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error);
  497                 return (error);
  498         }
  499         error = linux_put_timespec64(&tp, args->tp);
  500         if (error != 0)
  501                 LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error);
  502 
  503         return (error);
  504 }
  505 #endif
  506 
  507 static int
  508 linux_common_clock_settime(struct thread *td, clockid_t which,
  509     struct timespec *ts)
  510 {
  511         int error;
  512         clockid_t nwhich;
  513 
  514         error = linux_to_native_clockid(&nwhich, which);
  515         if (error != 0) {
  516                 linux_msg(curthread,
  517                     "unsupported clock_settime clockid %d", which);
  518                 LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error,
  519                     error);
  520                 return (error);
  521         }
  522 
  523         error = kern_clock_settime(td, nwhich, ts);
  524         if (error != 0)
  525                 LIN_SDT_PROBE1(time, linux_common_clock_settime,
  526                     settime_error, error);
  527 
  528         return (error);
  529 }
  530 
  531 int
  532 linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
  533 {
  534         struct timespec ts;
  535         int error;
  536 
  537         error = linux_get_timespec(&ts, args->tp);
  538         if (error != 0) {
  539                 LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
  540                 return (error);
  541         }
  542         return (linux_common_clock_settime(td, args->which, &ts));
  543 }
  544 
  545 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  546 int
  547 linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args)
  548 {
  549         struct timespec ts;
  550         int error;
  551 
  552         error = linux_get_timespec64(&ts, args->tp);
  553         if (error != 0) {
  554                 LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error);
  555                 return (error);
  556         }
  557         return (linux_common_clock_settime(td, args->which, &ts));
  558 }
  559 #endif
  560 
  561 static int
  562 linux_common_clock_getres(struct thread *td, clockid_t which,
  563     struct timespec *ts)
  564 {
  565         struct proc *p;
  566         int error, clockwhich;
  567         clockid_t nwhich;
  568         pid_t pid;
  569         lwpid_t tid;
  570 
  571         error = linux_to_native_clockid(&nwhich, which);
  572         if (error != 0) {
  573                 linux_msg(curthread,
  574                     "unsupported clock_getres clockid %d", which);
  575                 LIN_SDT_PROBE1(time, linux_common_clock_getres,
  576                     conversion_error, error);
  577                 return (error);
  578         }
  579 
  580         /*
  581          * Check user supplied clock id in case of per-process
  582          * or thread-specific cpu-time clock.
  583          */
  584         if (which < 0) {
  585                 switch (nwhich) {
  586                 case CLOCK_THREAD_CPUTIME_ID:
  587                         tid = LINUX_CPUCLOCK_ID(which);
  588                         if (tid != 0) {
  589                                 p = td->td_proc;
  590                                 if (linux_tdfind(td, tid, p->p_pid) == NULL)
  591                                         return (EINVAL);
  592                                 PROC_UNLOCK(p);
  593                         }
  594                         break;
  595                 case CLOCK_PROCESS_CPUTIME_ID:
  596                         pid = LINUX_CPUCLOCK_ID(which);
  597                         if (pid != 0) {
  598                                 error = pget(pid, PGET_CANSEE, &p);
  599                                 if (error != 0)
  600                                         return (EINVAL);
  601                                 PROC_UNLOCK(p);
  602                         }
  603                         break;
  604                 }
  605         }
  606 
  607         if (ts == NULL) {
  608                 LIN_SDT_PROBE0(time, linux_common_clock_getres, nullcall);
  609                 return (0);
  610         }
  611 
  612         switch (nwhich) {
  613         case CLOCK_THREAD_CPUTIME_ID:
  614         case CLOCK_PROCESS_CPUTIME_ID:
  615                 clockwhich = LINUX_CPUCLOCK_WHICH(which);
  616                 /*
  617                  * In both cases (when the clock id obtained by a call to
  618                  * clock_getcpuclockid() or using the clock
  619                  * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision
  620                  * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock.
  621                  *
  622                  * See Linux posix_cpu_clock_getres() implementation.
  623                  */
  624                 if (which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) {
  625                         ts->tv_sec = 0;
  626                         ts->tv_nsec = 1;
  627                         goto out;
  628                 }
  629 
  630                 switch (clockwhich) {
  631                 case LINUX_CPUCLOCK_PROF:
  632                         nwhich = CLOCK_PROF;
  633                         break;
  634                 case LINUX_CPUCLOCK_VIRT:
  635                         nwhich = CLOCK_VIRTUAL;
  636                         break;
  637                 default:
  638                         return (EINVAL);
  639                 }
  640                 break;
  641 
  642         default:
  643                 break;
  644         }
  645         error = kern_clock_getres(td, nwhich, ts);
  646         if (error != 0) {
  647                 LIN_SDT_PROBE1(time, linux_common_clock_getres,
  648                     getres_error, error);
  649                 return (error);
  650         }
  651 
  652 out:
  653         return (error);
  654 }
  655 
  656 int
  657 linux_clock_getres(struct thread *td,
  658     struct linux_clock_getres_args *args)
  659 {
  660         struct timespec ts;
  661         int error;
  662 
  663         error = linux_common_clock_getres(td, args->which, &ts);
  664         if (error != 0 || args->tp == NULL)
  665                 return (error);
  666         error = linux_put_timespec(&ts, args->tp);
  667         if (error != 0)
  668                 LIN_SDT_PROBE1(time, linux_clock_getres,
  669                     copyout_error, error);
  670         return (error);
  671 }
  672 
  673 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  674 int
  675 linux_clock_getres_time64(struct thread *td,
  676     struct linux_clock_getres_time64_args *args)
  677 {
  678         struct timespec ts;
  679         int error;
  680 
  681         error = linux_common_clock_getres(td, args->which, &ts);
  682         if (error != 0 || args->tp == NULL)
  683                 return (error);
  684         error = linux_put_timespec64(&ts, args->tp);
  685         if (error != 0)
  686                 LIN_SDT_PROBE1(time, linux_clock_getres_time64,
  687                     copyout_error, error);
  688         return (error);
  689 }
  690 #endif
  691 
  692 int
  693 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
  694 {
  695         struct timespec *rmtp;
  696         struct timespec rqts, rmts;
  697         int error, error2;
  698 
  699         error = linux_get_timespec(&rqts, args->rqtp);
  700         if (error != 0) {
  701                 LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
  702                 return (error);
  703         }
  704         if (args->rmtp != NULL)
  705                 rmtp = &rmts;
  706         else
  707                 rmtp = NULL;
  708 
  709         error = kern_nanosleep(td, &rqts, rmtp);
  710         if (error == EINTR && args->rmtp != NULL) {
  711                 error2 = linux_put_timespec(rmtp, args->rmtp);
  712                 if (error2 != 0) {
  713                         LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
  714                             error2);
  715                         return (error2);
  716                 }
  717         }
  718 
  719         return (error);
  720 }
  721 
  722 static int
  723 linux_common_clock_nanosleep(struct thread *td, clockid_t which,
  724     l_int lflags, struct timespec *rqtp, struct timespec *rmtp)
  725 {
  726         int error, flags;
  727         clockid_t clockid;
  728 
  729         error = linux_to_native_timerflags(&flags, lflags);
  730         if (error != 0) {
  731                 LIN_SDT_PROBE1(time, linux_common_clock_nanosleep,
  732                     unsupported_flags, lflags);
  733                 return (error);
  734         }
  735 
  736         error = linux_to_native_clockid(&clockid, which);
  737         if (error != 0) {
  738                 linux_msg(curthread,
  739                     "unsupported clock_nanosleep clockid %d", which);
  740                 LIN_SDT_PROBE1(time, linux_common_clock_nanosleep,
  741                     unsupported_clockid, which);
  742                 return (error);
  743         }
  744         if (clockid == CLOCK_THREAD_CPUTIME_ID)
  745                 return (ENOTSUP);
  746 
  747         return (kern_clock_nanosleep(td, clockid, flags, rqtp, rmtp));
  748 }
  749 
  750 int
  751 linux_clock_nanosleep(struct thread *td,
  752     struct linux_clock_nanosleep_args *args)
  753 {
  754         struct timespec *rmtp;
  755         struct timespec rqts, rmts;
  756         int error, error2;
  757 
  758         error = linux_get_timespec(&rqts, args->rqtp);
  759         if (error != 0) {
  760                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
  761                     error);
  762                 return (error);
  763         }
  764         if (args->rmtp != NULL)
  765                 rmtp = &rmts;
  766         else
  767                 rmtp = NULL;
  768 
  769         error = linux_common_clock_nanosleep(td, args->which, args->flags,
  770             &rqts, rmtp);
  771         if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
  772             args->rmtp != NULL) {
  773                 error2 = linux_put_timespec(rmtp, args->rmtp);
  774                 if (error2 != 0) {
  775                         LIN_SDT_PROBE1(time, linux_clock_nanosleep,
  776                             copyout_error, error2);
  777                         return (error2);
  778                 }
  779         }
  780         return (error);
  781 }
  782 
  783 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
  784 int
  785 linux_clock_nanosleep_time64(struct thread *td,
  786     struct linux_clock_nanosleep_time64_args *args)
  787 {
  788         struct timespec *rmtp;
  789         struct timespec rqts, rmts;
  790         int error, error2;
  791 
  792         error = linux_get_timespec64(&rqts, args->rqtp);
  793         if (error != 0) {
  794                 LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
  795                     copyin_error, error);
  796                 return (error);
  797         }
  798         if (args->rmtp != NULL)
  799                 rmtp = &rmts;
  800         else
  801                 rmtp = NULL;
  802 
  803         error = linux_common_clock_nanosleep(td, args->which, args->flags,
  804             &rqts, rmtp);
  805         if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
  806             args->rmtp != NULL) {
  807                 error2 = linux_put_timespec64(rmtp, args->rmtp);
  808                 if (error2 != 0) {
  809                         LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
  810                             copyout_error, error2);
  811                         return (error2);
  812                 }
  813         }
  814         return (error);
  815 }
  816 #endif

Cache object: d826bc56f6866f32a9e530cfa38b7d3a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.