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_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 } 621