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