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