1 /* $NetBSD: kern_time_50.c,v 1.8 2009/07/19 02:41:27 rmind Exp $ */ 2 3 /*- 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 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 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: kern_time_50.c,v 1.8 2009/07/19 02:41:27 rmind Exp $"); 33 34 #ifdef _KERNEL_OPT 35 #include "opt_aio.h" 36 #include "opt_ntp.h" 37 #include "opt_mqueue.h" 38 #endif 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/namei.h> 43 #include <sys/filedesc.h> 44 #include <sys/kernel.h> 45 #include <sys/file.h> 46 #include <sys/stat.h> 47 #include <sys/socketvar.h> 48 #include <sys/vnode.h> 49 #include <sys/mount.h> 50 #include <sys/proc.h> 51 #include <sys/uio.h> 52 #include <sys/dirent.h> 53 #include <sys/malloc.h> 54 #include <sys/kauth.h> 55 #include <sys/time.h> 56 #include <sys/timex.h> 57 #include <sys/timetc.h> 58 #include <sys/aio.h> 59 #include <sys/poll.h> 60 #include <sys/syscallargs.h> 61 #include <sys/resource.h> 62 63 #include <compat/common/compat_util.h> 64 #include <compat/sys/time.h> 65 #include <compat/sys/timex.h> 66 #include <compat/sys/resource.h> 67 #include <compat/sys/clockctl.h> 68 69 static int 70 compat_50_kevent_fetch_timeout(const void *src, void *dest, size_t length) 71 { 72 struct timespec50 ts50; 73 int error; 74 75 KASSERT(length == sizeof(struct timespec)); 76 77 error = copyin(src, &ts50, sizeof(ts50)); 78 if (error) 79 return error; 80 timespec50_to_timespec(&ts50, (struct timespec *)dest); 81 return 0; 82 } 83 84 int 85 compat_50_sys_kevent(struct lwp *l, const struct compat_50_sys_kevent_args *uap, 86 register_t *retval) 87 { 88 /* { 89 syscallarg(int) fd; 90 syscallarg(keventp_t) changelist; 91 syscallarg(size_t) nchanges; 92 syscallarg(keventp_t) eventlist; 93 syscallarg(size_t) nevents; 94 syscallarg(struct timespec50) timeout; 95 } */ 96 static const struct kevent_ops compat_50_kevent_ops = { 97 .keo_private = NULL, 98 .keo_fetch_timeout = compat_50_kevent_fetch_timeout, 99 .keo_fetch_changes = kevent_fetch_changes, 100 .keo_put_events = kevent_put_events, 101 }; 102 103 return kevent1(retval, SCARG(uap, fd), SCARG(uap, changelist), 104 SCARG(uap, nchanges), SCARG(uap, eventlist), SCARG(uap, nevents), 105 (const struct timespec *)(const void *)SCARG(uap, timeout), 106 &compat_50_kevent_ops); 107 } 108 109 int 110 compat_50_sys_clock_gettime(struct lwp *l, 111 const struct compat_50_sys_clock_gettime_args *uap, register_t *retval) 112 { 113 /* { 114 syscallarg(clockid_t) clock_id; 115 syscallarg(struct timespec50 *) tp; 116 } */ 117 clockid_t clock_id; 118 struct timespec ats; 119 struct timespec50 ats50; 120 121 clock_id = SCARG(uap, clock_id); 122 switch (clock_id) { 123 case CLOCK_REALTIME: 124 nanotime(&ats); 125 break; 126 case CLOCK_MONOTONIC: 127 nanouptime(&ats); 128 break; 129 default: 130 return (EINVAL); 131 } 132 timespec_to_timespec50(&ats, &ats50); 133 134 return copyout(&ats50, SCARG(uap, tp), sizeof(ats50)); 135 } 136 137 /* ARGSUSED */ 138 int 139 compat_50_sys_clock_settime(struct lwp *l, 140 const struct compat_50_sys_clock_settime_args *uap, register_t *retval) 141 { 142 /* { 143 syscallarg(clockid_t) clock_id; 144 syscallarg(const struct timespec50 *) tp; 145 } */ 146 int error; 147 struct timespec ats; 148 struct timespec50 ats50; 149 150 error = copyin(SCARG(uap, tp), &ats50, sizeof(ats50)); 151 if (error) 152 return error; 153 timespec50_to_timespec(&ats50, &ats); 154 155 return clock_settime1(l->l_proc, SCARG(uap, clock_id), &ats, 156 true); 157 } 158 159 160 int 161 compat_50_sys_clock_getres(struct lwp *l, 162 const struct compat_50_sys_clock_getres_args *uap, register_t *retval) 163 { 164 /* { 165 syscallarg(clockid_t) clock_id; 166 syscallarg(struct timespec50 *) tp; 167 } */ 168 clockid_t clock_id; 169 struct timespec50 ats50; 170 int error = 0; 171 172 clock_id = SCARG(uap, clock_id); 173 switch (clock_id) { 174 case CLOCK_REALTIME: 175 case CLOCK_MONOTONIC: 176 ats50.tv_sec = 0; 177 if (tc_getfrequency() > 1000000000) 178 ats50.tv_nsec = 1; 179 else 180 ats50.tv_nsec = 1000000000 / tc_getfrequency(); 181 break; 182 default: 183 return (EINVAL); 184 } 185 186 if (SCARG(uap, tp)) 187 error = copyout(&ats50, SCARG(uap, tp), sizeof(*SCARG(uap, tp))); 188 189 return error; 190 } 191 192 /* ARGSUSED */ 193 int 194 compat_50_sys_nanosleep(struct lwp *l, 195 const struct compat_50_sys_nanosleep_args *uap, register_t *retval) 196 { 197 /* { 198 syscallarg(struct timespec50 *) rqtp; 199 syscallarg(struct timespec50 *) rmtp; 200 } */ 201 struct timespec rmt, rqt; 202 struct timespec50 rmt50, rqt50; 203 int error, error1; 204 205 error = copyin(SCARG(uap, rqtp), &rqt50, sizeof(rqt50)); 206 if (error) 207 return error; 208 timespec50_to_timespec(&rqt50, &rqt); 209 210 error = nanosleep1(l, &rqt, SCARG(uap, rmtp) ? &rmt : NULL); 211 if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) 212 return error; 213 214 timespec_to_timespec50(&rmt, &rmt50); 215 error1 = copyout(&rmt50, SCARG(uap, rmtp), sizeof(*SCARG(uap, rmtp))); 216 return error1 ? error1 : error; 217 } 218 219 /* ARGSUSED */ 220 int 221 compat_50_sys_gettimeofday(struct lwp *l, 222 const struct compat_50_sys_gettimeofday_args *uap, register_t *retval) 223 { 224 /* { 225 syscallarg(struct timeval50 *) tp; 226 syscallarg(void *) tzp; really "struct timezone *"; 227 } */ 228 struct timeval atv; 229 struct timeval50 atv50; 230 int error = 0; 231 struct timezone tzfake; 232 233 if (SCARG(uap, tp)) { 234 microtime(&atv); 235 timeval_to_timeval50(&atv, &atv50); 236 error = copyout(&atv50, SCARG(uap, tp), sizeof(*SCARG(uap, tp))); 237 if (error) 238 return error; 239 } 240 if (SCARG(uap, tzp)) { 241 /* 242 * NetBSD has no kernel notion of time zone, so we just 243 * fake up a timezone struct and return it if demanded. 244 */ 245 tzfake.tz_minuteswest = 0; 246 tzfake.tz_dsttime = 0; 247 error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake)); 248 } 249 return error; 250 } 251 252 /* ARGSUSED */ 253 int 254 compat_50_sys_settimeofday(struct lwp *l, 255 const struct compat_50_sys_settimeofday_args *uap, register_t *retval) 256 { 257 /* { 258 syscallarg(const struct timeval50 *) tv; 259 syscallarg(const void *) tzp; really "const struct timezone *"; 260 } */ 261 struct timeval50 atv50; 262 struct timeval atv; 263 int error = copyin(SCARG(uap, tv), &atv50, sizeof(atv50)); 264 if (error) 265 return error; 266 timeval50_to_timeval(&atv50, &atv); 267 return settimeofday1(&atv, false, SCARG(uap, tzp), l, true); 268 } 269 270 /* ARGSUSED */ 271 int 272 compat_50_sys_adjtime(struct lwp *l, 273 const struct compat_50_sys_adjtime_args *uap, register_t *retval) 274 { 275 /* { 276 syscallarg(const struct timeval50 *) delta; 277 syscallarg(struct timeval50 *) olddelta; 278 } */ 279 int error; 280 struct timeval50 delta50, olddelta50; 281 struct timeval delta, olddelta; 282 283 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, 284 KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0) 285 return error; 286 287 if (SCARG(uap, delta)) { 288 error = copyin(SCARG(uap, delta), &delta50, 289 sizeof(*SCARG(uap, delta))); 290 if (error) 291 return (error); 292 timeval50_to_timeval(&delta50, &delta); 293 } 294 adjtime1(SCARG(uap, delta) ? &delta : NULL, 295 SCARG(uap, olddelta) ? &olddelta : NULL, l->l_proc); 296 if (SCARG(uap, olddelta)) { 297 timeval_to_timeval50(&olddelta, &olddelta50); 298 error = copyout(&olddelta50, SCARG(uap, olddelta), 299 sizeof(*SCARG(uap, olddelta))); 300 } 301 return error; 302 } 303 304 /* BSD routine to set/arm an interval timer. */ 305 /* ARGSUSED */ 306 int 307 compat_50_sys_getitimer(struct lwp *l, 308 const struct compat_50_sys_getitimer_args *uap, register_t *retval) 309 { 310 /* { 311 syscallarg(int) which; 312 syscallarg(struct itimerval50 *) itv; 313 } */ 314 struct proc *p = l->l_proc; 315 struct itimerval aitv; 316 struct itimerval50 aitv50; 317 int error; 318 319 error = dogetitimer(p, SCARG(uap, which), &aitv); 320 if (error) 321 return error; 322 itimerval_to_itimerval50(&aitv, &aitv50); 323 return copyout(&aitv50, SCARG(uap, itv), sizeof(*SCARG(uap, itv))); 324 } 325 326 int 327 compat_50_sys_setitimer(struct lwp *l, 328 const struct compat_50_sys_setitimer_args *uap, register_t *retval) 329 { 330 /* { 331 syscallarg(int) which; 332 syscallarg(const struct itimerval50 *) itv; 333 syscallarg(struct itimerval50 *) oitv; 334 } */ 335 struct proc *p = l->l_proc; 336 int which = SCARG(uap, which); 337 struct compat_50_sys_getitimer_args getargs; 338 const struct itimerval50 *itvp; 339 struct itimerval50 aitv50; 340 struct itimerval aitv; 341 int error; 342 343 if ((u_int)which > ITIMER_PROF) 344 return (EINVAL); 345 itvp = SCARG(uap, itv); 346 if (itvp && 347 (error = copyin(itvp, &aitv50, sizeof(aitv50)) != 0)) 348 return (error); 349 itimerval50_to_itimerval(&aitv50, &aitv); 350 if (SCARG(uap, oitv) != NULL) { 351 SCARG(&getargs, which) = which; 352 SCARG(&getargs, itv) = SCARG(uap, oitv); 353 if ((error = compat_50_sys_getitimer(l, &getargs, retval)) != 0) 354 return (error); 355 } 356 if (itvp == 0) 357 return (0); 358 359 return dosetitimer(p, which, &aitv); 360 } 361 362 int 363 compat_50_sys_aio_suspend(struct lwp *l, 364 const struct compat_50_sys_aio_suspend_args *uap, register_t *retval) 365 { 366 /* { 367 syscallarg(const struct aiocb *const[]) list; 368 syscallarg(int) nent; 369 syscallarg(const struct timespec50 *) timeout; 370 } */ 371 #ifdef AIO 372 struct aiocb **list; 373 struct timespec ts; 374 struct timespec50 ts50; 375 int error, nent; 376 377 nent = SCARG(uap, nent); 378 if (nent <= 0 || nent > aio_listio_max) 379 return EAGAIN; 380 381 if (SCARG(uap, timeout)) { 382 /* Convert timespec to ticks */ 383 error = copyin(SCARG(uap, timeout), &ts50, 384 sizeof(*SCARG(uap, timeout))); 385 if (error) 386 return error; 387 timespec50_to_timespec(&ts50, &ts); 388 } 389 list = kmem_zalloc(nent * sizeof(struct aio_job), KM_SLEEP); 390 error = copyin(SCARG(uap, list), list, nent * sizeof(struct aiocb)); 391 if (error) 392 goto out; 393 error = aio_suspend1(l, list, nent, SCARG(uap, timeout) ? &ts : NULL); 394 out: 395 kmem_free(list, nent * sizeof(struct aio_job)); 396 return error; 397 #else 398 return ENOSYS; 399 #endif 400 } 401 402 int 403 compat_50_sys_select(struct lwp *l, const struct compat_50_sys_select_args *uap, register_t *retval) 404 { 405 /* { 406 syscallarg(int) nd; 407 syscallarg(fd_set *) in; 408 syscallarg(fd_set *) ou; 409 syscallarg(fd_set *) ex; 410 syscallarg(struct timeval50 *) tv; 411 } */ 412 struct timespec ats, *ts = NULL; 413 struct timeval50 atv50; 414 int error; 415 416 if (SCARG(uap, tv)) { 417 error = copyin(SCARG(uap, tv), (void *)&atv50, sizeof(atv50)); 418 if (error) 419 return error; 420 ats.tv_sec = atv50.tv_sec; 421 ats.tv_nsec = atv50.tv_usec * 1000; 422 ts = &ats; 423 } 424 425 return selcommon(l, retval, SCARG(uap, nd), SCARG(uap, in), 426 SCARG(uap, ou), SCARG(uap, ex), ts, NULL); 427 } 428 429 int 430 compat_50_sys_pselect(struct lwp *l, 431 const struct compat_50_sys_pselect_args *uap, register_t *retval) 432 { 433 /* { 434 syscallarg(int) nd; 435 syscallarg(fd_set *) in; 436 syscallarg(fd_set *) ou; 437 syscallarg(fd_set *) ex; 438 syscallarg(const struct timespec50 *) ts; 439 syscallarg(sigset_t *) mask; 440 } */ 441 struct timespec50 ats50; 442 struct timespec ats, *ts = NULL; 443 sigset_t amask, *mask = NULL; 444 int error; 445 446 if (SCARG(uap, ts)) { 447 error = copyin(SCARG(uap, ts), &ats50, sizeof(ats50)); 448 if (error) 449 return error; 450 timespec50_to_timespec(&ats50, &ats); 451 ts = &ats; 452 } 453 if (SCARG(uap, mask) != NULL) { 454 error = copyin(SCARG(uap, mask), &amask, sizeof(amask)); 455 if (error) 456 return error; 457 mask = &amask; 458 } 459 460 return selcommon(l, retval, SCARG(uap, nd), SCARG(uap, in), 461 SCARG(uap, ou), SCARG(uap, ex), ts, mask); 462 } 463 int 464 compat_50_sys_pollts(struct lwp *l, const struct compat_50_sys_pollts_args *uap, 465 register_t *retval) 466 { 467 /* { 468 syscallarg(struct pollfd *) fds; 469 syscallarg(u_int) nfds; 470 syscallarg(const struct timespec50 *) ts; 471 syscallarg(const sigset_t *) mask; 472 } */ 473 struct timespec ats, *ts = NULL; 474 struct timespec50 ats50; 475 sigset_t amask, *mask = NULL; 476 int error; 477 478 if (SCARG(uap, ts)) { 479 error = copyin(SCARG(uap, ts), &ats50, sizeof(ats50)); 480 if (error) 481 return error; 482 timespec50_to_timespec(&ats50, &ats); 483 ts = &ats; 484 } 485 if (SCARG(uap, mask)) { 486 error = copyin(SCARG(uap, mask), &amask, sizeof(amask)); 487 if (error) 488 return error; 489 mask = &amask; 490 } 491 492 return pollcommon(l, retval, SCARG(uap, fds), SCARG(uap, nfds), 493 ts, mask); 494 } 495 496 int 497 compat_50_sys__lwp_park(struct lwp *l, 498 const struct compat_50_sys__lwp_park_args *uap, register_t *retval) 499 { 500 /* { 501 syscallarg(const struct timespec50 *) ts; 502 syscallarg(lwpid_t) unpark; 503 syscallarg(const void *) hint; 504 syscallarg(const void *) unparkhint; 505 } */ 506 struct timespec ts, *tsp; 507 struct timespec50 ts50; 508 int error; 509 510 if (SCARG(uap, ts) == NULL) 511 tsp = NULL; 512 else { 513 error = copyin(SCARG(uap, ts), &ts50, sizeof(ts50)); 514 if (error != 0) 515 return error; 516 timespec50_to_timespec(&ts50, &ts); 517 tsp = &ts; 518 } 519 520 if (SCARG(uap, unpark) != 0) { 521 error = lwp_unpark(SCARG(uap, unpark), SCARG(uap, unparkhint)); 522 if (error != 0) 523 return error; 524 } 525 526 return lwp_park(tsp, SCARG(uap, hint)); 527 } 528 529 int 530 compat_50_sys_mq_timedsend(struct lwp *l, 531 const struct compat_50_sys_mq_timedsend_args *uap, register_t *retval) 532 { 533 /* { 534 syscallarg(mqd_t) mqdes; 535 syscallarg(const char *) msg_ptr; 536 syscallarg(size_t) msg_len; 537 syscallarg(unsigned) msg_prio; 538 syscallarg(const struct timespec50 *) abs_timeout; 539 } */ 540 #ifdef MQUEUE 541 int t; 542 int error; 543 struct timespec50 ts50; 544 struct timespec ts; 545 546 /* Get and convert time value */ 547 if (SCARG(uap, abs_timeout)) { 548 error = copyin(SCARG(uap, abs_timeout), &ts50, sizeof(ts50)); 549 if (error) 550 return error; 551 timespec50_to_timespec(&ts50, &ts); 552 error = abstimeout2timo(&ts, &t); 553 if (error) 554 return error; 555 } else 556 t = 0; 557 558 return mq_send1(l, SCARG(uap, mqdes), SCARG(uap, msg_ptr), 559 SCARG(uap, msg_len), SCARG(uap, msg_prio), t); 560 #else 561 return ENOSYS; 562 #endif 563 } 564 565 int 566 compat_50_sys_mq_timedreceive(struct lwp *l, 567 const struct compat_50_sys_mq_timedreceive_args *uap, register_t *retval) 568 { 569 /* { 570 syscallarg(mqd_t) mqdes; 571 syscallarg(char *) msg_ptr; 572 syscallarg(size_t) msg_len; 573 syscallarg(unsigned *) msg_prio; 574 syscallarg(const struct timespec50 *) abs_timeout; 575 } */ 576 #ifdef MQUEUE 577 int error, t; 578 ssize_t mlen; 579 struct timespec ts; 580 struct timespec50 ts50; 581 582 /* Get and convert time value */ 583 if (SCARG(uap, abs_timeout)) { 584 error = copyin(SCARG(uap, abs_timeout), &ts50, sizeof(ts50)); 585 if (error) 586 return error; 587 588 timespec50_to_timespec(&ts50, &ts); 589 error = abstimeout2timo(&ts, &t); 590 if (error) 591 return error; 592 } else 593 t = 0; 594 595 error = mq_receive1(l, SCARG(uap, mqdes), SCARG(uap, msg_ptr), 596 SCARG(uap, msg_len), SCARG(uap, msg_prio), t, &mlen); 597 if (error == 0) 598 *retval = mlen; 599 600 return error; 601 #else 602 return ENOSYS; 603 #endif 604 } 605 606 static int 607 tscopyin(const void *u, void *s, size_t len) 608 { 609 struct timespec50 ts50; 610 KASSERT(len == sizeof(ts50)); 611 int error = copyin(u, &ts50, len); 612 if (error) 613 return error; 614 timespec50_to_timespec(&ts50, s); 615 return 0; 616 } 617 618 static int 619 tscopyout(const void *s, void *u, size_t len) 620 { 621 struct timespec50 ts50; 622 KASSERT(len == sizeof(ts50)); 623 timespec_to_timespec50(s, &ts50); 624 int error = copyout(&ts50, u, len); 625 if (error) 626 return error; 627 return 0; 628 } 629 630 int 631 compat_50_sys___sigtimedwait(struct lwp *l, 632 const struct compat_50_sys___sigtimedwait_args *uap, register_t *retval) 633 { 634 635 return __sigtimedwait1(l, 636 (const struct sys_____sigtimedwait50_args *)uap, retval, copyout, 637 tscopyin, tscopyout); 638 } 639 640 void 641 rusage_to_rusage50(const struct rusage *ru, struct rusage50 *ru50) 642 { 643 (void)memcpy(&ru50->ru_first, &ru->ru_first, 644 (char *)&ru50->ru_last - (char *)&ru50->ru_first + 645 sizeof(ru50->ru_last)); 646 ru50->ru_maxrss = ru->ru_maxrss; 647 timeval_to_timeval50(&ru->ru_utime, &ru50->ru_utime); 648 timeval_to_timeval50(&ru->ru_stime, &ru50->ru_stime); 649 } 650 651 int 652 compat_50_sys_getrusage(struct lwp *l, 653 const struct compat_50_sys_getrusage_args *uap, register_t *retval) 654 { 655 /* { 656 syscallarg(int) who; 657 syscallarg(struct rusage50 *) rusage; 658 } */ 659 struct rusage ru; 660 struct rusage50 ru50; 661 struct proc *p = l->l_proc; 662 663 switch (SCARG(uap, who)) { 664 case RUSAGE_SELF: 665 mutex_enter(p->p_lock); 666 memcpy(&ru, &p->p_stats->p_ru, sizeof(ru)); 667 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL); 668 mutex_exit(p->p_lock); 669 break; 670 671 case RUSAGE_CHILDREN: 672 mutex_enter(p->p_lock); 673 memcpy(&ru, &p->p_stats->p_cru, sizeof(ru)); 674 mutex_exit(p->p_lock); 675 break; 676 677 default: 678 return EINVAL; 679 } 680 rusage_to_rusage50(&ru, &ru50); 681 return copyout(&ru50, SCARG(uap, rusage), sizeof(ru50)); 682 } 683 684 685 /* Return the time remaining until a POSIX timer fires. */ 686 int 687 compat_50_sys_timer_gettime(struct lwp *l, 688 const struct compat_50_sys_timer_gettime_args *uap, register_t *retval) 689 { 690 /* { 691 syscallarg(timer_t) timerid; 692 syscallarg(struct itimerspec50 *) value; 693 } */ 694 struct itimerspec its; 695 struct itimerspec50 its50; 696 int error; 697 698 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, 699 &its)) != 0) 700 return error; 701 itimerspec_to_itimerspec50(&its, &its50); 702 703 return copyout(&its50, SCARG(uap, value), sizeof(its50)); 704 } 705 706 /* Set and arm a POSIX realtime timer */ 707 int 708 compat_50_sys_timer_settime(struct lwp *l, 709 const struct compat_50_sys_timer_settime_args *uap, register_t *retval) 710 { 711 /* { 712 syscallarg(timer_t) timerid; 713 syscallarg(int) flags; 714 syscallarg(const struct itimerspec50 *) value; 715 syscallarg(struct itimerspec50 *) ovalue; 716 } */ 717 int error; 718 struct itimerspec value, ovalue, *ovp = NULL; 719 struct itimerspec50 value50, ovalue50; 720 721 if ((error = copyin(SCARG(uap, value), &value50, sizeof(value50))) != 0) 722 return error; 723 724 itimerspec50_to_itimerspec(&value50, &value); 725 if (SCARG(uap, ovalue)) 726 ovp = &ovalue; 727 728 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp, 729 SCARG(uap, flags), l->l_proc)) != 0) 730 return error; 731 732 if (ovp) { 733 itimerspec_to_itimerspec50(&ovalue, &ovalue50); 734 return copyout(&ovalue50, SCARG(uap, ovalue), sizeof(ovalue50)); 735 } 736 return 0; 737 } 738 739 /* 740 * ntp_gettime() - NTP user application interface 741 */ 742 int 743 compat_50_sys___ntp_gettime30(struct lwp *l, 744 const struct compat_50_sys___ntp_gettime30_args *uap, register_t *retval) 745 { 746 #ifdef NTP 747 /* { 748 syscallarg(struct ntptimeval *) ntvp; 749 } */ 750 struct ntptimeval ntv; 751 struct ntptimeval50 ntv50; 752 int error; 753 754 if (SCARG(uap, ntvp)) { 755 ntp_gettime(&ntv); 756 timespec_to_timespec50(&ntv.time, &ntv50.time); 757 ntv50.maxerror = ntv.maxerror; 758 ntv50.esterror = ntv.esterror; 759 ntv50.tai = ntv.tai; 760 ntv50.time_state = ntv.time_state; 761 762 error = copyout(&ntv50, SCARG(uap, ntvp), sizeof(ntv50)); 763 if (error) 764 return error; 765 } 766 *retval = ntp_timestatus(); 767 return 0; 768 #else 769 return ENOSYS; 770 #endif 771 } 772 int 773 compat50_clockctlioctl(dev_t dev, u_long cmd, void *data, int flags, 774 struct lwp *l) 775 { 776 int error = 0; 777 778 switch (cmd) { 779 case CLOCKCTL_OSETTIMEOFDAY: { 780 struct timeval50 tv50; 781 struct timeval tv; 782 struct clockctl50_settimeofday *args = data; 783 784 error = copyin(args->tv, &tv50, sizeof(tv50)); 785 if (error) 786 return (error); 787 timeval50_to_timeval(&tv50, &tv); 788 error = settimeofday1(&tv, false, args->tzp, l, false); 789 break; 790 } 791 case CLOCKCTL_OADJTIME: { 792 struct timeval atv, oldatv; 793 struct timeval50 atv50; 794 struct clockctl50_adjtime *args = data; 795 796 if (args->delta) { 797 error = copyin(args->delta, &atv50, sizeof(atv50)); 798 if (error) 799 return (error); 800 timeval50_to_timeval(&atv50, &atv); 801 } 802 adjtime1(args->delta ? &atv : NULL, 803 args->olddelta ? &oldatv : NULL, l->l_proc); 804 if (args->olddelta) { 805 timeval_to_timeval50(&oldatv, &atv50); 806 error = copyout(&atv50, args->olddelta, sizeof(atv50)); 807 } 808 break; 809 } 810 case CLOCKCTL_OCLOCK_SETTIME: { 811 struct timespec50 tp50; 812 struct timespec tp; 813 struct clockctl50_clock_settime *args = data; 814 815 error = copyin(args->tp, &tp50, sizeof(tp50)); 816 if (error) 817 return (error); 818 timespec50_to_timespec(&tp50, &tp); 819 error = clock_settime1(l->l_proc, args->clock_id, &tp, true); 820 break; 821 } 822 default: 823 error = EINVAL; 824 } 825 826 return (error); 827 } 828 int 829 compat_50_sys_wait4(struct lwp *l, const struct compat_50_sys_wait4_args *uap, register_t *retval) 830 { 831 /* { 832 syscallarg(int) pid; 833 syscallarg(int *) status; 834 syscallarg(int) options; 835 syscallarg(struct rusage50 *) rusage; 836 } */ 837 int status, error; 838 int was_zombie; 839 struct rusage ru; 840 struct rusage50 ru50; 841 int pid = SCARG(uap, pid); 842 843 error = do_sys_wait(l, &pid, &status, SCARG(uap, options), 844 SCARG(uap, rusage) != NULL ? &ru : NULL, &was_zombie); 845 846 retval[0] = pid; 847 if (pid == 0) 848 return error; 849 850 if (SCARG(uap, rusage)) { 851 rusage_to_rusage50(&ru, &ru50); 852 error = copyout(&ru50, SCARG(uap, rusage), sizeof(ru50)); 853 } 854 855 if (error == 0 && SCARG(uap, status)) 856 error = copyout(&status, SCARG(uap, status), sizeof(status)); 857 858 return error; 859 } 860