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