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