]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/compat/linux/linux_time.c
zfs: merge openzfs/zfs@afa7b3484 (master) into main
[FreeBSD/FreeBSD.git] / sys / compat / linux / linux_time.c
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, conversion_error, "int");
105 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
106 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
107 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
108 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
109 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
110 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int");
111 LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int");
112 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
113 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, conversion_error, "int");
114 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int");
115 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int");
116 #endif
117
118 static int      linux_common_clock_gettime(struct thread *, clockid_t,
119                     struct timespec *);
120 static int      linux_common_clock_settime(struct thread *, clockid_t,
121                     struct timespec *);
122 static int      linux_common_clock_getres(struct thread *, clockid_t,
123                     struct timespec *);
124 static int      linux_common_clock_nanosleep(struct thread *, clockid_t,
125                     l_int, struct timespec *, struct timespec *);
126
127 int
128 native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
129 {
130
131 #ifdef COMPAT_LINUX32
132         if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN)
133                 return (EOVERFLOW);
134 #endif
135         ltp->tv_sec = ntp->tv_sec;
136         ltp->tv_nsec = ntp->tv_nsec;
137
138         return (0);
139 }
140
141 int
142 linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
143 {
144
145         if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999)
146                 return (EINVAL);
147         ntp->tv_sec = ltp->tv_sec;
148         ntp->tv_nsec = ltp->tv_nsec;
149
150         return (0);
151 }
152
153 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
154 int
155 native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
156 {
157
158         ltp64->tv_sec = ntp->tv_sec;
159         ltp64->tv_nsec = ntp->tv_nsec;
160
161         return (0);
162 }
163
164 int
165 linux_to_native_timespec64(struct timespec *ntp, struct l_timespec64 *ltp64)
166 {
167
168         if (ltp64->tv_sec < 0 || ltp64->tv_nsec < 0 || ltp64->tv_nsec > 999999999)
169                 return (EINVAL);
170         ntp->tv_sec = ltp64->tv_sec;
171         ntp->tv_nsec = ltp64->tv_nsec;
172
173         return (0);
174 }
175 #endif
176
177 int
178 native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
179 {
180         int error;
181
182         error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
183         if (error == 0)
184                 error = native_to_linux_timespec(&ltp->it_value, &ntp->it_interval);
185         return (error);
186 }
187
188 int
189 linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
190 {
191         int error;
192
193         error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
194         if (error == 0)
195                 error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
196         return (error);
197 }
198
199 int
200 linux_to_native_clockid(clockid_t *n, clockid_t l)
201 {
202
203         if (l < 0) {
204                 /* cpu-clock */
205                 if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
206                         return (EINVAL);
207                 if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
208                         return (EINVAL);
209
210                 if (LINUX_CPUCLOCK_PERTHREAD(l))
211                         *n = CLOCK_THREAD_CPUTIME_ID;
212                 else
213                         *n = CLOCK_PROCESS_CPUTIME_ID;
214                 return (0);
215         }
216
217         switch (l) {
218         case LINUX_CLOCK_REALTIME:
219                 *n = CLOCK_REALTIME;
220                 break;
221         case LINUX_CLOCK_MONOTONIC:
222                 *n = CLOCK_MONOTONIC;
223                 break;
224         case LINUX_CLOCK_PROCESS_CPUTIME_ID:
225                 *n = CLOCK_PROCESS_CPUTIME_ID;
226                 break;
227         case LINUX_CLOCK_THREAD_CPUTIME_ID:
228                 *n = CLOCK_THREAD_CPUTIME_ID;
229                 break;
230         case LINUX_CLOCK_REALTIME_COARSE:
231                 *n = CLOCK_REALTIME_FAST;
232                 break;
233         case LINUX_CLOCK_MONOTONIC_COARSE:
234         case LINUX_CLOCK_MONOTONIC_RAW:
235                 *n = CLOCK_MONOTONIC_FAST;
236                 break;
237         case LINUX_CLOCK_BOOTTIME:
238                 *n = CLOCK_UPTIME;
239                 break;
240         case LINUX_CLOCK_REALTIME_ALARM:
241         case LINUX_CLOCK_BOOTTIME_ALARM:
242         case LINUX_CLOCK_SGI_CYCLE:
243         case LINUX_CLOCK_TAI:
244                 LIN_SDT_PROBE1(time, linux_to_native_clockid,
245                     unsupported_clockid, l);
246                 return (EINVAL);
247         default:
248                 LIN_SDT_PROBE1(time, linux_to_native_clockid,
249                     unknown_clockid, l);
250                 return (EINVAL);
251         }
252
253         return (0);
254 }
255
256 int
257 linux_to_native_timerflags(int *nflags, int flags)
258 {
259
260         if (flags & ~LINUX_TIMER_ABSTIME)
261                 return (EINVAL);
262         *nflags = 0;
263         if (flags & LINUX_TIMER_ABSTIME)
264                 *nflags |= TIMER_ABSTIME;
265         return (0);
266 }
267
268 static int
269 linux_common_clock_gettime(struct thread *td, clockid_t which,
270     struct timespec *tp)
271 {
272         struct rusage ru;
273         struct thread *targettd;
274         struct proc *p;
275         int error, clockwhich;
276         clockid_t nwhich;
277         pid_t pid;
278         lwpid_t tid;
279
280         error = linux_to_native_clockid(&nwhich, which);
281         if (error != 0) {
282                 linux_msg(curthread,
283                     "unsupported clock_gettime clockid %d", which);
284                 LIN_SDT_PROBE1(time, linux_common_clock_gettime,
285                     conversion_error, error);
286                 return (error);
287         }
288
289         switch (nwhich) {
290         case CLOCK_PROCESS_CPUTIME_ID:
291                 if (which < 0) {
292                         clockwhich = LINUX_CPUCLOCK_WHICH(which);
293                         pid = LINUX_CPUCLOCK_ID(which);
294                 } else {
295                         clockwhich = LINUX_CPUCLOCK_SCHED;
296                         pid = 0;
297                 }
298                 if (pid == 0) {
299                         p = td->td_proc;
300                         PROC_LOCK(p);
301                 } else {
302                         error = pget(pid, PGET_CANSEE, &p);
303                         if (error != 0)
304                                 return (EINVAL);
305                 }
306                 switch (clockwhich) {
307                 case LINUX_CPUCLOCK_PROF:
308                         PROC_STATLOCK(p);
309                         calcru(p, &ru.ru_utime, &ru.ru_stime);
310                         PROC_STATUNLOCK(p);
311                         PROC_UNLOCK(p);
312                         timevaladd(&ru.ru_utime, &ru.ru_stime);
313                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
314                         break;
315                 case LINUX_CPUCLOCK_VIRT:
316                         PROC_STATLOCK(p);
317                         calcru(p, &ru.ru_utime, &ru.ru_stime);
318                         PROC_STATUNLOCK(p);
319                         PROC_UNLOCK(p);
320                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
321                         break;
322                 case LINUX_CPUCLOCK_SCHED:
323                         kern_process_cputime(p, tp);
324                         PROC_UNLOCK(p);
325                         break;
326                 default:
327                         PROC_UNLOCK(p);
328                         return (EINVAL);
329                 }
330
331                 break;
332
333         case CLOCK_THREAD_CPUTIME_ID:
334                 if (which < 0) {
335                         clockwhich = LINUX_CPUCLOCK_WHICH(which);
336                         tid = LINUX_CPUCLOCK_ID(which);
337                 } else {
338                         clockwhich = LINUX_CPUCLOCK_SCHED;
339                         tid = 0;
340                 }
341                 p = td->td_proc;
342                 if (tid == 0) {
343                         targettd = td;
344                         PROC_LOCK(p);
345                 } else {
346                         targettd = linux_tdfind(td, tid, p->p_pid);
347                         if (targettd == NULL)
348                                 return (EINVAL);
349                 }
350                 switch (clockwhich) {
351                 case LINUX_CPUCLOCK_PROF:
352                         PROC_STATLOCK(p);
353                         thread_lock(targettd);
354                         rufetchtd(targettd, &ru);
355                         thread_unlock(targettd);
356                         PROC_STATUNLOCK(p);
357                         PROC_UNLOCK(p);
358                         timevaladd(&ru.ru_utime, &ru.ru_stime);
359                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
360                         break;
361                 case LINUX_CPUCLOCK_VIRT:
362                         PROC_STATLOCK(p);
363                         thread_lock(targettd);
364                         rufetchtd(targettd, &ru);
365                         thread_unlock(targettd);
366                         PROC_STATUNLOCK(p);
367                         PROC_UNLOCK(p);
368                         TIMEVAL_TO_TIMESPEC(&ru.ru_utime, tp);
369                         break;
370                 case LINUX_CPUCLOCK_SCHED:
371                         if (td == targettd)
372                                 targettd = NULL;
373                         kern_thread_cputime(targettd, tp);
374                         PROC_UNLOCK(p);
375                         break;
376                 default:
377                         PROC_UNLOCK(p);
378                         return (EINVAL);
379                 }
380                 break;
381
382         default:
383                 error = kern_clock_gettime(td, nwhich, tp);
384                 break;
385         }
386
387         return (error);
388 }
389
390 int
391 linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
392 {
393         struct l_timespec lts;
394         struct timespec tp;
395         int error;
396
397         error = linux_common_clock_gettime(td, args->which, &tp);
398         if (error != 0) {
399                 LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
400                 return (error);
401         }
402         error = native_to_linux_timespec(&lts, &tp);
403         if (error != 0)
404                 return (error);
405         error = copyout(&lts, args->tp, sizeof(lts));
406         if (error != 0)
407                 LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
408
409         return (error);
410 }
411
412 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
413 int
414 linux_clock_gettime64(struct thread *td, struct linux_clock_gettime64_args *args)
415 {
416         struct l_timespec64 lts;
417         struct timespec tp;
418         int error;
419
420         error = linux_common_clock_gettime(td, args->which, &tp);
421         if (error != 0) {
422                 LIN_SDT_PROBE1(time, linux_clock_gettime64, gettime_error, error);
423                 return (error);
424         }
425         error = native_to_linux_timespec64(&lts, &tp);
426         if (error != 0)
427                 return (error);
428         error = copyout(&lts, args->tp, sizeof(lts));
429         if (error != 0)
430                 LIN_SDT_PROBE1(time, linux_clock_gettime64, copyout_error, error);
431
432         return (error);
433 }
434 #endif
435
436 static int
437 linux_common_clock_settime(struct thread *td, clockid_t which,
438     struct timespec *ts)
439 {
440         int error;
441         clockid_t nwhich;
442
443         error = linux_to_native_clockid(&nwhich, which);
444         if (error != 0) {
445                 linux_msg(curthread,
446                     "unsupported clock_settime clockid %d", which);
447                 LIN_SDT_PROBE1(time, linux_common_clock_settime, conversion_error,
448                     error);
449                 return (error);
450         }
451
452         error = kern_clock_settime(td, nwhich, ts);
453         if (error != 0)
454                 LIN_SDT_PROBE1(time, linux_common_clock_settime,
455                     settime_error, error);
456
457         return (error);
458 }
459
460 int
461 linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
462 {
463         struct timespec ts;
464         struct l_timespec lts;
465         int error;
466
467         error = copyin(args->tp, &lts, sizeof(lts));
468         if (error != 0) {
469                 LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
470                 return (error);
471         }
472         error = linux_to_native_timespec(&ts, &lts);
473         if (error != 0)
474                 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
475                     error);
476
477         return (linux_common_clock_settime(td, args->which, &ts));
478 }
479
480 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
481 int
482 linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args)
483 {
484         struct timespec ts;
485         struct l_timespec64 lts;
486         int error;
487
488         error = copyin(args->tp, &lts, sizeof(lts));
489         if (error != 0) {
490                 LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error);
491                 return (error);
492         }
493         error = linux_to_native_timespec64(&ts, &lts);
494         if (error != 0)
495                 LIN_SDT_PROBE1(time, linux_clock_settime64, conversion_error,
496                     error);
497         return (linux_common_clock_settime(td, args->which, &ts));
498 }
499 #endif
500
501 static int
502 linux_common_clock_getres(struct thread *td, clockid_t which,
503     struct timespec *ts)
504 {
505         struct proc *p;
506         int error, clockwhich;
507         clockid_t nwhich;
508         pid_t pid;
509         lwpid_t tid;
510
511         error = linux_to_native_clockid(&nwhich, which);
512         if (error != 0) {
513                 linux_msg(curthread,
514                     "unsupported clock_getres clockid %d", which);
515                 LIN_SDT_PROBE1(time, linux_common_clock_getres,
516                     conversion_error, error);
517                 return (error);
518         }
519
520         /*
521          * Check user supplied clock id in case of per-process
522          * or thread-specific cpu-time clock.
523          */
524         if (which < 0) {
525                 switch (nwhich) {
526                 case CLOCK_THREAD_CPUTIME_ID:
527                         tid = LINUX_CPUCLOCK_ID(which);
528                         if (tid != 0) {
529                                 p = td->td_proc;
530                                 if (linux_tdfind(td, tid, p->p_pid) == NULL)
531                                         return (EINVAL);
532                                 PROC_UNLOCK(p);
533                         }
534                         break;
535                 case CLOCK_PROCESS_CPUTIME_ID:
536                         pid = LINUX_CPUCLOCK_ID(which);
537                         if (pid != 0) {
538                                 error = pget(pid, PGET_CANSEE, &p);
539                                 if (error != 0)
540                                         return (EINVAL);
541                                 PROC_UNLOCK(p);
542                         }
543                         break;
544                 }
545         }
546
547         if (ts == NULL) {
548                 LIN_SDT_PROBE0(time, linux_common_clock_getres, nullcall);
549                 return (0);
550         }
551
552         switch (nwhich) {
553         case CLOCK_THREAD_CPUTIME_ID:
554         case CLOCK_PROCESS_CPUTIME_ID:
555                 clockwhich = LINUX_CPUCLOCK_WHICH(which);
556                 /*
557                  * In both cases (when the clock id obtained by a call to
558                  * clock_getcpuclockid() or using the clock
559                  * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision
560                  * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock.
561                  *
562                  * See Linux posix_cpu_clock_getres() implementation.
563                  */
564                 if (which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) {
565                         ts->tv_sec = 0;
566                         ts->tv_nsec = 1;
567                         goto out;
568                 }
569
570                 switch (clockwhich) {
571                 case LINUX_CPUCLOCK_PROF:
572                         nwhich = CLOCK_PROF;
573                         break;
574                 case LINUX_CPUCLOCK_VIRT:
575                         nwhich = CLOCK_VIRTUAL;
576                         break;
577                 default:
578                         return (EINVAL);
579                 }
580                 break;
581
582         default:
583                 break;
584         }
585         error = kern_clock_getres(td, nwhich, ts);
586         if (error != 0) {
587                 LIN_SDT_PROBE1(time, linux_common_clock_getres,
588                     getres_error, error);
589                 return (error);
590         }
591
592 out:
593         return (error);
594 }
595
596 int
597 linux_clock_getres(struct thread *td,
598     struct linux_clock_getres_args *args)
599 {
600         struct timespec ts;
601         struct l_timespec lts;
602         int error;
603
604         error = linux_common_clock_getres(td, args->which, &ts);
605         if (error != 0 || args->tp == NULL)
606                 return (error);
607
608         error = native_to_linux_timespec(&lts, &ts);
609         if (error != 0)
610                 return (error);
611         error = copyout(&lts, args->tp, sizeof(lts));
612         if (error != 0)
613                 LIN_SDT_PROBE1(time, linux_clock_getres,
614                     copyout_error, error);
615         return (error);
616 }
617
618 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
619 int
620 linux_clock_getres_time64(struct thread *td,
621     struct linux_clock_getres_time64_args *args)
622 {
623         struct timespec ts;
624         struct l_timespec64 lts;
625         int error;
626
627         error = linux_common_clock_getres(td, args->which, &ts);
628         if (error != 0 || args->tp == NULL)
629                 return (error);
630
631         error = native_to_linux_timespec64(&lts, &ts);
632         if (error != 0)
633                 return (error);
634         error = copyout(&lts, args->tp, sizeof(lts));
635         if (error != 0)
636                 LIN_SDT_PROBE1(time, linux_clock_getres_time64,
637                     copyout_error, error);
638         return (error);
639 }
640 #endif
641
642 int
643 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
644 {
645         struct timespec *rmtp;
646         struct l_timespec lrqts, lrmts;
647         struct timespec rqts, rmts;
648         int error, error2;
649
650         error = copyin(args->rqtp, &lrqts, sizeof lrqts);
651         if (error != 0) {
652                 LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
653                 return (error);
654         }
655
656         if (args->rmtp != NULL)
657                 rmtp = &rmts;
658         else
659                 rmtp = NULL;
660
661         error = linux_to_native_timespec(&rqts, &lrqts);
662         if (error != 0) {
663                 LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
664                 return (error);
665         }
666         error = kern_nanosleep(td, &rqts, rmtp);
667         if (error == EINTR && args->rmtp != NULL) {
668                 error2 = native_to_linux_timespec(&lrmts, rmtp);
669                 if (error2 != 0)
670                         return (error2);
671                 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
672                 if (error2 != 0) {
673                         LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
674                             error2);
675                         return (error2);
676                 }
677         }
678
679         return (error);
680 }
681
682 static int
683 linux_common_clock_nanosleep(struct thread *td, clockid_t which,
684     l_int lflags, struct timespec *rqtp, struct timespec *rmtp)
685 {
686         int error, flags;
687         clockid_t clockid;
688
689         error = linux_to_native_timerflags(&flags, lflags);
690         if (error != 0) {
691                 LIN_SDT_PROBE1(time, linux_common_clock_nanosleep,
692                     unsupported_flags, lflags);
693                 return (error);
694         }
695
696         error = linux_to_native_clockid(&clockid, which);
697         if (error != 0) {
698                 linux_msg(curthread,
699                     "unsupported clock_nanosleep clockid %d", which);
700                 LIN_SDT_PROBE1(time, linux_common_clock_nanosleep,
701                     unsupported_clockid, which);
702                 return (error);
703         }
704         if (clockid == CLOCK_THREAD_CPUTIME_ID)
705                 return (ENOTSUP);
706
707         return (kern_clock_nanosleep(td, clockid, flags, rqtp, rmtp));
708 }
709
710 int
711 linux_clock_nanosleep(struct thread *td,
712     struct linux_clock_nanosleep_args *args)
713 {
714         struct timespec *rmtp;
715         struct l_timespec lrqts, lrmts;
716         struct timespec rqts, rmts;
717         int error, error2;
718
719         error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
720         if (error != 0) {
721                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
722                     error);
723                 return (error);
724         }
725
726         error = linux_to_native_timespec(&rqts, &lrqts);
727         if (error != 0) {
728                 LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
729                     error);
730                 return (error);
731         }
732
733         if (args->rmtp != NULL)
734                 rmtp = &rmts;
735         else
736                 rmtp = NULL;
737
738         error = linux_common_clock_nanosleep(td, args->which, args->flags,
739             &rqts, rmtp);
740         if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
741             args->rmtp != NULL) {
742                 error2 = native_to_linux_timespec(&lrmts, rmtp);
743                 if (error2 != 0)
744                         return (error2);
745                 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
746                 if (error2 != 0) {
747                         LIN_SDT_PROBE1(time, linux_clock_nanosleep,
748                             copyout_error, error2);
749                         return (error2);
750                 }
751         }
752         return (error);
753 }
754
755 #if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
756 int
757 linux_clock_nanosleep_time64(struct thread *td,
758     struct linux_clock_nanosleep_time64_args *args)
759 {
760         struct timespec *rmtp;
761         struct l_timespec64 lrqts, lrmts;
762         struct timespec rqts, rmts;
763         int error, error2;
764
765         error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
766         if (error != 0) {
767                 LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
768                     copyin_error, error);
769                 return (error);
770         }
771
772         error = linux_to_native_timespec64(&rqts, &lrqts);
773         if (error != 0) {
774                 LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
775                     conversion_error, error);
776                 return (error);
777         }
778
779         if (args->rmtp != NULL)
780                 rmtp = &rmts;
781         else
782                 rmtp = NULL;
783
784         error = linux_common_clock_nanosleep(td, args->which, args->flags,
785             &rqts, rmtp);
786         if (error == EINTR && (args->flags & LINUX_TIMER_ABSTIME) == 0 &&
787             args->rmtp != NULL) {
788                 error2 = native_to_linux_timespec64(&lrmts, rmtp);
789                 if (error2 != 0)
790                         return (error2);
791                 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
792                 if (error2 != 0) {
793                         LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
794                             copyout_error, error2);
795                         return (error2);
796                 }
797         }
798         return (error);
799 }
800 #endif