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