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