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