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