xref: /netbsd-src/sys/kern/kern_time.c (revision e4d7c2e329d54c97e0c0bd3016bbe74f550c3d5e)
1 /*	$NetBSD: kern_time.c,v 1.43 2000/02/16 12:36:19 itojun Exp $	*/
2 
3 /*-
4  * Copyright (c) 2000 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Christopher G. Demetriou.
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 
39 /*
40  * Copyright (c) 1982, 1986, 1989, 1993
41  *	The Regents of the University of California.  All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  * 3. All advertising materials mentioning features or use of this software
52  *    must display the following acknowledgement:
53  *	This product includes software developed by the University of
54  *	California, Berkeley and its contributors.
55  * 4. Neither the name of the University nor the names of its contributors
56  *    may be used to endorse or promote products derived from this software
57  *    without specific prior written permission.
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69  * SUCH DAMAGE.
70  *
71  *	@(#)kern_time.c	8.4 (Berkeley) 5/26/95
72  */
73 
74 #include "fs_nfs.h"
75 #include "opt_nfsserver.h"
76 
77 #include <sys/param.h>
78 #include <sys/resourcevar.h>
79 #include <sys/kernel.h>
80 #include <sys/systm.h>
81 #include <sys/proc.h>
82 #include <sys/vnode.h>
83 #include <sys/signalvar.h>
84 #include <sys/syslog.h>
85 
86 #include <sys/mount.h>
87 #include <sys/syscallargs.h>
88 
89 #include <vm/vm.h>
90 #include <uvm/uvm_extern.h>
91 
92 #if defined(NFS) || defined(NFSSERVER)
93 #include <nfs/rpcv2.h>
94 #include <nfs/nfsproto.h>
95 #include <nfs/nfs_var.h>
96 #endif
97 
98 #include <machine/cpu.h>
99 
100 /*
101  * Time of day and interval timer support.
102  *
103  * These routines provide the kernel entry points to get and set
104  * the time-of-day and per-process interval timers.  Subroutines
105  * here provide support for adding and subtracting timeval structures
106  * and decrementing interval timers, optionally reloading the interval
107  * timers when they expire.
108  */
109 
110 /* This function is used by clock_settime and settimeofday */
111 int
112 settime(tv)
113 	struct timeval *tv;
114 {
115 	struct timeval delta;
116 	int s;
117 
118 	/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
119 	s = splclock();
120 	timersub(tv, &time, &delta);
121 	if ((delta.tv_sec < 0 || delta.tv_usec < 0) && securelevel > 1)
122 		return (EPERM);
123 #ifdef notyet
124 	if ((delta.tv_sec < 86400) && securelevel > 0)
125 		return (EPERM);
126 #endif
127 	time = *tv;
128 	(void) spllowersoftclock();
129 	timeradd(&boottime, &delta, &boottime);
130 	timeradd(&runtime, &delta, &runtime);
131 #	if defined(NFS) || defined(NFSSERVER)
132 		nqnfs_lease_updatetime(delta.tv_sec);
133 #	endif
134 	splx(s);
135 	resettodr();
136 	return (0);
137 }
138 
139 /* ARGSUSED */
140 int
141 sys_clock_gettime(p, v, retval)
142 	struct proc *p;
143 	void *v;
144 	register_t *retval;
145 {
146 	register struct sys_clock_gettime_args /* {
147 		syscallarg(clockid_t) clock_id;
148 		syscallarg(struct timespec *) tp;
149 	} */ *uap = v;
150 	clockid_t clock_id;
151 	struct timeval atv;
152 	struct timespec ats;
153 
154 	clock_id = SCARG(uap, clock_id);
155 	if (clock_id != CLOCK_REALTIME)
156 		return (EINVAL);
157 
158 	microtime(&atv);
159 	TIMEVAL_TO_TIMESPEC(&atv,&ats);
160 
161 	return copyout(&ats, SCARG(uap, tp), sizeof(ats));
162 }
163 
164 /* ARGSUSED */
165 int
166 sys_clock_settime(p, v, retval)
167 	struct proc *p;
168 	void *v;
169 	register_t *retval;
170 {
171 	register struct sys_clock_settime_args /* {
172 		syscallarg(clockid_t) clock_id;
173 		syscallarg(const struct timespec *) tp;
174 	} */ *uap = v;
175 	clockid_t clock_id;
176 	struct timeval atv;
177 	struct timespec ats;
178 	int error;
179 
180 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
181 		return (error);
182 
183 	clock_id = SCARG(uap, clock_id);
184 	if (clock_id != CLOCK_REALTIME)
185 		return (EINVAL);
186 
187 	if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
188 		return (error);
189 
190 	TIMESPEC_TO_TIMEVAL(&atv,&ats);
191 	if ((error = settime(&atv)))
192 		return (error);
193 
194 	return 0;
195 }
196 
197 int
198 sys_clock_getres(p, v, retval)
199 	struct proc *p;
200 	void *v;
201 	register_t *retval;
202 {
203 	register struct sys_clock_getres_args /* {
204 		syscallarg(clockid_t) clock_id;
205 		syscallarg(struct timespec *) tp;
206 	} */ *uap = v;
207 	clockid_t clock_id;
208 	struct timespec ts;
209 	int error = 0;
210 
211 	clock_id = SCARG(uap, clock_id);
212 	if (clock_id != CLOCK_REALTIME)
213 		return (EINVAL);
214 
215 	if (SCARG(uap, tp)) {
216 		ts.tv_sec = 0;
217 		ts.tv_nsec = 1000000000 / hz;
218 
219 		error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
220 	}
221 
222 	return error;
223 }
224 
225 /* ARGSUSED */
226 int
227 sys_nanosleep(p, v, retval)
228 	struct proc *p;
229 	void *v;
230 	register_t *retval;
231 {
232 	static int nanowait;
233 	register struct sys_nanosleep_args/* {
234 		syscallarg(struct timespec *) rqtp;
235 		syscallarg(struct timespec *) rmtp;
236 	} */ *uap = v;
237 	struct timespec rqt;
238 	struct timespec rmt;
239 	struct timeval atv, utv;
240 	int error, s, timo;
241 
242 	error = copyin((caddr_t)SCARG(uap, rqtp), (caddr_t)&rqt,
243 		       sizeof(struct timespec));
244 	if (error)
245 		return (error);
246 
247 	TIMESPEC_TO_TIMEVAL(&atv,&rqt)
248 	if (itimerfix(&atv))
249 		return (EINVAL);
250 
251 	s = splclock();
252 	timeradd(&atv,&time,&atv);
253 	timo = hzto(&atv);
254 	/*
255 	 * Avoid inadvertantly sleeping forever
256 	 */
257 	if (timo == 0)
258 		timo = 1;
259 	splx(s);
260 
261 	error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
262 	if (error == ERESTART)
263 		error = EINTR;
264 	if (error == EWOULDBLOCK)
265 		error = 0;
266 
267 	if (SCARG(uap, rmtp)) {
268 		int error;
269 
270 		s = splclock();
271 		utv = time;
272 		splx(s);
273 
274 		timersub(&atv, &utv, &utv);
275 		if (utv.tv_sec < 0)
276 			timerclear(&utv);
277 
278 		TIMEVAL_TO_TIMESPEC(&utv,&rmt);
279 		error = copyout((caddr_t)&rmt, (caddr_t)SCARG(uap,rmtp),
280 			sizeof(rmt));
281 		if (error)
282 			return (error);
283 	}
284 
285 	return error;
286 }
287 
288 /* ARGSUSED */
289 int
290 sys_gettimeofday(p, v, retval)
291 	struct proc *p;
292 	void *v;
293 	register_t *retval;
294 {
295 	register struct sys_gettimeofday_args /* {
296 		syscallarg(struct timeval *) tp;
297 		syscallarg(struct timezone *) tzp;
298 	} */ *uap = v;
299 	struct timeval atv;
300 	int error = 0;
301 	struct timezone tzfake;
302 
303 	if (SCARG(uap, tp)) {
304 		microtime(&atv);
305 		error = copyout(&atv, SCARG(uap, tp), sizeof(atv));
306 		if (error)
307 			return (error);
308 	}
309 	if (SCARG(uap, tzp)) {
310 		/*
311 		 * NetBSD has no kernel notion of time zone, so we just
312 		 * fake up a timezone struct and return it if demanded.
313 		 */
314 		tzfake.tz_minuteswest = 0;
315 		tzfake.tz_dsttime = 0;
316 		error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake));
317 	}
318 	return (error);
319 }
320 
321 /* ARGSUSED */
322 int
323 sys_settimeofday(p, v, retval)
324 	struct proc *p;
325 	void *v;
326 	register_t *retval;
327 {
328 	struct sys_settimeofday_args /* {
329 		syscallarg(const struct timeval *) tv;
330 		syscallarg(const struct timezone *) tzp;
331 	} */ *uap = v;
332 	struct timeval atv;
333 	struct timezone atz;
334 	int error;
335 
336 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
337 		return (error);
338 	/* Verify all parameters before changing time. */
339 	if (SCARG(uap, tv) && (error = copyin(SCARG(uap, tv),
340 	    &atv, sizeof(atv))))
341 		return (error);
342 	/* XXX since we don't use tz, probably no point in doing copyin. */
343 	if (SCARG(uap, tzp) && (error = copyin(SCARG(uap, tzp),
344 	    &atz, sizeof(atz))))
345 		return (error);
346 	if (SCARG(uap, tv))
347 		if ((error = settime(&atv)))
348 			return (error);
349 	/*
350 	 * NetBSD has no kernel notion of time zone, and only an
351 	 * obsolete program would try to set it, so we log a warning.
352 	 */
353 	if (SCARG(uap, tzp))
354 		log(LOG_WARNING, "pid %d attempted to set the "
355 		    "(obsolete) kernel time zone\n", p->p_pid);
356 	return (0);
357 }
358 
359 int	tickdelta;			/* current clock skew, us. per tick */
360 long	timedelta;			/* unapplied time correction, us. */
361 long	bigadj = 1000000;		/* use 10x skew above bigadj us. */
362 
363 /* ARGSUSED */
364 int
365 sys_adjtime(p, v, retval)
366 	struct proc *p;
367 	void *v;
368 	register_t *retval;
369 {
370 	register struct sys_adjtime_args /* {
371 		syscallarg(const struct timeval *) delta;
372 		syscallarg(struct timeval *) olddelta;
373 	} */ *uap = v;
374 	struct timeval atv;
375 	register long ndelta, ntickdelta, odelta;
376 	int s, error;
377 
378 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
379 		return (error);
380 
381 	error = copyin(SCARG(uap, delta), &atv, sizeof(struct timeval));
382 	if (error)
383 		return (error);
384 	if (SCARG(uap, olddelta) != NULL &&
385 	    uvm_useracc((caddr_t)SCARG(uap, olddelta), sizeof(struct timeval),
386 	     B_WRITE) == FALSE)
387 		return (EFAULT);
388 
389 	/*
390 	 * Compute the total correction and the rate at which to apply it.
391 	 * Round the adjustment down to a whole multiple of the per-tick
392 	 * delta, so that after some number of incremental changes in
393 	 * hardclock(), tickdelta will become zero, lest the correction
394 	 * overshoot and start taking us away from the desired final time.
395 	 */
396 	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
397 	if (ndelta > bigadj || ndelta < -bigadj)
398 		ntickdelta = 10 * tickadj;
399 	else
400 		ntickdelta = tickadj;
401 	if (ndelta % ntickdelta)
402 		ndelta = ndelta / ntickdelta * ntickdelta;
403 
404 	/*
405 	 * To make hardclock()'s job easier, make the per-tick delta negative
406 	 * if we want time to run slower; then hardclock can simply compute
407 	 * tick + tickdelta, and subtract tickdelta from timedelta.
408 	 */
409 	if (ndelta < 0)
410 		ntickdelta = -ntickdelta;
411 	s = splclock();
412 	odelta = timedelta;
413 	timedelta = ndelta;
414 	tickdelta = ntickdelta;
415 	splx(s);
416 
417 	if (SCARG(uap, olddelta)) {
418 		atv.tv_sec = odelta / 1000000;
419 		atv.tv_usec = odelta % 1000000;
420 		(void) copyout(&atv, SCARG(uap, olddelta),
421 		    sizeof(struct timeval));
422 	}
423 	return (0);
424 }
425 
426 /*
427  * Get value of an interval timer.  The process virtual and
428  * profiling virtual time timers are kept in the p_stats area, since
429  * they can be swapped out.  These are kept internally in the
430  * way they are specified externally: in time until they expire.
431  *
432  * The real time interval timer is kept in the process table slot
433  * for the process, and its value (it_value) is kept as an
434  * absolute time rather than as a delta, so that it is easy to keep
435  * periodic real-time signals from drifting.
436  *
437  * Virtual time timers are processed in the hardclock() routine of
438  * kern_clock.c.  The real time timer is processed by a timeout
439  * routine, called from the softclock() routine.  Since a callout
440  * may be delayed in real time due to interrupt processing in the system,
441  * it is possible for the real time timeout routine (realitexpire, given below),
442  * to be delayed in real time past when it is supposed to occur.  It
443  * does not suffice, therefore, to reload the real timer .it_value from the
444  * real time timers .it_interval.  Rather, we compute the next time in
445  * absolute time the timer should go off.
446  */
447 /* ARGSUSED */
448 int
449 sys_getitimer(p, v, retval)
450 	struct proc *p;
451 	void *v;
452 	register_t *retval;
453 {
454 	register struct sys_getitimer_args /* {
455 		syscallarg(int) which;
456 		syscallarg(struct itimerval *) itv;
457 	} */ *uap = v;
458 	int which = SCARG(uap, which);
459 	struct itimerval aitv;
460 	int s;
461 
462 	if ((u_int)which > ITIMER_PROF)
463 		return (EINVAL);
464 	s = splclock();
465 	if (which == ITIMER_REAL) {
466 		/*
467 		 * Convert from absolute to relative time in .it_value
468 		 * part of real time timer.  If time for real time timer
469 		 * has passed return 0, else return difference between
470 		 * current time and time for the timer to go off.
471 		 */
472 		aitv = p->p_realtimer;
473 		if (timerisset(&aitv.it_value)) {
474 			if (timercmp(&aitv.it_value, &time, <))
475 				timerclear(&aitv.it_value);
476 			else
477 				timersub(&aitv.it_value, &time, &aitv.it_value);
478 		}
479 	} else
480 		aitv = p->p_stats->p_timer[which];
481 	splx(s);
482 	return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)));
483 }
484 
485 /* ARGSUSED */
486 int
487 sys_setitimer(p, v, retval)
488 	struct proc *p;
489 	register void *v;
490 	register_t *retval;
491 {
492 	register struct sys_setitimer_args /* {
493 		syscallarg(int) which;
494 		syscallarg(const struct itimerval *) itv;
495 		syscallarg(struct itimerval *) oitv;
496 	} */ *uap = v;
497 	int which = SCARG(uap, which);
498 	struct sys_getitimer_args getargs;
499 	struct itimerval aitv;
500 	register const struct itimerval *itvp;
501 	int s, error;
502 
503 	if ((u_int)which > ITIMER_PROF)
504 		return (EINVAL);
505 	itvp = SCARG(uap, itv);
506 	if (itvp && (error = copyin(itvp, &aitv, sizeof(struct itimerval))))
507 		return (error);
508 	if (SCARG(uap, oitv) != NULL) {
509 		SCARG(&getargs, which) = which;
510 		SCARG(&getargs, itv) = SCARG(uap, oitv);
511 		if ((error = sys_getitimer(p, &getargs, retval)) != 0)
512 			return (error);
513 	}
514 	if (itvp == 0)
515 		return (0);
516 	if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
517 		return (EINVAL);
518 	s = splclock();
519 	if (which == ITIMER_REAL) {
520 		untimeout(realitexpire, p);
521 		if (timerisset(&aitv.it_value)) {
522 			timeradd(&aitv.it_value, &time, &aitv.it_value);
523 			timeout(realitexpire, p, hzto(&aitv.it_value));
524 		}
525 		p->p_realtimer = aitv;
526 	} else
527 		p->p_stats->p_timer[which] = aitv;
528 	splx(s);
529 	return (0);
530 }
531 
532 /*
533  * Real interval timer expired:
534  * send process whose timer expired an alarm signal.
535  * If time is not set up to reload, then just return.
536  * Else compute next time timer should go off which is > current time.
537  * This is where delay in processing this timeout causes multiple
538  * SIGALRM calls to be compressed into one.
539  */
540 void
541 realitexpire(arg)
542 	void *arg;
543 {
544 	register struct proc *p;
545 	int s;
546 
547 	p = (struct proc *)arg;
548 	psignal(p, SIGALRM);
549 	if (!timerisset(&p->p_realtimer.it_interval)) {
550 		timerclear(&p->p_realtimer.it_value);
551 		return;
552 	}
553 	for (;;) {
554 		s = splclock();
555 		timeradd(&p->p_realtimer.it_value,
556 		    &p->p_realtimer.it_interval, &p->p_realtimer.it_value);
557 		if (timercmp(&p->p_realtimer.it_value, &time, >)) {
558 			timeout(realitexpire, p,
559 			    hzto(&p->p_realtimer.it_value));
560 			splx(s);
561 			return;
562 		}
563 		splx(s);
564 	}
565 }
566 
567 /*
568  * Check that a proposed value to load into the .it_value or
569  * .it_interval part of an interval timer is acceptable, and
570  * fix it to have at least minimal value (i.e. if it is less
571  * than the resolution of the clock, round it up.)
572  */
573 int
574 itimerfix(tv)
575 	struct timeval *tv;
576 {
577 
578 	if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
579 	    tv->tv_usec < 0 || tv->tv_usec >= 1000000)
580 		return (EINVAL);
581 	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
582 		tv->tv_usec = tick;
583 	return (0);
584 }
585 
586 /*
587  * Decrement an interval timer by a specified number
588  * of microseconds, which must be less than a second,
589  * i.e. < 1000000.  If the timer expires, then reload
590  * it.  In this case, carry over (usec - old value) to
591  * reduce the value reloaded into the timer so that
592  * the timer does not drift.  This routine assumes
593  * that it is called in a context where the timers
594  * on which it is operating cannot change in value.
595  */
596 int
597 itimerdecr(itp, usec)
598 	register struct itimerval *itp;
599 	int usec;
600 {
601 
602 	if (itp->it_value.tv_usec < usec) {
603 		if (itp->it_value.tv_sec == 0) {
604 			/* expired, and already in next interval */
605 			usec -= itp->it_value.tv_usec;
606 			goto expire;
607 		}
608 		itp->it_value.tv_usec += 1000000;
609 		itp->it_value.tv_sec--;
610 	}
611 	itp->it_value.tv_usec -= usec;
612 	usec = 0;
613 	if (timerisset(&itp->it_value))
614 		return (1);
615 	/* expired, exactly at end of interval */
616 expire:
617 	if (timerisset(&itp->it_interval)) {
618 		itp->it_value = itp->it_interval;
619 		itp->it_value.tv_usec -= usec;
620 		if (itp->it_value.tv_usec < 0) {
621 			itp->it_value.tv_usec += 1000000;
622 			itp->it_value.tv_sec--;
623 		}
624 	} else
625 		itp->it_value.tv_usec = 0;		/* sec is already 0 */
626 	return (0);
627 }
628 
629 /*
630  * ratecheck(): simple time-based rate-limit checking.  see ratecheck(9)
631  * for usage and rationale.
632  */
633 int
634 ratecheck(lasttime, mininterval)
635 	struct timeval *lasttime;
636 	const struct timeval *mininterval;
637 {
638 	struct timeval delta;
639 	int s, rv = 0;
640 
641 	s = splclock();
642 	timersub(&mono_time, lasttime, &delta);
643 
644 	/*
645 	 * check for 0,0 is so that the message will be seen at least once,
646 	 * even if interval is huge.
647 	 */
648 	if (timercmp(&delta, mininterval, >=) ||
649 	    (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
650 		*lasttime = mono_time;
651 		rv = 1;
652 	}
653 	splx(s);
654 
655 	return (rv);
656 }
657