linux_time.c revision 316967
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: stable/11/sys/compat/linux/linux_time.c 316967 2017-04-15 15:30:28Z dchagin $"); 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 */ 69LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); 70 71/** 72 * DTrace probes in this module. 73 */ 74LIN_SDT_PROBE_DEFINE2(time, native_to_linux_timespec, entry, 75 "struct l_timespec *", "struct timespec *"); 76LIN_SDT_PROBE_DEFINE0(time, native_to_linux_timespec, return); 77LIN_SDT_PROBE_DEFINE2(time, linux_to_native_timespec, entry, 78 "struct timespec *", "struct l_timespec *"); 79LIN_SDT_PROBE_DEFINE1(time, linux_to_native_timespec, return, "int"); 80LIN_SDT_PROBE_DEFINE2(time, linux_to_native_clockid, entry, "clockid_t *", 81 "clockid_t"); 82LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unsupported_clockid, 83 "clockid_t"); 84LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, unknown_clockid, 85 "clockid_t"); 86LIN_SDT_PROBE_DEFINE1(time, linux_to_native_clockid, return, "int"); 87LIN_SDT_PROBE_DEFINE2(time, linux_clock_gettime, entry, "clockid_t", 88 "struct l_timespec *"); 89LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, conversion_error, "int"); 90LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, gettime_error, "int"); 91LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, copyout_error, "int"); 92LIN_SDT_PROBE_DEFINE1(time, linux_clock_gettime, return, "int"); 93LIN_SDT_PROBE_DEFINE2(time, linux_clock_settime, entry, "clockid_t", 94 "struct l_timespec *"); 95LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, conversion_error, "int"); 96LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, settime_error, "int"); 97LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, copyin_error, "int"); 98LIN_SDT_PROBE_DEFINE1(time, linux_clock_settime, return, "int"); 99LIN_SDT_PROBE_DEFINE2(time, linux_clock_getres, entry, "clockid_t", 100 "struct l_timespec *"); 101LIN_SDT_PROBE_DEFINE0(time, linux_clock_getres, nullcall); 102LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, conversion_error, "int"); 103LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, getres_error, "int"); 104LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int"); 105LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, return, "int"); 106LIN_SDT_PROBE_DEFINE2(time, linux_nanosleep, entry, "const struct l_timespec *", 107 "struct l_timespec *"); 108LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int"); 109LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int"); 110LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int"); 111LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, return, "int"); 112LIN_SDT_PROBE_DEFINE4(time, linux_clock_nanosleep, entry, "clockid_t", "int", 113 "struct l_timespec *", "struct l_timespec *"); 114LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int"); 115LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int"); 116LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int"); 117LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_flags, "int"); 118LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int"); 119LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int"); 120 121 122int 123native_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 138int 139linux_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 || (l_ulong)ltp->tv_nsec > 999999999L) { 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 155int 156native_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 166int 167linux_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 177int 178linux_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_MONOTONIC_RAW: 211 case LINUX_CLOCK_BOOTTIME: 212 case LINUX_CLOCK_REALTIME_ALARM: 213 case LINUX_CLOCK_BOOTTIME_ALARM: 214 case LINUX_CLOCK_SGI_CYCLE: 215 case LINUX_CLOCK_TAI: 216 LIN_SDT_PROBE1(time, linux_to_native_clockid, 217 unsupported_clockid, l); 218 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); 219 return (EINVAL); 220 default: 221 LIN_SDT_PROBE1(time, linux_to_native_clockid, 222 unknown_clockid, l); 223 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); 224 return (EINVAL); 225 } 226 227 LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0); 228 return (0); 229} 230 231int 232linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args) 233{ 234 struct l_timespec lts; 235 struct timespec tp; 236 struct rusage ru; 237 struct thread *targettd; 238 struct proc *p; 239 int error, clockwhich; 240 clockid_t nwhich = 0; /* XXX: GCC */ 241 pid_t pid; 242 lwpid_t tid; 243 244 LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp); 245 246 error = linux_to_native_clockid(&nwhich, args->which); 247 if (error != 0) { 248 LIN_SDT_PROBE1(time, linux_clock_gettime, conversion_error, 249 error); 250 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 251 return (error); 252 } 253 254 switch (nwhich) { 255 case CLOCK_PROCESS_CPUTIME_ID: 256 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 257 pid = LINUX_CPUCLOCK_ID(args->which); 258 if (pid == 0) { 259 p = td->td_proc; 260 PROC_LOCK(p); 261 } else { 262 error = pget(pid, PGET_CANSEE, &p); 263 if (error != 0) 264 return (EINVAL); 265 } 266 switch (clockwhich) { 267 case LINUX_CPUCLOCK_PROF: 268 PROC_STATLOCK(p); 269 calcru(p, &ru.ru_utime, &ru.ru_stime); 270 PROC_STATUNLOCK(p); 271 PROC_UNLOCK(p); 272 timevaladd(&ru.ru_utime, &ru.ru_stime); 273 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 274 break; 275 case LINUX_CPUCLOCK_VIRT: 276 PROC_STATLOCK(p); 277 calcru(p, &ru.ru_utime, &ru.ru_stime); 278 PROC_STATUNLOCK(p); 279 PROC_UNLOCK(p); 280 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 281 break; 282 case LINUX_CPUCLOCK_SCHED: 283 PROC_UNLOCK(p); 284 error = kern_clock_getcpuclockid2(td, pid, 285 CPUCLOCK_WHICH_PID, &nwhich); 286 if (error != 0) 287 return (EINVAL); 288 error = kern_clock_gettime(td, nwhich, &tp); 289 break; 290 default: 291 PROC_UNLOCK(p); 292 return (EINVAL); 293 } 294 295 break; 296 297 case CLOCK_THREAD_CPUTIME_ID: 298 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 299 p = td->td_proc; 300 tid = LINUX_CPUCLOCK_ID(args->which); 301 if (tid == 0) { 302 targettd = td; 303 PROC_LOCK(p); 304 } else { 305 targettd = tdfind(tid, p->p_pid); 306 if (targettd == NULL) 307 return (EINVAL); 308 } 309 switch (clockwhich) { 310 case LINUX_CPUCLOCK_PROF: 311 PROC_STATLOCK(p); 312 thread_lock(targettd); 313 rufetchtd(targettd, &ru); 314 thread_unlock(targettd); 315 PROC_STATUNLOCK(p); 316 PROC_UNLOCK(p); 317 timevaladd(&ru.ru_utime, &ru.ru_stime); 318 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 319 break; 320 case LINUX_CPUCLOCK_VIRT: 321 PROC_STATLOCK(p); 322 thread_lock(targettd); 323 rufetchtd(targettd, &ru); 324 thread_unlock(targettd); 325 PROC_STATUNLOCK(p); 326 PROC_UNLOCK(p); 327 TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); 328 break; 329 case LINUX_CPUCLOCK_SCHED: 330 error = kern_clock_getcpuclockid2(td, tid, 331 CPUCLOCK_WHICH_TID, &nwhich); 332 PROC_UNLOCK(p); 333 if (error != 0) 334 return (EINVAL); 335 error = kern_clock_gettime(td, nwhich, &tp); 336 break; 337 default: 338 PROC_UNLOCK(p); 339 return (EINVAL); 340 } 341 break; 342 343 default: 344 error = kern_clock_gettime(td, nwhich, &tp); 345 break; 346 } 347 if (error != 0) { 348 LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error); 349 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 350 return (error); 351 } 352 error = native_to_linux_timespec(<s, &tp); 353 if (error != 0) 354 return (error); 355 error = copyout(<s, args->tp, sizeof lts); 356 if (error != 0) 357 LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error); 358 359 LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); 360 return (error); 361} 362 363int 364linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args) 365{ 366 struct timespec ts; 367 struct l_timespec lts; 368 int error; 369 clockid_t nwhich = 0; /* XXX: GCC */ 370 371 LIN_SDT_PROBE2(time, linux_clock_settime, entry, args->which, args->tp); 372 373 error = linux_to_native_clockid(&nwhich, args->which); 374 if (error != 0) { 375 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error, 376 error); 377 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 378 return (error); 379 } 380 error = copyin(args->tp, <s, sizeof lts); 381 if (error != 0) { 382 LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error); 383 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 384 return (error); 385 } 386 error = linux_to_native_timespec(&ts, <s); 387 if (error != 0) { 388 LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error, 389 error); 390 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 391 return (error); 392 } 393 394 error = kern_clock_settime(td, nwhich, &ts); 395 if (error != 0) 396 LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error); 397 398 LIN_SDT_PROBE1(time, linux_clock_settime, return, error); 399 return (error); 400} 401 402int 403linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args) 404{ 405 struct proc *p; 406 struct timespec ts; 407 struct l_timespec lts; 408 int error, clockwhich; 409 clockid_t nwhich = 0; /* XXX: GCC */ 410 pid_t pid; 411 lwpid_t tid; 412 413 LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp); 414 415 error = linux_to_native_clockid(&nwhich, args->which); 416 if (error != 0) { 417 LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error, 418 error); 419 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 420 return (error); 421 } 422 423 /* 424 * Check user supplied clock id in case of per-process 425 * or thread-specific cpu-time clock. 426 */ 427 switch (nwhich) { 428 case CLOCK_THREAD_CPUTIME_ID: 429 tid = LINUX_CPUCLOCK_ID(args->which); 430 if (tid != 0) { 431 p = td->td_proc; 432 if (tdfind(tid, p->p_pid) == NULL) 433 return (ESRCH); 434 PROC_UNLOCK(p); 435 } 436 break; 437 case CLOCK_PROCESS_CPUTIME_ID: 438 pid = LINUX_CPUCLOCK_ID(args->which); 439 if (pid != 0) { 440 error = pget(pid, PGET_CANSEE, &p); 441 if (error != 0) 442 return (EINVAL); 443 PROC_UNLOCK(p); 444 } 445 break; 446 } 447 448 if (args->tp == NULL) { 449 LIN_SDT_PROBE0(time, linux_clock_getres, nullcall); 450 LIN_SDT_PROBE1(time, linux_clock_getres, return, 0); 451 return (0); 452 } 453 454 switch (nwhich) { 455 case CLOCK_THREAD_CPUTIME_ID: 456 case CLOCK_PROCESS_CPUTIME_ID: 457 clockwhich = LINUX_CPUCLOCK_WHICH(args->which); 458 switch (clockwhich) { 459 case LINUX_CPUCLOCK_PROF: 460 nwhich = CLOCK_PROF; 461 break; 462 case LINUX_CPUCLOCK_VIRT: 463 nwhich = CLOCK_VIRTUAL; 464 break; 465 case LINUX_CPUCLOCK_SCHED: 466 break; 467 default: 468 return (EINVAL); 469 } 470 break; 471 472 default: 473 break; 474 } 475 error = kern_clock_getres(td, nwhich, &ts); 476 if (error != 0) { 477 LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error); 478 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 479 return (error); 480 } 481 error = native_to_linux_timespec(<s, &ts); 482 if (error != 0) 483 return (error); 484 error = copyout(<s, args->tp, sizeof lts); 485 if (error != 0) 486 LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error); 487 488 LIN_SDT_PROBE1(time, linux_clock_getres, return, error); 489 return (error); 490} 491 492int 493linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args) 494{ 495 struct timespec *rmtp; 496 struct l_timespec lrqts, lrmts; 497 struct timespec rqts, rmts; 498 int error, error2; 499 500 LIN_SDT_PROBE2(time, linux_nanosleep, entry, args->rqtp, args->rmtp); 501 502 error = copyin(args->rqtp, &lrqts, sizeof lrqts); 503 if (error != 0) { 504 LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error); 505 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 506 return (error); 507 } 508 509 if (args->rmtp != NULL) 510 rmtp = &rmts; 511 else 512 rmtp = NULL; 513 514 error = linux_to_native_timespec(&rqts, &lrqts); 515 if (error != 0) { 516 LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error); 517 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 518 return (error); 519 } 520 error = kern_nanosleep(td, &rqts, rmtp); 521 if (error == EINTR && args->rmtp != NULL) { 522 error2 = native_to_linux_timespec(&lrmts, rmtp); 523 if (error2 != 0) 524 return (error2); 525 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 526 if (error2 != 0) { 527 LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error, 528 error2); 529 LIN_SDT_PROBE1(time, linux_nanosleep, return, error2); 530 return (error2); 531 } 532 } 533 534 LIN_SDT_PROBE1(time, linux_nanosleep, return, error); 535 return (error); 536} 537 538int 539linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args) 540{ 541 struct timespec *rmtp; 542 struct l_timespec lrqts, lrmts; 543 struct timespec rqts, rmts; 544 int error, error2; 545 546 LIN_SDT_PROBE4(time, linux_clock_nanosleep, entry, args->which, 547 args->flags, args->rqtp, args->rmtp); 548 549 if (args->flags != 0) { 550 /* XXX deal with TIMER_ABSTIME */ 551 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_flags, 552 args->flags); 553 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL); 554 return (EINVAL); /* XXX deal with TIMER_ABSTIME */ 555 } 556 557 if (args->which != LINUX_CLOCK_REALTIME) { 558 LIN_SDT_PROBE1(time, linux_clock_nanosleep, unsupported_clockid, 559 args->which); 560 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, EINVAL); 561 return (EINVAL); 562 } 563 564 error = copyin(args->rqtp, &lrqts, sizeof(lrqts)); 565 if (error != 0) { 566 LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error, 567 error); 568 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 569 return (error); 570 } 571 572 if (args->rmtp != NULL) 573 rmtp = &rmts; 574 else 575 rmtp = NULL; 576 577 error = linux_to_native_timespec(&rqts, &lrqts); 578 if (error != 0) { 579 LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error, 580 error); 581 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 582 return (error); 583 } 584 error = kern_nanosleep(td, &rqts, rmtp); 585 if (error == EINTR && args->rmtp != NULL) { 586 /* XXX. Not for TIMER_ABSTIME */ 587 error2 = native_to_linux_timespec(&lrmts, rmtp); 588 if (error2 != 0) 589 return (error2); 590 error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts)); 591 if (error2 != 0) { 592 LIN_SDT_PROBE1(time, linux_clock_nanosleep, 593 copyout_error, error2); 594 LIN_SDT_PROBE1(time, linux_clock_nanosleep, 595 return, error2); 596 return (error2); 597 } 598 } 599 600 LIN_SDT_PROBE1(time, linux_clock_nanosleep, return, error); 601 return (error); 602} 603