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 && 129 sizeof(ltp->tv_sec) != sizeof(ntp->tv_sec)) 130 return (EOVERFLOW); 131 #endif 132 ltp->tv_sec = ntp->tv_sec; 133 ltp->tv_nsec = ntp->tv_nsec; 134 135 LIN_SDT_PROBE0(time, native_to_linux_timespec, return); 136 return (0); 137 } 138 139 int 140 linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp) 141 { 142 143 LIN_SDT_PROBE2(time, linux_to_native_timespec, entry, ntp, ltp); 144 145 if (ltp->tv_sec < 0 || (l_ulong)ltp->tv_nsec > 999999999L) { 146 LIN_SDT_PROBE1(time, linux_to_native_timespec, return, EINVAL); 147 return (EINVAL); 148 } 149 ntp->tv_sec = ltp->tv_sec; 150 ntp->tv_nsec = ltp->tv_nsec; 151 152 LIN_SDT_PROBE1(time, linux_to_native_timespec, return, 0); 153 return (0); 154 } 155 156 int 157 native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp) 158 { 159 int error; 160 161 error = native_to_linux_timespec(<p->it_interval, &ntp->it_interval); 162 if (error == 0) 163 error = native_to_linux_timespec(<p->it_value, &ntp->it_interval); 164 return (error); 165 } 166 167 int 168 linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp) 169 { 170 int error; 171 172 error = linux_to_native_timespec(&ntp->it_interval, <p->it_interval); 173 if (error == 0) 174 error = linux_to_native_timespec(&ntp->it_value, <p->it_value); 175 return (error); 176 } 177 178 int 179 linux_to_native_clockid(clockid_t *n, clockid_t l) 180 { 181 182 LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l); 183 184 if (l < 0) { 185 /* cpu-clock */ 186 if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD) 187 return (EINVAL); 188 if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX) 189 return (EINVAL); 190 191 if (LINUX_CPUCLOCK_PERTHREAD(l)) 192 *n = CLOCK_THREAD_CPUTIME_ID; 193 else 194 *n = CLOCK_PROCESS_CPUTIME_ID; 195 return (0); 196 } 197 198 switch (l) { 199 case LINUX_CLOCK_REALTIME: 200 *n = CLOCK_REALTIME; 201 break; 202 case LINUX_CLOCK_MONOTONIC: 203 *n = CLOCK_MONOTONIC; 204 break; 205 case LINUX_CLOCK_REALTIME_COARSE: 206 *n = CLOCK_REALTIME_FAST; 207 break; 208 case LINUX_CLOCK_MONOTONIC_COARSE: 209 *n = CLOCK_MONOTONIC_FAST; 210 break; 211 case LINUX_CLOCK_MONOTONIC_RAW: 212 case LINUX_CLOCK_BOOTTIME: 213 case LINUX_CLOCK_REALTIME_ALARM: 214 case LINUX_CLOCK_BOOTTIME_ALARM: 215 case LINUX_CLOCK_SGI_CYCLE: 216 case LINUX_CLOCK_TAI: 217 LIN_SDT_PROBE1(time, linux_to_native_clockid, 218 unsupported_clockid, l); 219 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); 220 return (EINVAL); 221 default: 222 LIN_SDT_PROBE1(time, linux_to_native_clockid, 223 unknown_clockid, l); 224 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); 225 return (EINVAL); 226 } 227 228 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0); 229 return (0); 230 } 231 232 int 233 linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args) 234 { 235 struct l_timespec lts; 236 struct timespec tp; 237 struct rusage ru; 238 struct thread *targettd; 239 struct proc *p; 240 int error, clockwhich; 241 clockid_t nwhich = 0; /* XXX: GCC */ 242 pid_t pid; 243 lwpid_t tid; 244 245 LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp); 246 247 error = linux_to_native_clockid(&nwhich, args->which); 248 if (error != 0) { 249 LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error, 250 error); 251 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 252 return (error); 253 } 254 255 switch (nwhich) { 256 case CLOCK_PROCESS_CPUTIME_ID: 257 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 258 pid = LINUX_CPUCLOCK_ID(args->which); 259 if (pid == 0) { 260 p = td->td_proc; 261 PROC_LOCK(p); 262 } else { 263 error = pget(pid, PGET_CANSEE, &p); 264 if (error != 0) 265 return (EINVAL); 266 } 267 switch (clockwhich) { 268 case LINUX_CPUCLOCK_PROF: 269 PROC_STATLOCK(p); 270 calcru(p, &ru.ru_utime, &ru.ru_stime); 271 PROC_STATUNLOCK(p); 272 PROC_UNLOCK(p); 273 timevaladd(&ru.ru_utime, &ru.ru_stime); 274 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 275 break; 276 case LINUX_CPUCLOCK_VIRT: 277 PROC_STATLOCK(p); 278 calcru(p, &ru.ru_utime, &ru.ru_stime); 279 PROC_STATUNLOCK(p); 280 PROC_UNLOCK(p); 281 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 282 break; 283 case LINUX_CPUCLOCK_SCHED: 284 PROC_UNLOCK(p); 285 error = kern_clock_getcpuclockid2(td, pid, 286 CPUCLOCK_WHICH_PID, &nwhich); 287 if (error != 0) 288 return (EINVAL); 289 error = kern_clock_gettime(td, nwhich, &tp); 290 break; 291 default: 292 PROC_UNLOCK(p); 293 return (EINVAL); 294 } 295 296 break; 297 298 case CLOCK_THREAD_CPUTIME_ID: 299 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 300 p = td->td_proc; 301 tid = LINUX_CPUCLOCK_ID(args->which); 302 if (tid == 0) { 303 targettd = td; 304 PROC_LOCK(p); 305 } else { 306 targettd = tdfind(tid, p->p_pid); 307 if (targettd == NULL) 308 return (EINVAL); 309 } 310 switch (clockwhich) { 311 case LINUX_CPUCLOCK_PROF: 312 PROC_STATLOCK(p); 313 thread_lock(targettd); 314 rufetchtd(targettd, &ru); 315 thread_unlock(targettd); 316 PROC_STATUNLOCK(p); 317 PROC_UNLOCK(p); 318 timevaladd(&ru.ru_utime, &ru.ru_stime); 319 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 320 break; 321 case LINUX_CPUCLOCK_VIRT: 322 PROC_STATLOCK(p); 323 thread_lock(targettd); 324 rufetchtd(targettd, &ru); 325 thread_unlock(targettd); 326 PROC_STATUNLOCK(p); 327 PROC_UNLOCK(p); 328 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 329 break; 330 case LINUX_CPUCLOCK_SCHED: 331 error = kern_clock_getcpuclockid2(td, tid, 332 CPUCLOCK_WHICH_TID, &nwhich); 333 PROC_UNLOCK(p); 334 if (error != 0) 335 return (EINVAL); 336 error = kern_clock_gettime(td, nwhich, &tp); 337 break; 338 default: 339 PROC_UNLOCK(p); 340 return (EINVAL); 341 } 342 break; 343 344 default: 345 error = kern_clock_gettime(td, nwhich, &tp); 346 break; 347 } 348 if (error != 0) { 349 LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error); 350 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 351 return (error); 352 } 353 error = native_to_linux_timespec(<s, &tp); 354 if (error != 0) 355 return (error); 356 error = copyout(<s, args->tp, sizeof lts); 357 if (error != 0) 358 LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error); 359 360 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 361 return (error); 362 } 363 364 int 365 linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args) 366 { 367 struct timespec ts; 368 struct l_timespec lts; 369 int error; 370 clockid_t nwhich = 0; /* XXX: GCC */ 371 372 LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp); 373 374 error = linux_to_native_clockid(&nwhich, args->which); 375 if (error != 0) { 376 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error, 377 error); 378 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 379 return (error); 380 } 381 error = copyin(args->tp, <s, sizeof lts); 382 if (error != 0) { 383 LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error); 384 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 385 return (error); 386 } 387 error = linux_to_native_timespec(&ts, <s); 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 395 error = kern_clock_settime(td, nwhich, &ts); 396 if (error != 0) 397 LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error); 398 399 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 400 return (error); 401 } 402 403 int 404 linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args) 405 { 406 struct proc *p; 407 struct timespec ts; 408 struct l_timespec lts; 409 int error, clockwhich; 410 clockid_t nwhich = 0; /* XXX: GCC */ 411 pid_t pid; 412 lwpid_t tid; 413 414 LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp); 415 416 error = linux_to_native_clockid(&nwhich, args->which); 417 if (error != 0) { 418 LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error, 419 error); 420 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 421 return (error); 422 } 423 424 /* 425 * Check user supplied clock id in case of per-process 426 * or thread-specific cpu-time clock. 427 */ 428 switch (nwhich) { 429 case CLOCK_THREAD_CPUTIME_ID: 430 tid = LINUX_CPUCLOCK_ID(args->which); 431 if (tid != 0) { 432 p = td->td_proc; 433 if (tdfind(tid, p->p_pid) == NULL) 434 return (ESRCH); 435 PROC_UNLOCK(p); 436 } 437 break; 438 case CLOCK_PROCESS_CPUTIME_ID: 439 pid = LINUX_CPUCLOCK_ID(args->which); 440 if (pid != 0) { 441 error = pget(pid, PGET_CANSEE, &p); 442 if (error != 0) 443 return (EINVAL); 444 PROC_UNLOCK(p); 445 } 446 break; 447 } 448 449 if (args->tp == NULL) { 450 LIN_SDT_PROBE0(time, linux_clock_getres, nullcall); 451 LIN_SDT_PROBE1(time, linux_clock_getres, return, 0); 452 return (0); 453 } 454 455 switch (nwhich) { 456 case CLOCK_THREAD_CPUTIME_ID: 457 case CLOCK_PROCESS_CPUTIME_ID: 458 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 459 switch (clockwhich) { 460 case LINUX_CPUCLOCK_PROF: 461 nwhich = CLOCK_PROF; 462 break; 463 case LINUX_CPUCLOCK_VIRT: 464 nwhich = CLOCK_VIRTUAL; 465 break; 466 case LINUX_CPUCLOCK_SCHED: 467 break; 468 default: 469 return (EINVAL); 470 } 471 break; 472 473 default: 474 break; 475 } 476 error = kern_clock_getres(td, nwhich, &ts); 477 if (error != 0) { 478 LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error); 479 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 480 return (error); 481 } 482 error = native_to_linux_timespec(<s, &ts); 483 if (error != 0) 484 return (error); 485 error = copyout(<s, args->tp, sizeof lts); 486 if (error != 0) 487 LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error); 488 489 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 490 return (error); 491 } 492 493 int 494 linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args) 495 { 496 struct timespec *rmtp; 497 struct l_timespec lrqts, lrmts; 498 struct timespec rqts, rmts; 499 int error, error2; 500 501 LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp); 502 503 error = copyin(args->rqtp, &lrqts, sizeof lrqts); 504 if (error != 0) { 505 LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error); 506 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 507 return (error); 508 } 509 510 if (args->rmtp != NULL) 511 rmtp = &rmts; 512 else 513 rmtp = NULL; 514 515 error = linux_to_native_timespec(&rqts, &lrqts); 516 if (error != 0) { 517 LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error); 518 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 519 return (error); 520 } 521 error = kern_nanosleep(td, &rqts, rmtp); 522 if (error == EINTR && args->rmtp != NULL) { 523 error2 = native_to_linux_timespec(&lrmts, rmtp); 524 if (error2 != 0) 525 return (error2); 526 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 527 if (error2 != 0) { 528 LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error, 529 error2); 530 LIN_SDT_PROBE1(time, linux_nanosleep, return, error2); 531 return (error2); 532 } 533 } 534 535 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 536 return (error); 537 } 538 539 int 540 linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args) 541 { 542 struct timespec *rmtp; 543 struct l_timespec lrqts, lrmts; 544 struct timespec rqts, rmts; 545 int error, error2; 546 547 LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which, 548 args->flags, args->rqtp, args->rmtp); 549 550 if (args->flags != 0) { 551 /* XXX deal with TIMER_ABSTIME */ 552 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags, 553 args->flags); 554 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL); 555 return (EINVAL); /* XXX deal with TIMER_ABSTIME */ 556 } 557 558 if (args->which != LINUX_CLOCK_REALTIME) { 559 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid, 560 args->which); 561 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL); 562 return (EINVAL); 563 } 564 565 error = copyin(args->rqtp, &lrqts, sizeof(lrqts)); 566 if (error != 0) { 567 LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error, 568 error); 569 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 570 return (error); 571 } 572 573 if (args->rmtp != NULL) 574 rmtp = &rmts; 575 else 576 rmtp = NULL; 577 578 error = linux_to_native_timespec(&rqts, &lrqts); 579 if (error != 0) { 580 LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error, 581 error); 582 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 583 return (error); 584 } 585 error = kern_nanosleep(td, &rqts, rmtp); 586 if (error == EINTR && args->rmtp != NULL) { 587 /* XXX. Not for TIMER_ABSTIME */ 588 error2 = native_to_linux_timespec(&lrmts, rmtp); 589 if (error2 != 0) 590 return (error2); 591 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 592 if (error2 != 0) { 593 LIN_SDT_PROBE1(time, linux_clock_nanosleep, 594 copyout_error, error2); 595 LIN_SDT_PROBE1(time, linux_clock_nanosleep, 596 return, error2); 597 return (error2); 598 } 599 } 600 601 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 602 return (error); 603 } 604