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  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Emmanuel Dreyfus.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/11.0/sys/compat/linux/linux_time.c 283498 2015-05-24 18:14:38Z dchagin $");
   34 #if 0
   35 __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $");
   36 #endif
   37 
   38 #include "opt_compat.h"
   39 
   40 #include <sys/param.h>
   41 #include <sys/kernel.h>
   42 #include <sys/lock.h>
   43 #include <sys/ucred.h>
   44 #include <sys/mount.h>
   45 #include <sys/mutex.h>
   46 #include <sys/resourcevar.h>
   47 #include <sys/sdt.h>
   48 #include <sys/signal.h>
   49 #include <sys/stdint.h>
   50 #include <sys/syscallsubr.h>
   51 #include <sys/sysproto.h>
   52 #include <sys/time.h>
   53 #include <sys/systm.h>
   54 #include <sys/proc.h>
   55 
   56 #ifdef COMPAT_LINUX32
   57 #include <machine/../linux32/linux.h>
   58 #include <machine/../linux32/linux32_proto.h>
   59 #else
   60 #include <machine/../linux/linux.h>
   61 #include <machine/../linux/linux_proto.h>
   62 #endif
   63 
   64 #include <compat/linux/linux_dtrace.h>
   65 #include <compat/linux/linux_timer.h>
   66 
   67 /* DTrace init */
   68 LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
   69 
   70 /**
   71  * DTrace probes in this module.
   72  */
   73 LIN_SDT_PROBE_DEFINE2(time, native_to_linux_timespec, entry,
   74     "struct l_timespec *", "struct timespec *");
   75 LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return);
   76 LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry,
   77     "struct timespec *", "struct l_timespec *");
   78 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int");
   79 LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *",
   80     "clockid_t");
   81 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
   82     "clockid_t");
   83 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
   84     "clockid_t");
   85 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int");
   86 LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t",
   87     "struct l_timespec *");
   88 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int");
   89 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
   90 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
   91 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int");
   92 LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t",
   93     "struct l_timespec *");
   94 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
   95 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int");
   96 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
   97 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int");
   98 LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t",
   99     "struct l_timespec *");
  100 LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall);
  101 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int");
  102 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int");
  103 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
  104 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int");
  105 LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *",
  106     "struct l_timespec *");
  107 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
  108 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
  109 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
  110 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int");
  111 LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int",
  112     "struct l_timespec *", "struct l_timespec *");
  113 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
  114 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
  115 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
  116 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int");
  117 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
  118 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int");
  119 
  120 
  121 void
  122 native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
  123 {
  124 
  125         LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp);
  126 
  127         ltp->tv_sec = ntp->tv_sec;
  128         ltp->tv_nsec = ntp->tv_nsec;
  129 
  130         LIN_SDT_PROBE0(time, native_to_linux_timespec, return);
  131 }
  132 
  133 int
  134 linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
  135 {
  136 
  137         LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp);
  138 
  139         if (ltp->tv_sec < 0 || ltp->tv_nsec > (l_long)999999999L) {
  140                 LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL);
  141                 return (EINVAL);
  142         }
  143         ntp->tv_sec = ltp->tv_sec;
  144         ntp->tv_nsec = ltp->tv_nsec;
  145 
  146         LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0);
  147         return (0);
  148 }
  149 
  150 int
  151 linux_to_native_clockid(clockid_t *n, clockid_t l)
  152 {
  153 
  154         LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l);
  155 
  156         if (l < 0) {
  157                 /* cpu-clock */
  158                 if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
  159                         return (EINVAL);
  160                 if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
  161                         return (EINVAL);
  162 
  163                 if (LINUX_CPUCLOCK_PERTHREAD(l))
  164                         *n = CLOCK_THREAD_CPUTIME_ID;
  165                 else
  166                         *n = CLOCK_PROCESS_CPUTIME_ID;
  167                 return (0);
  168         }
  169 
  170         switch (l) {
  171         case LINUX_CLOCK_REALTIME:
  172                 *n = CLOCK_REALTIME;
  173                 break;
  174         case LINUX_CLOCK_MONOTONIC:
  175                 *n = CLOCK_MONOTONIC;
  176                 break;
  177         case LINUX_CLOCK_REALTIME_COARSE:
  178                 *n = CLOCK_REALTIME_FAST;
  179                 break;
  180         case LINUX_CLOCK_MONOTONIC_COARSE:
  181                 *n = CLOCK_MONOTONIC_FAST;
  182                 break;
  183         case LINUX_CLOCK_MONOTONIC_RAW:
  184         case LINUX_CLOCK_BOOTTIME:
  185         case LINUX_CLOCK_REALTIME_ALARM:
  186         case LINUX_CLOCK_BOOTTIME_ALARM:
  187         case LINUX_CLOCK_SGI_CYCLE:
  188         case LINUX_CLOCK_TAI:
  189                 LIN_SDT_PROBE1(time, linux_to_native_clockid,
  190                     unsupported_clockid, l);
  191                 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
  192                 return (EINVAL);
  193         default:
  194                 LIN_SDT_PROBE1(time, linux_to_native_clockid,
  195                     unknown_clockid, l);
  196                 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
  197                 return (EINVAL);
  198         }
  199 
  200         LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0);
  201         return (0);
  202 }
  203 
  204 int
  205 linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
  206 {
  207         struct l_timespec lts;
  208         struct timespec tp;
  209         struct rusage ru;
  210         struct thread *targettd;
  211         struct proc *p;
  212         int error, clockwhich;
  213         clockid_t nwhich = 0;   /* XXX: GCC */
  214         pid_t pid;
  215         lwpid_t tid;
  216 
  217         LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp);
  218 
  219         error = linux_to_native_clockid(&nwhich, args->which);
  220         if (error != 0) {
  221                 LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error,
  222                     error);
  223                 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
  224                 return (error);
  225         }
  226 
  227         switch (nwhich) {
  228         case CLOCK_PROCESS_CPUTIME_ID:
  229                 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
  230                 pid = LINUX_CPUCLOCK_ID(args->which);
  231                 if (pid == 0) {
  232                         p = td->td_proc;
  233                         PROC_LOCK(p);
  234                 } else {
  235                         error = pget(pid, PGET_CANSEE, &p);
  236                         if (error != 0)
  237                                 return (EINVAL);
  238                 }
  239                 switch (clockwhich) {
  240                 case LINUX_CPUCLOCK_PROF:
  241                         PROC_STATLOCK(p);
  242                         calcru(p, &ru.ru_utime, &ru.ru_stime);
  243                         PROC_STATUNLOCK(p);
  244                         PROC_UNLOCK(p);
  245                         timevaladd(&ru.ru_utime, &ru.ru_stime);
  246                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
  247                         break;
  248                 case LINUX_CPUCLOCK_VIRT:
  249                         PROC_STATLOCK(p);
  250                         calcru(p, &ru.ru_utime, &ru.ru_stime);
  251                         PROC_STATUNLOCK(p);
  252                         PROC_UNLOCK(p);
  253                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
  254                         break;
  255                 case LINUX_CPUCLOCK_SCHED:
  256                         PROC_UNLOCK(p);
  257                         error = kern_clock_getcpuclockid2(td, pid,
  258                             CPUCLOCK_WHICH_PID, &nwhich);
  259                         if (error != 0)
  260                                 return (EINVAL);
  261                         error = kern_clock_gettime(td, nwhich, &tp);
  262                         break;
  263                 default:
  264                         PROC_UNLOCK(p);
  265                         return (EINVAL);
  266                 }
  267 
  268                 break;
  269 
  270         case CLOCK_THREAD_CPUTIME_ID:
  271                 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
  272                 p = td->td_proc;
  273                 tid = LINUX_CPUCLOCK_ID(args->which);
  274                 if (tid == 0) {
  275                         targettd = td;
  276                         PROC_LOCK(p);
  277                 } else {
  278                         targettd = tdfind(tid, p->p_pid);
  279                         if (targettd == NULL)
  280                                 return (EINVAL);
  281                 }
  282                 switch (clockwhich) {
  283                 case LINUX_CPUCLOCK_PROF:
  284                         PROC_STATLOCK(p);
  285                         thread_lock(targettd);
  286                         rufetchtd(targettd, &ru);
  287                         thread_unlock(targettd);
  288                         PROC_STATUNLOCK(p);
  289                         PROC_UNLOCK(p);
  290                         timevaladd(&ru.ru_utime, &ru.ru_stime);
  291                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
  292                         break;
  293                 case LINUX_CPUCLOCK_VIRT:
  294                         PROC_STATLOCK(p);
  295                         thread_lock(targettd);
  296                         rufetchtd(targettd, &ru);
  297                         thread_unlock(targettd);
  298                         PROC_STATUNLOCK(p);
  299                         PROC_UNLOCK(p);
  300                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
  301                         break;
  302                 case LINUX_CPUCLOCK_SCHED:
  303                         error = kern_clock_getcpuclockid2(td, tid,
  304                             CPUCLOCK_WHICH_TID, &nwhich);
  305                         PROC_UNLOCK(p);
  306                         if (error != 0)
  307                                 return (EINVAL);
  308                         error = kern_clock_gettime(td, nwhich, &tp);
  309                         break;
  310                 default:
  311                         PROC_UNLOCK(p);
  312                         return (EINVAL);
  313                 }
  314                 break;
  315 
  316         default:
  317                 error = kern_clock_gettime(td, nwhich, &tp);
  318                 break;
  319         }
  320         if (error != 0) {
  321                 LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
  322                 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
  323                 return (error);
  324         }
  325         native_to_linux_timespec(&lts, &tp);
  326 
  327         error = copyout(&lts, args->tp, sizeof lts);
  328         if (error != 0)
  329                 LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
  330 
  331         LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
  332         return (error);
  333 }
  334 
  335 int
  336 linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
  337 {
  338         struct timespec ts;
  339         struct l_timespec lts;
  340         int error;
  341         clockid_t nwhich = 0;   /* XXX: GCC */
  342 
  343         LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp);
  344 
  345         error = linux_to_native_clockid(&nwhich, args->which);
  346         if (error != 0) {
  347                 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
  348                     error);
  349                 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
  350                 return (error);
  351         }
  352         error = copyin(args->tp, &lts, sizeof lts);
  353         if (error != 0) {
  354                 LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
  355                 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
  356                 return (error);
  357         }
  358         error = linux_to_native_timespec(&ts, &lts);
  359         if (error != 0) {
  360                 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
  361                     error);
  362                 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
  363                 return (error);
  364         }
  365 
  366         error = kern_clock_settime(td, nwhich, &ts);
  367         if (error != 0)
  368                 LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error);
  369 
  370         LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
  371         return (error);
  372 }
  373 
  374 int
  375 linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
  376 {
  377         struct proc *p;
  378         struct timespec ts;
  379         struct l_timespec lts;
  380         int error, clockwhich;
  381         clockid_t nwhich = 0;   /* XXX: GCC */
  382         pid_t pid;
  383         lwpid_t tid;
  384 
  385         LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp);
  386 
  387         error = linux_to_native_clockid(&nwhich, args->which);
  388         if (error != 0) {
  389                 LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error,
  390                     error);
  391                 LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
  392                 return (error);
  393         }
  394 
  395         /*
  396          * Check user supplied clock id in case of per-process 
  397          * or thread-specific cpu-time clock.
  398          */
  399         switch (nwhich) {
  400         case CLOCK_THREAD_CPUTIME_ID:
  401                 tid = LINUX_CPUCLOCK_ID(args->which);
  402                 if (tid != 0) {
  403                         p = td->td_proc;
  404                         if (tdfind(tid, p->p_pid) == NULL)
  405                                 return (ESRCH);
  406                         PROC_UNLOCK(p);
  407                 }
  408                 break;
  409         case CLOCK_PROCESS_CPUTIME_ID:
  410                 pid = LINUX_CPUCLOCK_ID(args->which);
  411                 if (pid != 0) {
  412                         error = pget(pid, PGET_CANSEE, &p);
  413                         if (error != 0)
  414                                 return (EINVAL);
  415                         PROC_UNLOCK(p);
  416                 }
  417                 break;
  418         }
  419 
  420         if (args->tp == NULL) {
  421                 LIN_SDT_PROBE0(time, linux_clock_getres, nullcall);
  422                 LIN_SDT_PROBE1(time, linux_clock_getres, return, 0);
  423                 return (0);
  424         }
  425 
  426         switch (nwhich) {
  427         case CLOCK_THREAD_CPUTIME_ID:
  428         case CLOCK_PROCESS_CPUTIME_ID:
  429                 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
  430                 switch (clockwhich) {
  431                 case LINUX_CPUCLOCK_PROF:
  432                         nwhich = CLOCK_PROF;
  433                         break;
  434                 case LINUX_CPUCLOCK_VIRT:
  435                         nwhich = CLOCK_VIRTUAL;
  436                         break;
  437                 case LINUX_CPUCLOCK_SCHED:
  438                         break;
  439                 default:
  440                         return (EINVAL);
  441                 }
  442                 break;
  443 
  444         default:
  445                 break;
  446         }
  447         error = kern_clock_getres(td, nwhich, &ts);
  448         if (error != 0) {
  449                 LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error);
  450                 LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
  451                 return (error);
  452         }
  453         native_to_linux_timespec(&lts, &ts);
  454 
  455         error = copyout(&lts, args->tp, sizeof lts);
  456         if (error != 0)
  457                 LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
  458 
  459         LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
  460         return (error);
  461 }
  462 
  463 int
  464 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
  465 {
  466         struct timespec *rmtp;
  467         struct l_timespec lrqts, lrmts;
  468         struct timespec rqts, rmts;
  469         int error, error2;
  470 
  471         LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp);
  472 
  473         error = copyin(args->rqtp, &lrqts, sizeof lrqts);
  474         if (error != 0) {
  475                 LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
  476                 LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
  477                 return (error);
  478         }
  479 
  480         if (args->rmtp != NULL)
  481                 rmtp = &rmts;
  482         else
  483                 rmtp = NULL;
  484 
  485         error = linux_to_native_timespec(&rqts, &lrqts);
  486         if (error != 0) {
  487                 LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
  488                 LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
  489                 return (error);
  490         }
  491         error = kern_nanosleep(td, &rqts, rmtp);
  492         if (args->rmtp != NULL) {
  493                 native_to_linux_timespec(&lrmts, rmtp);
  494                 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
  495                 if (error2 != 0) {
  496                         LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
  497                             error2);
  498                         LIN_SDT_PROBE1(time, linux_nanosleep, return, error2);
  499                         return (error2);
  500                 }
  501         }
  502 
  503         LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
  504         return (error);
  505 }
  506 
  507 int
  508 linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args)
  509 {
  510         struct timespec *rmtp;
  511         struct l_timespec lrqts, lrmts;
  512         struct timespec rqts, rmts;
  513         int error, error2;
  514 
  515         LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which,
  516             args->flags, args->rqtp, args->rmtp);
  517 
  518         if (args->flags != 0) {
  519                 /* XXX deal with TIMER_ABSTIME */
  520                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags,
  521                     args->flags);
  522                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL);
  523                 return (EINVAL);        /* XXX deal with TIMER_ABSTIME */
  524         }
  525 
  526         if (args->which != LINUX_CLOCK_REALTIME) {
  527                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid,
  528                     args->which);
  529                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL);
  530                 return (EINVAL);
  531         }
  532 
  533         error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
  534         if (error != 0) {
  535                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
  536                     error);
  537                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
  538                 return (error);
  539         }
  540 
  541         if (args->rmtp != NULL)
  542                 rmtp = &rmts;
  543         else
  544                 rmtp = NULL;
  545 
  546         error = linux_to_native_timespec(&rqts, &lrqts);
  547         if (error != 0) {
  548                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
  549                     error);
  550                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
  551                 return (error);
  552         }
  553         error = kern_nanosleep(td, &rqts, rmtp);
  554         if (args->rmtp != NULL) {
  555                 /* XXX. Not for TIMER_ABSTIME */
  556                 native_to_linux_timespec(&lrmts, rmtp);
  557                 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
  558                 if (error2 != 0) {
  559                         LIN_SDT_PROBE1(time, linux_clock_nanosleep,
  560                             copyout_error, error2);
  561                         LIN_SDT_PROBE1(time, linux_clock_nanosleep,
  562                             return, error2);
  563                         return (error2);
  564                 }
  565         }
  566 
  567         LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
  568         return (error);
  569 }

Cache object: a8cdeb2d81ab55008dba699dbce3da7b


[ 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.