1 /* $NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Emmanuel Dreyfus. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 #if 0 35 __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp $"); 36 #endif 37 38 #include "opt_compat.h" 39 40 #include <sys/param.h> 41 #include <sys/kernel.h> 42 #include <sys/lock.h> 43 #include <sys/ucred.h> 44 #include <sys/limits.h> 45 #include <sys/mount.h> 46 #include <sys/mutex.h> 47 #include <sys/resourcevar.h> 48 #include <sys/sdt.h> 49 #include <sys/signal.h> 50 #include <sys/stdint.h> 51 #include <sys/syscallsubr.h> 52 #include <sys/sysproto.h> 53 #include <sys/time.h> 54 #include <sys/systm.h> 55 #include <sys/proc.h> 56 57 #ifdef COMPAT_LINUX32 58 #include <machine/../linux32/linux.h> 59 #include <machine/../linux32/linux32_proto.h> 60 #else 61 #include <machine/../linux/linux.h> 62 #include <machine/../linux/linux_proto.h> 63 #endif 64 65 #include <compat/linux/linux_dtrace.h> 66 #include <compat/linux/linux_timer.h> 67 68 /* DTrace init */ 69 LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); 70 71 /** 72 * DTrace probes in this module. 73 */ 74 LIN_SDT_PROBE_DEFINE2(time, native_to_linux_timespec, entry, 75 "struct l_timespec *", "struct timespec *"); 76 LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return); 77 LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry, 78 "struct timespec *", "struct l_timespec *"); 79 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int"); 80 LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *", 81 "clockid_t"); 82 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid, 83 "clockid_t"); 84 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid, 85 "clockid_t"); 86 LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int"); 87 LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t", 88 "struct l_timespec *"); 89 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int"); 90 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int"); 91 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int"); 92 LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int"); 93 LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t", 94 "struct l_timespec *"); 95 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int"); 96 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int"); 97 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int"); 98 LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int"); 99 LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t", 100 "struct l_timespec *"); 101 LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall); 102 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int"); 103 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int"); 104 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int"); 105 LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int"); 106 LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *", 107 "struct l_timespec *"); 108 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int"); 109 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int"); 110 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int"); 111 LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int"); 112 LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int", 113 "struct l_timespec *", "struct l_timespec *"); 114 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int"); 115 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int"); 116 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int"); 117 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int"); 118 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int"); 119 LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int"); 120 121 122 int 123 native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp) 124 { 125 126 LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp); 127 #ifdef COMPAT_LINUX32 128 if (ntp->tv_sec > INT_MAX || ntp->tv_sec < INT_MIN) 129 return (EOVERFLOW); 130 #endif 131 ltp->tv_sec = ntp->tv_sec; 132 ltp->tv_nsec = ntp->tv_nsec; 133 134 LIN_SDT_PROBE0(time, native_to_linux_timespec, return); 135 return (0); 136 } 137 138 int 139 linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp) 140 { 141 142 LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp); 143 144 if (ltp->tv_sec < 0 || ltp->tv_nsec < 0 || ltp->tv_nsec > 999999999) { 145 LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL); 146 return (EINVAL); 147 } 148 ntp->tv_sec = ltp->tv_sec; 149 ntp->tv_nsec = ltp->tv_nsec; 150 151 LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0); 152 return (0); 153 } 154 155 int 156 native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp) 157 { 158 int error; 159 160 error = native_to_linux_timespec(<p->it_interval, &ntp->it_interval); 161 if (error == 0) 162 error = native_to_linux_timespec(<p->it_value, &ntp->it_interval); 163 return (error); 164 } 165 166 int 167 linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp) 168 { 169 int error; 170 171 error = linux_to_native_timespec(&ntp->it_interval, <p->it_interval); 172 if (error == 0) 173 error = linux_to_native_timespec(&ntp->it_value, <p->it_value); 174 return (error); 175 } 176 177 int 178 linux_to_native_clockid(clockid_t *n, clockid_t l) 179 { 180 181 LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l); 182 183 if (l < 0) { 184 /* cpu-clock */ 185 if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD) 186 return (EINVAL); 187 if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX) 188 return (EINVAL); 189 190 if (LINUX_CPUCLOCK_PERTHREAD(l)) 191 *n = CLOCK_THREAD_CPUTIME_ID; 192 else 193 *n = CLOCK_PROCESS_CPUTIME_ID; 194 return (0); 195 } 196 197 switch (l) { 198 case LINUX_CLOCK_REALTIME: 199 *n = CLOCK_REALTIME; 200 break; 201 case LINUX_CLOCK_MONOTONIC: 202 *n = CLOCK_MONOTONIC; 203 break; 204 case LINUX_CLOCK_REALTIME_COARSE: 205 *n = CLOCK_REALTIME_FAST; 206 break; 207 case LINUX_CLOCK_MONOTONIC_COARSE: 208 *n = CLOCK_MONOTONIC_FAST; 209 break; 210 case LINUX_CLOCK_BOOTTIME: 211 *n = CLOCK_UPTIME; 212 break; 213 case LINUX_CLOCK_MONOTONIC_RAW: 214 case LINUX_CLOCK_REALTIME_ALARM: 215 case LINUX_CLOCK_BOOTTIME_ALARM: 216 case LINUX_CLOCK_SGI_CYCLE: 217 case LINUX_CLOCK_TAI: 218 LIN_SDT_PROBE1(time, linux_to_native_clockid, 219 unsupported_clockid, l); 220 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); 221 return (EINVAL); 222 default: 223 LIN_SDT_PROBE1(time, linux_to_native_clockid, 224 unknown_clockid, l); 225 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); 226 return (EINVAL); 227 } 228 229 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0); 230 return (0); 231 } 232 233 int 234 linux_to_native_timerflags(int *nflags, int flags) 235 { 236 237 if (flags & ~LINUX_TIMER_ABSTIME) 238 return (EINVAL); 239 *nflags = 0; 240 if (flags & LINUX_TIMER_ABSTIME) 241 *nflags |= TIMER_ABSTIME; 242 return (0); 243 } 244 245 int 246 linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args) 247 { 248 struct l_timespec lts; 249 struct timespec tp; 250 struct rusage ru; 251 struct thread *targettd; 252 struct proc *p; 253 int error, clockwhich; 254 clockid_t nwhich = 0; /* XXX: GCC */ 255 pid_t pid; 256 lwpid_t tid; 257 258 LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp); 259 260 error = linux_to_native_clockid(&nwhich, args->which); 261 if (error != 0) { 262 LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error, 263 error); 264 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 265 return (error); 266 } 267 268 switch (nwhich) { 269 case CLOCK_PROCESS_CPUTIME_ID: 270 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 271 pid = LINUX_CPUCLOCK_ID(args->which); 272 if (pid == 0) { 273 p = td->td_proc; 274 PROC_LOCK(p); 275 } else { 276 error = pget(pid, PGET_CANSEE, &p); 277 if (error != 0) 278 return (EINVAL); 279 } 280 switch (clockwhich) { 281 case LINUX_CPUCLOCK_PROF: 282 PROC_STATLOCK(p); 283 calcru(p, &ru.ru_utime, &ru.ru_stime); 284 PROC_STATUNLOCK(p); 285 PROC_UNLOCK(p); 286 timevaladd(&ru.ru_utime, &ru.ru_stime); 287 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 288 break; 289 case LINUX_CPUCLOCK_VIRT: 290 PROC_STATLOCK(p); 291 calcru(p, &ru.ru_utime, &ru.ru_stime); 292 PROC_STATUNLOCK(p); 293 PROC_UNLOCK(p); 294 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 295 break; 296 case LINUX_CPUCLOCK_SCHED: 297 PROC_UNLOCK(p); 298 error = kern_clock_getcpuclockid2(td, pid, 299 CPUCLOCK_WHICH_PID, &nwhich); 300 if (error != 0) 301 return (EINVAL); 302 error = kern_clock_gettime(td, nwhich, &tp); 303 break; 304 default: 305 PROC_UNLOCK(p); 306 return (EINVAL); 307 } 308 309 break; 310 311 case CLOCK_THREAD_CPUTIME_ID: 312 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 313 p = td->td_proc; 314 tid = LINUX_CPUCLOCK_ID(args->which); 315 if (tid == 0) { 316 targettd = td; 317 PROC_LOCK(p); 318 } else { 319 targettd = tdfind(tid, p->p_pid); 320 if (targettd == NULL) 321 return (EINVAL); 322 } 323 switch (clockwhich) { 324 case LINUX_CPUCLOCK_PROF: 325 PROC_STATLOCK(p); 326 thread_lock(targettd); 327 rufetchtd(targettd, &ru); 328 thread_unlock(targettd); 329 PROC_STATUNLOCK(p); 330 PROC_UNLOCK(p); 331 timevaladd(&ru.ru_utime, &ru.ru_stime); 332 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 333 break; 334 case LINUX_CPUCLOCK_VIRT: 335 PROC_STATLOCK(p); 336 thread_lock(targettd); 337 rufetchtd(targettd, &ru); 338 thread_unlock(targettd); 339 PROC_STATUNLOCK(p); 340 PROC_UNLOCK(p); 341 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 342 break; 343 case LINUX_CPUCLOCK_SCHED: 344 error = kern_clock_getcpuclockid2(td, tid, 345 CPUCLOCK_WHICH_TID, &nwhich); 346 PROC_UNLOCK(p); 347 if (error != 0) 348 return (EINVAL); 349 error = kern_clock_gettime(td, nwhich, &tp); 350 break; 351 default: 352 PROC_UNLOCK(p); 353 return (EINVAL); 354 } 355 break; 356 357 default: 358 error = kern_clock_gettime(td, nwhich, &tp); 359 break; 360 } 361 if (error != 0) { 362 LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error); 363 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 364 return (error); 365 } 366 error = native_to_linux_timespec(<s, &tp); 367 if (error != 0) 368 return (error); 369 error = copyout(<s, args->tp, sizeof lts); 370 if (error != 0) 371 LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error); 372 373 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 374 return (error); 375 } 376 377 int 378 linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args) 379 { 380 struct timespec ts; 381 struct l_timespec lts; 382 int error; 383 clockid_t nwhich = 0; /* XXX: GCC */ 384 385 LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp); 386 387 error = linux_to_native_clockid(&nwhich, args->which); 388 if (error != 0) { 389 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error, 390 error); 391 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 392 return (error); 393 } 394 error = copyin(args->tp, <s, sizeof lts); 395 if (error != 0) { 396 LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error); 397 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 398 return (error); 399 } 400 error = linux_to_native_timespec(&ts, <s); 401 if (error != 0) { 402 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error, 403 error); 404 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 405 return (error); 406 } 407 408 error = kern_clock_settime(td, nwhich, &ts); 409 if (error != 0) 410 LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error); 411 412 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 413 return (error); 414 } 415 416 int 417 linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args) 418 { 419 struct proc *p; 420 struct timespec ts; 421 struct l_timespec lts; 422 int error, clockwhich; 423 clockid_t nwhich = 0; /* XXX: GCC */ 424 pid_t pid; 425 lwpid_t tid; 426 427 LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp); 428 429 error = linux_to_native_clockid(&nwhich, args->which); 430 if (error != 0) { 431 LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error, 432 error); 433 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 434 return (error); 435 } 436 437 /* 438 * Check user supplied clock id in case of per-process 439 * or thread-specific cpu-time clock. 440 */ 441 switch (nwhich) { 442 case CLOCK_THREAD_CPUTIME_ID: 443 tid = LINUX_CPUCLOCK_ID(args->which); 444 if (tid != 0) { 445 p = td->td_proc; 446 if (tdfind(tid, p->p_pid) == NULL) 447 return (ESRCH); 448 PROC_UNLOCK(p); 449 } 450 break; 451 case CLOCK_PROCESS_CPUTIME_ID: 452 pid = LINUX_CPUCLOCK_ID(args->which); 453 if (pid != 0) { 454 error = pget(pid, PGET_CANSEE, &p); 455 if (error != 0) 456 return (EINVAL); 457 PROC_UNLOCK(p); 458 } 459 break; 460 } 461 462 if (args->tp == NULL) { 463 LIN_SDT_PROBE0(time, linux_clock_getres, nullcall); 464 LIN_SDT_PROBE1(time, linux_clock_getres, return, 0); 465 return (0); 466 } 467 468 switch (nwhich) { 469 case CLOCK_THREAD_CPUTIME_ID: 470 case CLOCK_PROCESS_CPUTIME_ID: 471 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 472 switch (clockwhich) { 473 case LINUX_CPUCLOCK_PROF: 474 nwhich = CLOCK_PROF; 475 break; 476 case LINUX_CPUCLOCK_VIRT: 477 nwhich = CLOCK_VIRTUAL; 478 break; 479 case LINUX_CPUCLOCK_SCHED: 480 break; 481 default: 482 return (EINVAL); 483 } 484 break; 485 486 default: 487 break; 488 } 489 error = kern_clock_getres(td, nwhich, &ts); 490 if (error != 0) { 491 LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error); 492 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 493 return (error); 494 } 495 error = native_to_linux_timespec(<s, &ts); 496 if (error != 0) 497 return (error); 498 error = copyout(<s, args->tp, sizeof lts); 499 if (error != 0) 500 LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error); 501 502 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 503 return (error); 504 } 505 506 int 507 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args) 508 { 509 struct timespec *rmtp; 510 struct l_timespec lrqts, lrmts; 511 struct timespec rqts, rmts; 512 int error, error2; 513 514 LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp); 515 516 error = copyin(args->rqtp, &lrqts, sizeof lrqts); 517 if (error != 0) { 518 LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error); 519 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 520 return (error); 521 } 522 523 if (args->rmtp != NULL) 524 rmtp = &rmts; 525 else 526 rmtp = NULL; 527 528 error = linux_to_native_timespec(&rqts, &lrqts); 529 if (error != 0) { 530 LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error); 531 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 532 return (error); 533 } 534 error = kern_nanosleep(td, &rqts, rmtp); 535 if (error == EINTR && args->rmtp != NULL) { 536 error2 = native_to_linux_timespec(&lrmts, rmtp); 537 if (error2 != 0) 538 return (error2); 539 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 540 if (error2 != 0) { 541 LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error, 542 error2); 543 LIN_SDT_PROBE1(time, linux_nanosleep, return, error2); 544 return (error2); 545 } 546 } 547 548 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 549 return (error); 550 } 551 552 int 553 linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args) 554 { 555 struct timespec *rmtp; 556 struct l_timespec lrqts, lrmts; 557 struct timespec rqts, rmts; 558 int error, error2, flags; 559 clockid_t clockid; 560 561 LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which, 562 args->flags, args->rqtp, args->rmtp); 563 564 error = linux_to_native_timerflags(&flags, args->flags); 565 if (error != 0) { 566 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags, 567 args->flags); 568 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 569 return (error); 570 } 571 572 error = linux_to_native_clockid(&clockid, args->which); 573 if (error != 0) { 574 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid, 575 args->which); 576 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 577 return (error); 578 } 579 580 error = copyin(args->rqtp, &lrqts, sizeof(lrqts)); 581 if (error != 0) { 582 LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error, 583 error); 584 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 585 return (error); 586 } 587 588 if (args->rmtp != NULL) 589 rmtp = &rmts; 590 else 591 rmtp = NULL; 592 593 error = linux_to_native_timespec(&rqts, &lrqts); 594 if (error != 0) { 595 LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error, 596 error); 597 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 598 return (error); 599 } 600 error = kern_clock_nanosleep(td, clockid, flags, &rqts, rmtp); 601 if (error == EINTR && (flags & TIMER_ABSTIME) == 0 && 602 args->rmtp != NULL) { 603 error2 = native_to_linux_timespec(&lrmts, rmtp); 604 if (error2 != 0) 605 return (error2); 606 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 607 if (error2 != 0) { 608 LIN_SDT_PROBE1(time, linux_clock_nanosleep, 609 copyout_error, error2); 610 LIN_SDT_PROBE1(time, linux_clock_nanosleep, 611 return, error2); 612 return (error2); 613 } 614 } 615 616 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 617 return (error); 618 } 619