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: releng/12.0/sys/compat/linux/linux_time.c 328890 2018-02-05 17:29:12Z emaste $");
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_timer.h>
69
70 /* DTrace init */
71 LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
72
73 /**
74 * DTrace probes in this module.
75 */
76 LIN_SDT_PROBE_DEFINE2(time, native_to_linux_timespec, entry,
77 "struct l_timespec *", "struct timespec *");
78 LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return);
79 LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry,
80 "struct timespec *", "struct l_timespec *");
81 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int");
82 LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *",
83 "clockid_t");
84 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid,
85 "clockid_t");
86 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid,
87 "clockid_t");
88 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int");
89 LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t",
90 "struct l_timespec *");
91 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int");
92 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int");
93 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int");
94 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int");
95 LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t",
96 "struct l_timespec *");
97 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int");
98 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int");
99 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int");
100 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int");
101 LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t",
102 "struct l_timespec *");
103 LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall);
104 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int");
105 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int");
106 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
107 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int");
108 LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *",
109 "struct l_timespec *");
110 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
111 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
112 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
113 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int");
114 LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int",
115 "struct l_timespec *", "struct l_timespec *");
116 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
117 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
118 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
119 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int");
120 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
121 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int");
122
123
124 int
125 native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
126 {
127
128 LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp);
129 #ifdef COMPAT_LINUX32
130 if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN)
131 return (EOVERFLOW);
132 #endif
133 ltp->tv_sec = ntp->tv_sec;
134 ltp->tv_nsec = ntp->tv_nsec;
135
136 LIN_SDT_PROBE0(time, native_to_linux_timespec, return);
137 return (0);
138 }
139
140 int
141 linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
142 {
143
144 LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp);
145
146 if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999) {
147 LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL);
148 return (EINVAL);
149 }
150 ntp->tv_sec = ltp->tv_sec;
151 ntp->tv_nsec = ltp->tv_nsec;
152
153 LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0);
154 return (0);
155 }
156
157 int
158 native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
159 {
160 int error;
161
162 error = native_to_linux_timespec(<p->it_interval, &ntp->it_interval);
163 if (error == 0)
164 error = native_to_linux_timespec(<p->it_value, &ntp->it_interval);
165 return (error);
166 }
167
168 int
169 linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
170 {
171 int error;
172
173 error = linux_to_native_timespec(&ntp->it_interval, <p->it_interval);
174 if (error == 0)
175 error = linux_to_native_timespec(&ntp->it_value, <p->it_value);
176 return (error);
177 }
178
179 int
180 linux_to_native_clockid(clockid_t *n, clockid_t l)
181 {
182
183 LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l);
184
185 if (l < 0) {
186 /* cpu-clock */
187 if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD)
188 return (EINVAL);
189 if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX)
190 return (EINVAL);
191
192 if (LINUX_CPUCLOCK_PERTHREAD(l))
193 *n = CLOCK_THREAD_CPUTIME_ID;
194 else
195 *n = CLOCK_PROCESS_CPUTIME_ID;
196 return (0);
197 }
198
199 switch (l) {
200 case LINUX_CLOCK_REALTIME:
201 *n = CLOCK_REALTIME;
202 break;
203 case LINUX_CLOCK_MONOTONIC:
204 *n = CLOCK_MONOTONIC;
205 break;
206 case LINUX_CLOCK_REALTIME_COARSE:
207 *n = CLOCK_REALTIME_FAST;
208 break;
209 case LINUX_CLOCK_MONOTONIC_COARSE:
210 *n = CLOCK_MONOTONIC_FAST;
211 break;
212 case LINUX_CLOCK_BOOTTIME:
213 *n = CLOCK_UPTIME;
214 break;
215 case LINUX_CLOCK_MONOTONIC_RAW:
216 case LINUX_CLOCK_REALTIME_ALARM:
217 case LINUX_CLOCK_BOOTTIME_ALARM:
218 case LINUX_CLOCK_SGI_CYCLE:
219 case LINUX_CLOCK_TAI:
220 LIN_SDT_PROBE1(time, linux_to_native_clockid,
221 unsupported_clockid, l);
222 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
223 return (EINVAL);
224 default:
225 LIN_SDT_PROBE1(time, linux_to_native_clockid,
226 unknown_clockid, l);
227 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL);
228 return (EINVAL);
229 }
230
231 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0);
232 return (0);
233 }
234
235 int
236 linux_to_native_timerflags(int *nflags, int flags)
237 {
238
239 if (flags & ~LINUX_TIMER_ABSTIME)
240 return (EINVAL);
241 *nflags = 0;
242 if (flags & LINUX_TIMER_ABSTIME)
243 *nflags |= TIMER_ABSTIME;
244 return (0);
245 }
246
247 int
248 linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
249 {
250 struct l_timespec lts;
251 struct timespec tp;
252 struct rusage ru;
253 struct thread *targettd;
254 struct proc *p;
255 int error, clockwhich;
256 clockid_t nwhich = 0; /* XXX: GCC */
257 pid_t pid;
258 lwpid_t tid;
259
260 LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp);
261
262 error = linux_to_native_clockid(&nwhich, args->which);
263 if (error != 0) {
264 LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error,
265 error);
266 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
267 return (error);
268 }
269
270 switch (nwhich) {
271 case CLOCK_PROCESS_CPUTIME_ID:
272 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
273 pid = LINUX_CPUCLOCK_ID(args->which);
274 if (pid == 0) {
275 p = td->td_proc;
276 PROC_LOCK(p);
277 } else {
278 error = pget(pid, PGET_CANSEE, &p);
279 if (error != 0)
280 return (EINVAL);
281 }
282 switch (clockwhich) {
283 case LINUX_CPUCLOCK_PROF:
284 PROC_STATLOCK(p);
285 calcru(p, &ru.ru_utime, &ru.ru_stime);
286 PROC_STATUNLOCK(p);
287 PROC_UNLOCK(p);
288 timevaladd(&ru.ru_utime, &ru.ru_stime);
289 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
290 break;
291 case LINUX_CPUCLOCK_VIRT:
292 PROC_STATLOCK(p);
293 calcru(p, &ru.ru_utime, &ru.ru_stime);
294 PROC_STATUNLOCK(p);
295 PROC_UNLOCK(p);
296 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
297 break;
298 case LINUX_CPUCLOCK_SCHED:
299 PROC_UNLOCK(p);
300 error = kern_clock_getcpuclockid2(td, pid,
301 CPUCLOCK_WHICH_PID, &nwhich);
302 if (error != 0)
303 return (EINVAL);
304 error = kern_clock_gettime(td, nwhich, &tp);
305 break;
306 default:
307 PROC_UNLOCK(p);
308 return (EINVAL);
309 }
310
311 break;
312
313 case CLOCK_THREAD_CPUTIME_ID:
314 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
315 p = td->td_proc;
316 tid = LINUX_CPUCLOCK_ID(args->which);
317 if (tid == 0) {
318 targettd = td;
319 PROC_LOCK(p);
320 } else {
321 targettd = tdfind(tid, p->p_pid);
322 if (targettd == NULL)
323 return (EINVAL);
324 }
325 switch (clockwhich) {
326 case LINUX_CPUCLOCK_PROF:
327 PROC_STATLOCK(p);
328 thread_lock(targettd);
329 rufetchtd(targettd, &ru);
330 thread_unlock(targettd);
331 PROC_STATUNLOCK(p);
332 PROC_UNLOCK(p);
333 timevaladd(&ru.ru_utime, &ru.ru_stime);
334 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
335 break;
336 case LINUX_CPUCLOCK_VIRT:
337 PROC_STATLOCK(p);
338 thread_lock(targettd);
339 rufetchtd(targettd, &ru);
340 thread_unlock(targettd);
341 PROC_STATUNLOCK(p);
342 PROC_UNLOCK(p);
343 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp);
344 break;
345 case LINUX_CPUCLOCK_SCHED:
346 error = kern_clock_getcpuclockid2(td, tid,
347 CPUCLOCK_WHICH_TID, &nwhich);
348 PROC_UNLOCK(p);
349 if (error != 0)
350 return (EINVAL);
351 error = kern_clock_gettime(td, nwhich, &tp);
352 break;
353 default:
354 PROC_UNLOCK(p);
355 return (EINVAL);
356 }
357 break;
358
359 default:
360 error = kern_clock_gettime(td, nwhich, &tp);
361 break;
362 }
363 if (error != 0) {
364 LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error);
365 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
366 return (error);
367 }
368 error = native_to_linux_timespec(<s, &tp);
369 if (error != 0)
370 return (error);
371 error = copyout(<s, args->tp, sizeof lts);
372 if (error != 0)
373 LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
374
375 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
376 return (error);
377 }
378
379 int
380 linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
381 {
382 struct timespec ts;
383 struct l_timespec lts;
384 int error;
385 clockid_t nwhich = 0; /* XXX: GCC */
386
387 LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp);
388
389 error = linux_to_native_clockid(&nwhich, args->which);
390 if (error != 0) {
391 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
392 error);
393 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
394 return (error);
395 }
396 error = copyin(args->tp, <s, sizeof lts);
397 if (error != 0) {
398 LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
399 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
400 return (error);
401 }
402 error = linux_to_native_timespec(&ts, <s);
403 if (error != 0) {
404 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
405 error);
406 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
407 return (error);
408 }
409
410 error = kern_clock_settime(td, nwhich, &ts);
411 if (error != 0)
412 LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error);
413
414 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
415 return (error);
416 }
417
418 int
419 linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
420 {
421 struct proc *p;
422 struct timespec ts;
423 struct l_timespec lts;
424 int error, clockwhich;
425 clockid_t nwhich = 0; /* XXX: GCC */
426 pid_t pid;
427 lwpid_t tid;
428
429 LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp);
430
431 error = linux_to_native_clockid(&nwhich, args->which);
432 if (error != 0) {
433 LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error,
434 error);
435 LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
436 return (error);
437 }
438
439 /*
440 * Check user supplied clock id in case of per-process
441 * or thread-specific cpu-time clock.
442 */
443 switch (nwhich) {
444 case CLOCK_THREAD_CPUTIME_ID:
445 tid = LINUX_CPUCLOCK_ID(args->which);
446 if (tid != 0) {
447 p = td->td_proc;
448 if (tdfind(tid, p->p_pid) == NULL)
449 return (ESRCH);
450 PROC_UNLOCK(p);
451 }
452 break;
453 case CLOCK_PROCESS_CPUTIME_ID:
454 pid = LINUX_CPUCLOCK_ID(args->which);
455 if (pid != 0) {
456 error = pget(pid, PGET_CANSEE, &p);
457 if (error != 0)
458 return (EINVAL);
459 PROC_UNLOCK(p);
460 }
461 break;
462 }
463
464 if (args->tp == NULL) {
465 LIN_SDT_PROBE0(time, linux_clock_getres, nullcall);
466 LIN_SDT_PROBE1(time, linux_clock_getres, return, 0);
467 return (0);
468 }
469
470 switch (nwhich) {
471 case CLOCK_THREAD_CPUTIME_ID:
472 case CLOCK_PROCESS_CPUTIME_ID:
473 clockwhich = LINUX_CPUCLOCK_WHICH(args->which);
474 switch (clockwhich) {
475 case LINUX_CPUCLOCK_PROF:
476 nwhich = CLOCK_PROF;
477 break;
478 case LINUX_CPUCLOCK_VIRT:
479 nwhich = CLOCK_VIRTUAL;
480 break;
481 case LINUX_CPUCLOCK_SCHED:
482 break;
483 default:
484 return (EINVAL);
485 }
486 break;
487
488 default:
489 break;
490 }
491 error = kern_clock_getres(td, nwhich, &ts);
492 if (error != 0) {
493 LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error);
494 LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
495 return (error);
496 }
497 error = native_to_linux_timespec(<s, &ts);
498 if (error != 0)
499 return (error);
500 error = copyout(<s, args->tp, sizeof lts);
501 if (error != 0)
502 LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
503
504 LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
505 return (error);
506 }
507
508 int
509 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
510 {
511 struct timespec *rmtp;
512 struct l_timespec lrqts, lrmts;
513 struct timespec rqts, rmts;
514 int error, error2;
515
516 LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp);
517
518 error = copyin(args->rqtp, &lrqts, sizeof lrqts);
519 if (error != 0) {
520 LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
521 LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
522 return (error);
523 }
524
525 if (args->rmtp != NULL)
526 rmtp = &rmts;
527 else
528 rmtp = NULL;
529
530 error = linux_to_native_timespec(&rqts, &lrqts);
531 if (error != 0) {
532 LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
533 LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
534 return (error);
535 }
536 error = kern_nanosleep(td, &rqts, rmtp);
537 if (error == EINTR && args->rmtp != NULL) {
538 error2 = native_to_linux_timespec(&lrmts, rmtp);
539 if (error2 != 0)
540 return (error2);
541 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
542 if (error2 != 0) {
543 LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
544 error2);
545 LIN_SDT_PROBE1(time, linux_nanosleep, return, error2);
546 return (error2);
547 }
548 }
549
550 LIN_SDT_PROBE1(time, linux_nanosleep, return, error);
551 return (error);
552 }
553
554 int
555 linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args)
556 {
557 struct timespec *rmtp;
558 struct l_timespec lrqts, lrmts;
559 struct timespec rqts, rmts;
560 int error, error2, flags;
561 clockid_t clockid;
562
563 LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which,
564 args->flags, args->rqtp, args->rmtp);
565
566 error = linux_to_native_timerflags(&flags, args->flags);
567 if (error != 0) {
568 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags,
569 args->flags);
570 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
571 return (error);
572 }
573
574 error = linux_to_native_clockid(&clockid, args->which);
575 if (error != 0) {
576 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid,
577 args->which);
578 LIN_SDT_PROBE1(time, linux_clock_settime, return, error);
579 return (error);
580 }
581
582 error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
583 if (error != 0) {
584 LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
585 error);
586 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
587 return (error);
588 }
589
590 if (args->rmtp != NULL)
591 rmtp = &rmts;
592 else
593 rmtp = NULL;
594
595 error = linux_to_native_timespec(&rqts, &lrqts);
596 if (error != 0) {
597 LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
598 error);
599 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
600 return (error);
601 }
602 error = kern_clock_nanosleep(td, clockid, flags, &rqts, rmtp);
603 if (error == EINTR && (flags & TIMER_ABSTIME) == 0 &&
604 args->rmtp != NULL) {
605 error2 = native_to_linux_timespec(&lrmts, rmtp);
606 if (error2 != 0)
607 return (error2);
608 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
609 if (error2 != 0) {
610 LIN_SDT_PROBE1(time, linux_clock_nanosleep,
611 copyout_error, error2);
612 LIN_SDT_PROBE1(time, linux_clock_nanosleep,
613 return, error2);
614 return (error2);
615 }
616 }
617
618 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error);
619 return (error);
620 }
Cache object: 0f69c33c0f870bf5d85bfc8ce8730bee
|