Home | History | Annotate | Line # | Download | only in netbsd32
netbsd32_time.c revision 1.13
      1 /*	$NetBSD: netbsd32_time.c,v 1.13 2005/10/23 00:09:14 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.13 2005/10/23 00:09:14 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/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 	int error;
    390 	struct proc *p = l->l_proc;
    391 
    392 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    393 		return (error);
    394 	/* Verify all parameters before changing time. */
    395 	if (SCARG(uap, tv) &&
    396 	    (error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, tv)), &atv32,
    397 	    sizeof(atv32))))
    398 		return (error);
    399 	netbsd32_to_timeval(&atv32, &atv);
    400 	if (SCARG(uap, tv))
    401 		if ((error = settime(&atv)))
    402 			return (error);
    403 	/* don't bother copying the tz in, we don't use it. */
    404 	/*
    405 	 * NetBSD has no kernel notion of time zone, and only an
    406 	 * obsolete program would try to set it, so we log a warning.
    407 	 */
    408 	if (SCARG(uap, tzp))
    409 		printf("pid %d attempted to set the "
    410 		    "(obsolete) kernel time zone\n", p->p_pid);
    411 	return (0);
    412 }
    413 
    414 int
    415 netbsd32_adjtime(l, v, retval)
    416 	struct lwp *l;
    417 	void *v;
    418 	register_t *retval;
    419 {
    420 	struct netbsd32_adjtime_args /* {
    421 		syscallarg(const netbsd32_timevalp_t) delta;
    422 		syscallarg(netbsd32_timevalp_t) olddelta;
    423 	} */ *uap = v;
    424 	struct netbsd32_timeval atv;
    425 	int32_t ndelta, ntickdelta, odelta;
    426 	int s, error;
    427 	struct proc *p = l->l_proc;
    428 	extern long bigadj, timedelta;
    429 	extern int tickdelta;
    430 
    431 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    432 		return (error);
    433 
    434 	error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, delta)), &atv,
    435 	    sizeof(struct timeval));
    436 	if (error)
    437 		return (error);
    438 	/*
    439 	 * Compute the total correction and the rate at which to apply it.
    440 	 * Round the adjustment down to a whole multiple of the per-tick
    441 	 * delta, so that after some number of incremental changes in
    442 	 * hardclock(), tickdelta will become zero, lest the correction
    443 	 * overshoot and start taking us away from the desired final time.
    444 	 */
    445 	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
    446 	if (ndelta > bigadj)
    447 		ntickdelta = 10 * tickadj;
    448 	else
    449 		ntickdelta = tickadj;
    450 	if (ndelta % ntickdelta)
    451 		ndelta = ndelta / ntickdelta * ntickdelta;
    452 
    453 	/*
    454 	 * To make hardclock()'s job easier, make the per-tick delta negative
    455 	 * if we want time to run slower; then hardclock can simply compute
    456 	 * tick + tickdelta, and subtract tickdelta from timedelta.
    457 	 */
    458 	if (ndelta < 0)
    459 		ntickdelta = -ntickdelta;
    460 	s = splclock();
    461 	odelta = timedelta;
    462 	timedelta = ndelta;
    463 	tickdelta = ntickdelta;
    464 	splx(s);
    465 
    466 	if (SCARG(uap, olddelta)) {
    467 		atv.tv_sec = odelta / 1000000;
    468 		atv.tv_usec = odelta % 1000000;
    469 		(void) copyout(&atv,
    470 		    (caddr_t)NETBSD32PTR64(SCARG(uap, olddelta)), sizeof(atv));
    471 	}
    472 	return (0);
    473 }
    474 
    475 int
    476 netbsd32_clock_gettime(l, v, retval)
    477 	struct lwp *l;
    478 	void *v;
    479 	register_t *retval;
    480 {
    481 	struct netbsd32_clock_gettime_args /* {
    482 		syscallarg(netbsd32_clockid_t) clock_id;
    483 		syscallarg(netbsd32_timespecp_t) tp;
    484 	} */ *uap = v;
    485 	clockid_t clock_id;
    486 	struct timeval atv;
    487 	struct timespec ats;
    488 	struct netbsd32_timespec ts32;
    489 
    490 	clock_id = SCARG(uap, clock_id);
    491 	if (clock_id != CLOCK_REALTIME)
    492 		return (EINVAL);
    493 
    494 	microtime(&atv);
    495 	TIMEVAL_TO_TIMESPEC(&atv,&ats);
    496 	netbsd32_from_timespec(&ats, &ts32);
    497 
    498 	return copyout(&ts32, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
    499 	    sizeof(ts32));
    500 }
    501 
    502 int
    503 netbsd32_clock_settime(l, v, retval)
    504 	struct lwp *l;
    505 	void *v;
    506 	register_t *retval;
    507 {
    508 	struct netbsd32_clock_settime_args /* {
    509 		syscallarg(netbsd32_clockid_t) clock_id;
    510 		syscallarg(const netbsd32_timespecp_t) tp;
    511 	} */ *uap = v;
    512 	struct netbsd32_timespec ts32;
    513 	clockid_t clock_id;
    514 	struct timeval atv;
    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 	TIMESPEC_TO_TIMEVAL(&atv,&ats);
    532 	if ((error = settime(&atv)))
    533 		return (error);
    534 
    535 	return 0;
    536 }
    537 
    538 int
    539 netbsd32_clock_getres(l, v, retval)
    540 	struct lwp *l;
    541 	void *v;
    542 	register_t *retval;
    543 {
    544 	struct netbsd32_clock_getres_args /* {
    545 		syscallarg(netbsd32_clockid_t) clock_id;
    546 		syscallarg(netbsd32_timespecp_t) tp;
    547 	} */ *uap = v;
    548 	struct netbsd32_timespec ts32;
    549 	clockid_t clock_id;
    550 	struct timespec ts;
    551 	int error = 0;
    552 
    553 	clock_id = SCARG(uap, clock_id);
    554 	if (clock_id != CLOCK_REALTIME)
    555 		return (EINVAL);
    556 
    557 	if (SCARG(uap, tp)) {
    558 		ts.tv_sec = 0;
    559 		ts.tv_nsec = 1000000000 / hz;
    560 
    561 		netbsd32_from_timespec(&ts, &ts32);
    562 		error = copyout(&ts, (caddr_t)NETBSD32PTR64(SCARG(uap, tp)),
    563 		    sizeof(ts));
    564 	}
    565 
    566 	return error;
    567 }
    568 
    569 int
    570 netbsd32_nanosleep(l, v, retval)
    571 	struct lwp *l;
    572 	void *v;
    573 	register_t *retval;
    574 {
    575 	struct netbsd32_nanosleep_args /* {
    576 		syscallarg(const netbsd32_timespecp_t) rqtp;
    577 		syscallarg(netbsd32_timespecp_t) rmtp;
    578 	} */ *uap = v;
    579 	static int nanowait;
    580 	struct netbsd32_timespec ts32;
    581 	struct timespec rqt;
    582 	struct timespec rmt;
    583 	struct timeval atv, utv;
    584 	int error, s, timo;
    585 
    586 	error = copyin((caddr_t)NETBSD32PTR64(SCARG(uap, rqtp)), (caddr_t)&ts32,
    587 	    sizeof(ts32));
    588 	if (error)
    589 		return (error);
    590 
    591 	netbsd32_to_timespec(&ts32, &rqt);
    592 	TIMESPEC_TO_TIMEVAL(&atv,&rqt);
    593 	if (itimerfix(&atv))
    594 		return (EINVAL);
    595 
    596 	s = splclock();
    597 	timeradd(&atv,&time,&atv);
    598 	timo = hzto(&atv);
    599 	/*
    600 	 * Avoid inadvertantly sleeping forever
    601 	 */
    602 	if (timo == 0)
    603 		timo = 1;
    604 	splx(s);
    605 
    606 	error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
    607 	if (error == ERESTART)
    608 		error = EINTR;
    609 	if (error == EWOULDBLOCK)
    610 		error = 0;
    611 
    612 	if (SCARG(uap, rmtp)) {
    613 		int error1;
    614 
    615 		s = splclock();
    616 		utv = time;
    617 		splx(s);
    618 
    619 		timersub(&atv, &utv, &utv);
    620 		if (utv.tv_sec < 0)
    621 			timerclear(&utv);
    622 
    623 		TIMEVAL_TO_TIMESPEC(&utv,&rmt);
    624 		netbsd32_from_timespec(&rmt, &ts32);
    625 		error1 = copyout(&ts32,
    626 		    NETBSD32PTR64(SCARG(uap,rmtp)), sizeof(ts32));
    627 		if (error1)
    628 			return (error1);
    629 	}
    630 
    631 	return error;
    632 }
    633 
    634 static int
    635 netbsd32_timer_create_fetch(const void *src, void *dst, size_t size)
    636 {
    637 	struct sigevent *evp = dst;
    638 	struct netbsd32_sigevent ev32;
    639 	int error;
    640 
    641 	error = copyin(src, &ev32, sizeof(ev32));
    642 	if (error)
    643 		return error;
    644 
    645 	netbsd32_to_sigevent(&ev32, evp);
    646 	return 0;
    647 }
    648 
    649 int
    650 netbsd32_timer_create(struct lwp *l, void *v, register_t *retval)
    651 {
    652 	struct netbsd32_timer_create_args /* {
    653 		syscallarg(netbsd32_clockid_t) clock_id;
    654 		syscallarg(netbsd32_sigeventp_t) evp;
    655 		syscallarg(netbsd32_timerp_t) timerid;
    656 	} */ *uap = v;
    657 
    658 	return timer_create1(NETBSD32PTR64(SCARG(uap, timerid)),
    659 	    SCARG(uap, clock_id), NETBSD32PTR64(SCARG(uap, evp)),
    660 	    netbsd32_timer_create_fetch, l->l_proc);
    661 }
    662 
    663 int
    664 netbsd32_timer_delete(struct lwp *l, void *v, register_t *retval)
    665 {
    666 	struct netbsd32_timer_delete_args /* {
    667 		syscallarg(netbsd32_timer_t) timerid;
    668 	} */ *uap = v;
    669 	struct sys_timer_delete_args ua;
    670 
    671 	NETBSD32TO64_UAP(timerid);
    672 	return sys_timer_delete(l, (void *)&ua, retval);
    673 }
    674 
    675 int
    676 netbsd32_timer_settime(struct lwp *l, void *v, register_t *retval)
    677 {
    678 	struct netbsd32_timer_settime_args /* {
    679 		syscallarg(netbsd32_timer_t) timerid;
    680 		syscallarg(int) flags;
    681 		syscallarg(const netbsd32_itimerspecp_t) value;
    682 		syscallarg(netbsd32_itimerspecp_t) ovalue;
    683 	} */ *uap = v;
    684 	int error;
    685 	struct itimerspec value, ovalue, *ovp = NULL;
    686 	struct netbsd32_itimerspec its32;
    687 
    688 	if ((error = copyin(NETBSD32PTR64(SCARG(uap, value)), &its32,
    689 	    sizeof(its32))) != 0)
    690 		return (error);
    691 	netbsd32_to_timespec(&its32.it_interval, &value.it_interval);
    692 	netbsd32_to_timespec(&its32.it_value, &value.it_value);
    693 
    694 	if (SCARG(uap, ovalue))
    695 		ovp = &ovalue;
    696 
    697 	if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
    698 	    SCARG(uap, flags), l->l_proc)) != 0)
    699 		return error;
    700 
    701 	if (ovp) {
    702 		netbsd32_from_timespec(&ovp->it_interval, &its32.it_interval);
    703 		netbsd32_from_timespec(&ovp->it_value, &its32.it_value);
    704 		return copyout(&its32, NETBSD32PTR64(SCARG(uap, ovalue)),
    705 		    sizeof(its32));
    706 	}
    707 	return 0;
    708 }
    709 
    710 int
    711 netbsd32_timer_gettime(struct lwp *l, void *v, register_t *retval)
    712 {
    713 	struct netbsd32_timer_gettime_args /* {
    714 		syscallarg(netbsd32_timer_t) timerid;
    715 		syscallarg(netbsd32_itimerspecp_t) value;
    716 	} */ *uap = v;
    717 	int error;
    718 	struct itimerspec its;
    719 	struct netbsd32_itimerspec its32;
    720 
    721 	if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
    722 	    &its)) != 0)
    723 		return error;
    724 
    725 	netbsd32_from_timespec(&its.it_interval, &its32.it_interval);
    726 	netbsd32_from_timespec(&its.it_value, &its32.it_value);
    727 
    728 	return copyout(&its32, (caddr_t)NETBSD32PTR64(SCARG(uap, value)),
    729 	    sizeof(its32));
    730 }
    731 
    732 int
    733 netbsd32_timer_getoverrun(struct lwp *l, void *v, register_t *retval)
    734 {
    735 	struct netbsd32_timer_getoverrun_args /* {
    736 		syscallarg(netbsd32_timer_t) timerid;
    737 	} */ *uap = v;
    738 	struct sys_timer_getoverrun_args ua;
    739 
    740 	NETBSD32TO64_UAP(timerid);
    741 	return sys_timer_getoverrun(l, (void *)&ua, retval);
    742 }
    743