1 /* $NetBSD: netbsd32_time.c,v 1.18 2005/12/06 13:37:35 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1998, 2001 Matthew R. Green 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: netbsd32_time.c,v 1.18 2005/12/06 13:37:35 christos Exp $"); 33 34 #if defined(_KERNEL_OPT) 35 #include "opt_ntp.h" 36 #endif 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/mount.h> 41 #include <sys/time.h> 42 #include <sys/timex.h> 43 #include <sys/timevar.h> 44 #include <sys/proc.h> 45 #include <sys/pool.h> 46 #include <sys/resourcevar.h> 47 #include <sys/dirent.h> 48 49 #include <compat/netbsd32/netbsd32.h> 50 #include <compat/netbsd32/netbsd32_syscallargs.h> 51 #include <compat/netbsd32/netbsd32_conv.h> 52 53 #ifdef NTP 54 int 55 netbsd32_ntp_gettime(l, v, retval) 56 struct lwp *l; 57 void *v; 58 register_t *retval; 59 { 60 struct netbsd32_ntp_gettime_args /* { 61 syscallarg(netbsd32_ntptimevalp_t) ntvp; 62 } */ *uap = v; 63 struct netbsd32_ntptimeval ntv32; 64 struct timeval atv; 65 struct ntptimeval ntv; 66 int error = 0; 67 int s; 68 69 /* The following are NTP variables */ 70 extern long time_maxerror; 71 extern long time_esterror; 72 extern int time_status; 73 extern int time_state; /* clock state */ 74 extern int time_status; /* clock status bits */ 75 76 if (SCARG(uap, ntvp)) { 77 s = splclock(); 78 #ifdef EXT_CLOCK 79 /* 80 * The microtime() external clock routine returns a 81 * status code. If less than zero, we declare an error 82 * in the clock status word and return the kernel 83 * (software) time variable. While there are other 84 * places that call microtime(), this is the only place 85 * that matters from an application point of view. 86 */ 87 if (microtime(&atv) < 0) { 88 time_status |= STA_CLOCKERR; 89 ntv.time = time; 90 } else 91 time_status &= ~STA_CLOCKERR; 92 #else /* EXT_CLOCK */ 93 microtime(&atv); 94 #endif /* EXT_CLOCK */ 95 ntv.time = atv; 96 ntv.maxerror = time_maxerror; 97 ntv.esterror = time_esterror; 98 (void) splx(s); 99 100 netbsd32_from_timeval(&ntv.time, &ntv32.time); 101 ntv32.maxerror = (netbsd32_long)ntv.maxerror; 102 ntv32.esterror = (netbsd32_long)ntv.esterror; 103 error = copyout((caddr_t)&ntv32, 104 (caddr_t)NETBSD32PTR64(SCARG(uap, ntvp)), sizeof(ntv32)); 105 } 106 if (!error) { 107 108 /* 109 * Status word error decode. If any of these conditions 110 * occur, an error is returned, instead of the status 111 * word. Most applications will care only about the fact 112 * the system clock may not be trusted, not about the 113 * details. 114 * 115 * Hardware or software error 116 */ 117 if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || 118 119 /* 120 * PPS signal lost when either time or frequency 121 * synchronization requested 122 */ 123 (time_status & (STA_PPSFREQ | STA_PPSTIME) && 124 !(time_status & STA_PPSSIGNAL)) || 125 126 /* 127 * PPS jitter exceeded when time synchronization 128 * requested 129 */ 130 (time_status & STA_PPSTIME && 131 time_status & STA_PPSJITTER) || 132 133 /* 134 * PPS wander exceeded or calibration error when 135 * frequency synchronization requested 136 */ 137 (time_status & STA_PPSFREQ && 138 time_status & (STA_PPSWANDER | STA_PPSERROR))) 139 *retval = TIME_ERROR; 140 else 141 *retval = time_state; 142 } 143 return (error); 144 } 145 146 int 147 netbsd32_ntp_adjtime(l, v, retval) 148 struct lwp *l; 149 void *v; 150 register_t *retval; 151 { 152 struct netbsd32_ntp_adjtime_args /* { 153 syscallarg(netbsd32_timexp_t) tp; 154 } */ *uap = v; 155 struct netbsd32_timex ntv32; 156 struct timex ntv; 157 int error = 0; 158 int modes; 159 int s; 160 struct proc *p = l->l_proc; 161 extern long time_freq; /* frequency offset (scaled ppm) */ 162 extern long time_maxerror; 163 extern long time_esterror; 164 extern int time_state; /* clock state */ 165 extern int time_status; /* clock status bits */ 166 extern long time_constant; /* pll time constant */ 167 extern long time_offset; /* time offset (us) */ 168 extern long time_tolerance; /* frequency tolerance (scaled ppm) */ 169 extern long time_precision; /* clock precision (us) */ 170 171 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 172 (caddr_t)&ntv32, sizeof(ntv32)))) 173 return (error); 174 netbsd32_to_timex(&ntv32, &ntv); 175 176 /* 177 * Update selected clock variables - only the superuser can 178 * change anything. Note that there is no error checking here on 179 * the assumption the superuser should know what it is doing. 180 */ 181 modes = ntv.modes; 182 if (modes != 0 && (error = suser(p->p_ucred, &p->p_acflag))) 183 return (error); 184 185 s = splclock(); 186 if (modes & MOD_FREQUENCY) 187 #ifdef PPS_SYNC 188 time_freq = ntv.freq - pps_freq; 189 #else /* PPS_SYNC */ 190 time_freq = ntv.freq; 191 #endif /* PPS_SYNC */ 192 if (modes & MOD_MAXERROR) 193 time_maxerror = ntv.maxerror; 194 if (modes & MOD_ESTERROR) 195 time_esterror = ntv.esterror; 196 if (modes & MOD_STATUS) { 197 time_status &= STA_RONLY; 198 time_status |= ntv.status & ~STA_RONLY; 199 } 200 if (modes & MOD_TIMECONST) 201 time_constant = ntv.constant; 202 if (modes & MOD_OFFSET) 203 hardupdate(ntv.offset); 204 205 /* 206 * Retrieve all clock variables 207 */ 208 if (time_offset < 0) 209 ntv.offset = -(-time_offset >> SHIFT_UPDATE); 210 else 211 ntv.offset = time_offset >> SHIFT_UPDATE; 212 #ifdef PPS_SYNC 213 ntv.freq = time_freq + pps_freq; 214 #else /* PPS_SYNC */ 215 ntv.freq = time_freq; 216 #endif /* PPS_SYNC */ 217 ntv.maxerror = time_maxerror; 218 ntv.esterror = time_esterror; 219 ntv.status = time_status; 220 ntv.constant = time_constant; 221 ntv.precision = time_precision; 222 ntv.tolerance = time_tolerance; 223 #ifdef PPS_SYNC 224 ntv.shift = pps_shift; 225 ntv.ppsfreq = pps_freq; 226 ntv.jitter = pps_jitter >> PPS_AVG; 227 ntv.stabil = pps_stabil; 228 ntv.calcnt = pps_calcnt; 229 ntv.errcnt = pps_errcnt; 230 ntv.jitcnt = pps_jitcnt; 231 ntv.stbcnt = pps_stbcnt; 232 #endif /* PPS_SYNC */ 233 (void)splx(s); 234 235 netbsd32_from_timex(&ntv, &ntv32); 236 error = copyout((caddr_t)&ntv32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 237 sizeof(ntv32)); 238 if (!error) { 239 240 /* 241 * Status word error decode. See comments in 242 * ntp_gettime() routine. 243 */ 244 if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || 245 (time_status & (STA_PPSFREQ | STA_PPSTIME) && 246 !(time_status & STA_PPSSIGNAL)) || 247 (time_status & STA_PPSTIME && 248 time_status & STA_PPSJITTER) || 249 (time_status & STA_PPSFREQ && 250 time_status & (STA_PPSWANDER | STA_PPSERROR))) 251 *retval = TIME_ERROR; 252 else 253 *retval = time_state; 254 } 255 return error; 256 } 257 #else 258 int 259 netbsd32_ntp_gettime(l, v, retval) 260 struct lwp *l; 261 void *v; 262 register_t *retval; 263 { 264 265 return (ENOSYS); 266 } 267 268 int 269 netbsd32_ntp_adjtime(l, v, retval) 270 struct lwp *l; 271 void *v; 272 register_t *retval; 273 { 274 275 return (ENOSYS); 276 } 277 #endif 278 279 int 280 netbsd32_setitimer(l, v, retval) 281 struct lwp *l; 282 void *v; 283 register_t *retval; 284 { 285 struct netbsd32_setitimer_args /* { 286 syscallarg(int) which; 287 syscallarg(const netbsd32_itimervalp_t) itv; 288 syscallarg(netbsd32_itimervalp_t) oitv; 289 } */ *uap = v; 290 struct proc *p = l->l_proc; 291 struct netbsd32_itimerval s32it, *itv32; 292 int which = SCARG(uap, which); 293 struct netbsd32_getitimer_args getargs; 294 struct itimerval aitv; 295 int error; 296 297 if ((u_int)which > ITIMER_PROF) 298 return (EINVAL); 299 itv32 = (struct netbsd32_itimerval *)NETBSD32PTR64(SCARG(uap, itv)); 300 if (itv32) { 301 if ((error = copyin(itv32, &s32it, sizeof(s32it)))) 302 return (error); 303 netbsd32_to_itimerval(&s32it, &aitv); 304 } 305 if (SCARG(uap, oitv) != 0) { 306 SCARG(&getargs, which) = which; 307 SCARG(&getargs, itv) = SCARG(uap, oitv); 308 if ((error = netbsd32_getitimer(l, &getargs, retval)) != 0) 309 return (error); 310 } 311 if (itv32 == 0) 312 return 0; 313 314 return dosetitimer(p, which, &aitv); 315 } 316 317 int 318 netbsd32_getitimer(l, v, retval) 319 struct lwp *l; 320 void *v; 321 register_t *retval; 322 { 323 struct netbsd32_getitimer_args /* { 324 syscallarg(int) which; 325 syscallarg(netbsd32_itimervalp_t) itv; 326 } */ *uap = v; 327 struct proc *p = l->l_proc; 328 struct netbsd32_itimerval s32it; 329 struct itimerval aitv; 330 int error; 331 332 error = dogetitimer(p, SCARG(uap, which), &aitv); 333 if (error) 334 return error; 335 336 netbsd32_from_itimerval(&aitv, &s32it); 337 return (copyout(&s32it, (caddr_t)NETBSD32PTR64(SCARG(uap, itv)), 338 sizeof(s32it))); 339 } 340 341 int 342 netbsd32_gettimeofday(l, v, retval) 343 struct lwp *l; 344 void *v; 345 register_t *retval; 346 { 347 struct netbsd32_gettimeofday_args /* { 348 syscallarg(netbsd32_timevalp_t) tp; 349 syscallarg(netbsd32_timezonep_t) tzp; 350 } */ *uap = v; 351 struct timeval atv; 352 struct netbsd32_timeval tv32; 353 int error = 0; 354 struct netbsd32_timezone tzfake; 355 356 if (SCARG(uap, tp)) { 357 microtime(&atv); 358 netbsd32_from_timeval(&atv, &tv32); 359 error = copyout(&tv32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 360 sizeof(tv32)); 361 if (error) 362 return (error); 363 } 364 if (SCARG(uap, tzp)) { 365 /* 366 * NetBSD has no kernel notion of time zone, so we just 367 * fake up a timezone struct and return it if demanded. 368 */ 369 tzfake.tz_minuteswest = 0; 370 tzfake.tz_dsttime = 0; 371 error = copyout(&tzfake, 372 (caddr_t)NETBSD32PTR64(SCARG(uap, tzp)), sizeof(tzfake)); 373 } 374 return (error); 375 } 376 377 int 378 netbsd32_settimeofday(l, v, retval) 379 struct lwp *l; 380 void *v; 381 register_t *retval; 382 { 383 struct netbsd32_settimeofday_args /* { 384 syscallarg(const netbsd32_timevalp_t) tv; 385 syscallarg(const netbsd32_timezonep_t) tzp; 386 } */ *uap = v; 387 struct netbsd32_timeval atv32; 388 struct timeval atv; 389 struct timespec ats; 390 int error; 391 struct proc *p = l->l_proc; 392 393 /* Verify all parameters before changing time. */ 394 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 395 return error; 396 397 /* 398 * NetBSD has no kernel notion of time zone, and only an 399 * obsolete program would try to set it, so we log a warning. 400 */ 401 if (SCARG(uap, tzp)) 402 printf("pid %d attempted to set the " 403 "(obsolete) kernel time zone\n", p->p_pid); 404 405 if (SCARG(uap, tv) == 0) 406 return 0; 407 408 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tv)), &atv32, 409 sizeof(atv32))) != 0) 410 return error; 411 412 netbsd32_to_timeval(&atv32, &atv); 413 TIMEVAL_TO_TIMESPEC(&atv, &ats); 414 return settime(p, &ats); 415 } 416 417 int 418 netbsd32_adjtime(l, v, retval) 419 struct lwp *l; 420 void *v; 421 register_t *retval; 422 { 423 struct netbsd32_adjtime_args /* { 424 syscallarg(const netbsd32_timevalp_t) delta; 425 syscallarg(netbsd32_timevalp_t) olddelta; 426 } */ *uap = v; 427 struct netbsd32_timeval atv; 428 int32_t ndelta, ntickdelta, odelta; 429 int s, error; 430 struct proc *p = l->l_proc; 431 extern long bigadj, timedelta; 432 extern int tickdelta; 433 434 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 435 return (error); 436 437 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, delta)), &atv, 438 sizeof(struct timeval)); 439 if (error) 440 return (error); 441 /* 442 * Compute the total correction and the rate at which to apply it. 443 * Round the adjustment down to a whole multiple of the per-tick 444 * delta, so that after some number of incremental changes in 445 * hardclock(), tickdelta will become zero, lest the correction 446 * overshoot and start taking us away from the desired final time. 447 */ 448 ndelta = atv.tv_sec * 1000000 + atv.tv_usec; 449 if (ndelta > bigadj) 450 ntickdelta = 10 * tickadj; 451 else 452 ntickdelta = tickadj; 453 if (ndelta % ntickdelta) 454 ndelta = ndelta / ntickdelta * ntickdelta; 455 456 /* 457 * To make hardclock()'s job easier, make the per-tick delta negative 458 * if we want time to run slower; then hardclock can simply compute 459 * tick + tickdelta, and subtract tickdelta from timedelta. 460 */ 461 if (ndelta < 0) 462 ntickdelta = -ntickdelta; 463 s = splclock(); 464 odelta = timedelta; 465 timedelta = ndelta; 466 tickdelta = ntickdelta; 467 splx(s); 468 469 if (SCARG(uap, olddelta)) { 470 atv.tv_sec = odelta / 1000000; 471 atv.tv_usec = odelta % 1000000; 472 (void) copyout(&atv, 473 (caddr_t)NETBSD32PTR64(SCARG(uap, olddelta)), sizeof(atv)); 474 } 475 return (0); 476 } 477 478 int 479 netbsd32_clock_gettime(l, v, retval) 480 struct lwp *l; 481 void *v; 482 register_t *retval; 483 { 484 struct netbsd32_clock_gettime_args /* { 485 syscallarg(netbsd32_clockid_t) clock_id; 486 syscallarg(netbsd32_timespecp_t) tp; 487 } */ *uap = v; 488 clockid_t clock_id; 489 struct timespec ats; 490 struct netbsd32_timespec ts32; 491 492 clock_id = SCARG(uap, clock_id); 493 if (clock_id != CLOCK_REALTIME) 494 return (EINVAL); 495 496 nanotime(&ats); 497 netbsd32_from_timespec(&ats, &ts32); 498 499 return copyout(&ts32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 500 sizeof(ts32)); 501 } 502 503 int 504 netbsd32_clock_settime(l, v, retval) 505 struct lwp *l; 506 void *v; 507 register_t *retval; 508 { 509 struct netbsd32_clock_settime_args /* { 510 syscallarg(netbsd32_clockid_t) clock_id; 511 syscallarg(const netbsd32_timespecp_t) tp; 512 } */ *uap = v; 513 struct netbsd32_timespec ts32; 514 clockid_t clock_id; 515 struct timespec ats; 516 int error; 517 struct proc *p = l->l_proc; 518 519 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 520 return (error); 521 522 clock_id = SCARG(uap, clock_id); 523 if (clock_id != CLOCK_REALTIME) 524 return (EINVAL); 525 526 if ((error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tp)), &ts32, 527 sizeof(ts32))) != 0) 528 return (error); 529 530 netbsd32_to_timespec(&ts32, &ats); 531 return settime(p, &ats); 532 } 533 534 int 535 netbsd32_clock_getres(l, v, retval) 536 struct lwp *l; 537 void *v; 538 register_t *retval; 539 { 540 struct netbsd32_clock_getres_args /* { 541 syscallarg(netbsd32_clockid_t) clock_id; 542 syscallarg(netbsd32_timespecp_t) tp; 543 } */ *uap = v; 544 struct netbsd32_timespec ts32; 545 clockid_t clock_id; 546 struct timespec ts; 547 int error = 0; 548 549 clock_id = SCARG(uap, clock_id); 550 if (clock_id != CLOCK_REALTIME) 551 return (EINVAL); 552 553 if (SCARG(uap, tp)) { 554 ts.tv_sec = 0; 555 ts.tv_nsec = 1000000000 / hz; 556 557 netbsd32_from_timespec(&ts, &ts32); 558 error = copyout(&ts, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)), 559 sizeof(ts)); 560 } 561 562 return error; 563 } 564 565 int 566 netbsd32_nanosleep(l, v, retval) 567 struct lwp *l; 568 void *v; 569 register_t *retval; 570 { 571 struct netbsd32_nanosleep_args /* { 572 syscallarg(const netbsd32_timespecp_t) rqtp; 573 syscallarg(netbsd32_timespecp_t) rmtp; 574 } */ *uap = v; 575 static int nanowait; 576 struct netbsd32_timespec ts32; 577 struct timespec rqt; 578 struct timespec rmt; 579 struct timeval atv, utv; 580 int error, s, timo; 581 582 error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, rqtp)), (caddr_t)&ts32, 583 sizeof(ts32)); 584 if (error) 585 return (error); 586 587 netbsd32_to_timespec(&ts32, &rqt); 588 TIMESPEC_TO_TIMEVAL(&atv,&rqt); 589 if (itimerfix(&atv)) 590 return (EINVAL); 591 592 s = splclock(); 593 timeradd(&atv,&time,&atv); 594 timo = hzto(&atv); 595 /* 596 * Avoid inadvertantly sleeping forever 597 */ 598 if (timo == 0) 599 timo = 1; 600 splx(s); 601 602 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo); 603 if (error == ERESTART) 604 error = EINTR; 605 if (error == EWOULDBLOCK) 606 error = 0; 607 608 if (SCARG(uap, rmtp)) { 609 int error1; 610 611 s = splclock(); 612 utv = time; 613 splx(s); 614 615 timersub(&atv, &utv, &utv); 616 if (utv.tv_sec < 0) 617 timerclear(&utv); 618 619 TIMEVAL_TO_TIMESPEC(&utv,&rmt); 620 netbsd32_from_timespec(&rmt, &ts32); 621 error1 = copyout(&ts32, 622 NETBSD32PTR64(SCARG(uap,rmtp)), sizeof(ts32)); 623 if (error1) 624 return (error1); 625 } 626 627 return error; 628 } 629 630 static int 631 netbsd32_timer_create_fetch(const void *src, void *dst, size_t size) 632 { 633 struct sigevent *evp = dst; 634 struct netbsd32_sigevent ev32; 635 int error; 636 637 error = copyin(src, &ev32, sizeof(ev32)); 638 if (error) 639 return error; 640 641 netbsd32_to_sigevent(&ev32, evp); 642 return 0; 643 } 644 645 int 646 netbsd32_timer_create(struct lwp *l, void *v, register_t *retval) 647 { 648 struct netbsd32_timer_create_args /* { 649 syscallarg(netbsd32_clockid_t) clock_id; 650 syscallarg(netbsd32_sigeventp_t) evp; 651 syscallarg(netbsd32_timerp_t) timerid; 652 } */ *uap = v; 653 654 return timer_create1(NETBSD32PTR64(SCARG(uap, timerid)), 655 SCARG(uap, clock_id), NETBSD32PTR64(SCARG(uap, evp)), 656 netbsd32_timer_create_fetch, l->l_proc); 657 } 658 659 int 660 netbsd32_timer_delete(struct lwp *l, void *v, register_t *retval) 661 { 662 struct netbsd32_timer_delete_args /* { 663 syscallarg(netbsd32_timer_t) timerid; 664 } */ *uap = v; 665 struct sys_timer_delete_args ua; 666 667 NETBSD32TO64_UAP(timerid); 668 return sys_timer_delete(l, (void *)&ua, retval); 669 } 670 671 int 672 netbsd32_timer_settime(struct lwp *l, void *v, register_t *retval) 673 { 674 struct netbsd32_timer_settime_args /* { 675 syscallarg(netbsd32_timer_t) timerid; 676 syscallarg(int) flags; 677 syscallarg(const netbsd32_itimerspecp_t) value; 678 syscallarg(netbsd32_itimerspecp_t) ovalue; 679 } */ *uap = v; 680 int error; 681 struct itimerspec value, ovalue, *ovp = NULL; 682 struct netbsd32_itimerspec its32; 683 684 if ((error = copyin(NETBSD32PTR64(SCARG(uap, value)), &its32, 685 sizeof(its32))) != 0) 686 return (error); 687 netbsd32_to_timespec(&its32.it_interval, &value.it_interval); 688 netbsd32_to_timespec(&its32.it_value, &value.it_value); 689 690 if (SCARG(uap, ovalue)) 691 ovp = &ovalue; 692 693 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp, 694 SCARG(uap, flags), l->l_proc)) != 0) 695 return error; 696 697 if (ovp) { 698 netbsd32_from_timespec(&ovp->it_interval, &its32.it_interval); 699 netbsd32_from_timespec(&ovp->it_value, &its32.it_value); 700 return copyout(&its32, NETBSD32PTR64(SCARG(uap, ovalue)), 701 sizeof(its32)); 702 } 703 return 0; 704 } 705 706 int 707 netbsd32_timer_gettime(struct lwp *l, void *v, register_t *retval) 708 { 709 struct netbsd32_timer_gettime_args /* { 710 syscallarg(netbsd32_timer_t) timerid; 711 syscallarg(netbsd32_itimerspecp_t) value; 712 } */ *uap = v; 713 int error; 714 struct itimerspec its; 715 struct netbsd32_itimerspec its32; 716 717 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, 718 &its)) != 0) 719 return error; 720 721 netbsd32_from_timespec(&its.it_interval, &its32.it_interval); 722 netbsd32_from_timespec(&its.it_value, &its32.it_value); 723 724 return copyout(&its32, (caddr_t)NETBSD32PTR64(SCARG(uap, value)), 725 sizeof(its32)); 726 } 727 728 int 729 netbsd32_timer_getoverrun(struct lwp *l, void *v, register_t *retval) 730 { 731 struct netbsd32_timer_getoverrun_args /* { 732 syscallarg(netbsd32_timer_t) timerid; 733 } */ *uap = v; 734 struct sys_timer_getoverrun_args ua; 735 736 NETBSD32TO64_UAP(timerid); 737 return sys_timer_getoverrun(l, (void *)&ua, retval); 738 } 739