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