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