FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_time.c
1 /*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. 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.1 (Berkeley) 6/10/93
34 * $FreeBSD$
35 */
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/buf.h>
40 #include <sys/sysproto.h>
41 #include <sys/resourcevar.h>
42 #include <sys/signalvar.h>
43 #include <sys/kernel.h>
44 #include <sys/systm.h>
45 #include <sys/sysent.h>
46 #include <sys/proc.h>
47 #include <sys/time.h>
48 #include <sys/vnode.h>
49 #include <vm/vm.h>
50 #include <vm/vm_extern.h>
51
52 struct timezone tz;
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 static int nanosleep1 __P((struct proc *p, struct timespec *rqt,
65 struct timespec *rmt));
66 static int settime __P((struct timeval *));
67 static void timevalfix __P((struct timeval *));
68 static void no_lease_updatetime __P((int));
69
70 static void
71 no_lease_updatetime(deltat)
72 int deltat;
73 {
74 }
75
76 void (*lease_updatetime) __P((int)) = no_lease_updatetime;
77
78 static int
79 settime(tv)
80 struct timeval *tv;
81 {
82 struct timeval delta, tv1, tv2;
83 static struct timeval maxtime, laststep;
84 struct timespec ts;
85 int s;
86
87 s = splclock();
88 microtime(&tv1);
89 delta = *tv;
90 timevalsub(&delta, &tv1);
91
92 /*
93 * If the system is secure, we do not allow the time to be
94 * set to a value earlier than 1 second less than the highest
95 * time we have yet seen. The worst a miscreant can do in
96 * this circumstance is "freeze" time. He couldn't go
97 * back to the past.
98 *
99 * We similarly do not allow the clock to be stepped more
100 * than one second, nor more than once per second. This allows
101 * a miscreant to make the clock march double-time, but no worse.
102 */
103 if (securelevel > 1) {
104 if (delta.tv_sec < 0 || delta.tv_usec < 0) {
105 /*
106 * Update maxtime to latest time we've seen.
107 */
108 if (tv1.tv_sec > maxtime.tv_sec)
109 maxtime = tv1;
110 tv2 = *tv;
111 timevalsub(&tv2, &maxtime);
112 if (tv2.tv_sec < -1) {
113 tv->tv_sec = maxtime.tv_sec - 1;
114 printf("Time adjustment clamped to -1 second\n");
115 }
116 } else {
117 if (tv1.tv_sec == laststep.tv_sec) {
118 splx(s);
119 return (EPERM);
120 }
121 if (delta.tv_sec > 1) {
122 tv->tv_sec = tv1.tv_sec + 1;
123 printf("Time adjustment clamped to +1 second\n");
124 }
125 laststep = *tv;
126 }
127 }
128
129 ts.tv_sec = tv->tv_sec;
130 ts.tv_nsec = tv->tv_usec * 1000;
131 set_timecounter(&ts);
132 (void) splsoftclock();
133 lease_updatetime(delta.tv_sec);
134 splx(s);
135 resettodr();
136 return (0);
137 }
138
139 #ifndef _SYS_SYSPROTO_H_
140 struct clock_gettime_args {
141 clockid_t clock_id;
142 struct timespec *tp;
143 };
144 #endif
145
146 /* ARGSUSED */
147 int
148 clock_gettime(p, uap)
149 struct proc *p;
150 struct clock_gettime_args *uap;
151 {
152 struct timespec ats;
153
154 if (SCARG(uap, clock_id) != CLOCK_REALTIME)
155 return (EINVAL);
156 nanotime(&ats);
157 return (copyout(&ats, SCARG(uap, tp), sizeof(ats)));
158 }
159
160 #ifndef _SYS_SYSPROTO_H_
161 struct clock_settime_args {
162 clockid_t clock_id;
163 const struct timespec *tp;
164 };
165 #endif
166
167 /* ARGSUSED */
168 int
169 clock_settime(p, uap)
170 struct proc *p;
171 struct clock_settime_args *uap;
172 {
173 struct timeval atv;
174 struct timespec ats;
175 int error;
176
177 if ((error = suser(p)) != 0)
178 return (error);
179 if (SCARG(uap, clock_id) != CLOCK_REALTIME)
180 return (EINVAL);
181 if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
182 return (error);
183 if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000)
184 return (EINVAL);
185 /* XXX Don't convert nsec->usec and back */
186 TIMESPEC_TO_TIMEVAL(&atv, &ats);
187 if ((error = settime(&atv)))
188 return (error);
189 return (0);
190 }
191
192 #ifndef _SYS_SYSPROTO_H_
193 struct clock_getres_args {
194 clockid_t clock_id;
195 struct timespec *tp;
196 };
197 #endif
198
199 int
200 clock_getres(p, uap)
201 struct proc *p;
202 struct clock_getres_args *uap;
203 {
204 struct timespec ts;
205 int error;
206
207 if (SCARG(uap, clock_id) != CLOCK_REALTIME)
208 return (EINVAL);
209 error = 0;
210 if (SCARG(uap, tp)) {
211 ts.tv_sec = 0;
212 /*
213 * Round up the result of the division cheaply by adding 1.
214 * Rounding up is especially important if rounding down
215 * would give 0. Perfect rounding is unimportant.
216 */
217 ts.tv_nsec = 1000000000 / timecounter->tc_frequency + 1;
218 error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
219 }
220 return (error);
221 }
222
223 static int nanowait;
224
225 static int
226 nanosleep1(p, rqt, rmt)
227 struct proc *p;
228 struct timespec *rqt, *rmt;
229 {
230 struct timespec ts, ts2, ts3;
231 struct timeval tv;
232 int error;
233
234 if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
235 return (EINVAL);
236 if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0))
237 return (0);
238 getnanouptime(&ts);
239 timespecadd(&ts, rqt);
240 TIMESPEC_TO_TIMEVAL(&tv, rqt);
241 for (;;) {
242 error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp",
243 tvtohz(&tv));
244 getnanouptime(&ts2);
245 if (error != EWOULDBLOCK) {
246 if (error == ERESTART)
247 error = EINTR;
248 if (rmt != NULL) {
249 timespecsub(&ts, &ts2);
250 if (ts.tv_sec < 0)
251 timespecclear(&ts);
252 *rmt = ts;
253 }
254 return (error);
255 }
256 if (timespeccmp(&ts2, &ts, >=))
257 return (0);
258 ts3 = ts;
259 timespecsub(&ts3, &ts2);
260 TIMESPEC_TO_TIMEVAL(&tv, &ts3);
261 }
262 }
263
264 #ifndef _SYS_SYSPROTO_H_
265 struct nanosleep_args {
266 struct timespec *rqtp;
267 struct timespec *rmtp;
268 };
269 #endif
270
271 /* ARGSUSED */
272 int
273 nanosleep(p, uap)
274 struct proc *p;
275 struct nanosleep_args *uap;
276 {
277 struct timespec rmt, rqt;
278 int error, error2;
279
280 error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
281 if (error)
282 return (error);
283 if (SCARG(uap, rmtp))
284 if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt),
285 VM_PROT_WRITE))
286 return (EFAULT);
287 error = nanosleep1(p, &rqt, &rmt);
288 if (error && SCARG(uap, rmtp)) {
289 error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
290 if (error2) /* XXX shouldn't happen, did useracc() above */
291 return (error2);
292 }
293 return (error);
294 }
295
296 #ifndef _SYS_SYSPROTO_H_
297 struct gettimeofday_args {
298 struct timeval *tp;
299 struct timezone *tzp;
300 };
301 #endif
302 /* ARGSUSED */
303 int
304 gettimeofday(p, uap)
305 struct proc *p;
306 register struct gettimeofday_args *uap;
307 {
308 struct timeval atv;
309 int error = 0;
310
311 if (uap->tp) {
312 microtime(&atv);
313 if ((error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
314 sizeof (atv))))
315 return (error);
316 }
317 if (uap->tzp)
318 error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
319 sizeof (tz));
320 return (error);
321 }
322
323 #ifndef _SYS_SYSPROTO_H_
324 struct settimeofday_args {
325 struct timeval *tv;
326 struct timezone *tzp;
327 };
328 #endif
329 /* ARGSUSED */
330 int
331 settimeofday(p, uap)
332 struct proc *p;
333 struct settimeofday_args *uap;
334 {
335 struct timeval atv;
336 struct timezone atz;
337 int error;
338
339 if ((error = suser(p)))
340 return (error);
341 /* Verify all parameters before changing time. */
342 if (uap->tv) {
343 if ((error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
344 sizeof(atv))))
345 return (error);
346 if (atv.tv_usec < 0 || atv.tv_usec >= 1000000)
347 return (EINVAL);
348 }
349 if (uap->tzp &&
350 (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz))))
351 return (error);
352 if (uap->tv && (error = settime(&atv)))
353 return (error);
354 if (uap->tzp)
355 tz = atz;
356 return (0);
357 }
358
359 int tickdelta; /* current clock skew, us. per tick */
360 long timedelta; /* unapplied time correction, us. */
361 static long bigadj = 1000000; /* use 10x skew above bigadj us. */
362
363 #ifndef _SYS_SYSPROTO_H_
364 struct adjtime_args {
365 struct timeval *delta;
366 struct timeval *olddelta;
367 };
368 #endif
369 /* ARGSUSED */
370 int
371 adjtime(p, uap)
372 struct proc *p;
373 register struct adjtime_args *uap;
374 {
375 struct timeval atv;
376 register long ndelta, ntickdelta, odelta;
377 int s, error;
378
379 if ((error = suser(p)))
380 return (error);
381 if ((error =
382 copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))))
383 return (error);
384
385 /*
386 * Compute the total correction and the rate at which to apply it.
387 * Round the adjustment down to a whole multiple of the per-tick
388 * delta, so that after some number of incremental changes in
389 * hardclock(), tickdelta will become zero, lest the correction
390 * overshoot and start taking us away from the desired final time.
391 */
392 ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
393 if (ndelta > bigadj || ndelta < -bigadj)
394 ntickdelta = 10 * tickadj;
395 else
396 ntickdelta = tickadj;
397 if (ndelta % ntickdelta)
398 ndelta = ndelta / ntickdelta * ntickdelta;
399
400 /*
401 * To make hardclock()'s job easier, make the per-tick delta negative
402 * if we want time to run slower; then hardclock can simply compute
403 * tick + tickdelta, and subtract tickdelta from timedelta.
404 */
405 if (ndelta < 0)
406 ntickdelta = -ntickdelta;
407 s = splclock();
408 odelta = timedelta;
409 timedelta = ndelta;
410 tickdelta = ntickdelta;
411 splx(s);
412
413 if (uap->olddelta) {
414 atv.tv_sec = odelta / 1000000;
415 atv.tv_usec = odelta % 1000000;
416 (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta,
417 sizeof(struct timeval));
418 }
419 return (0);
420 }
421
422 /*
423 * Get value of an interval timer. The process virtual and
424 * profiling virtual time timers are kept in the p_stats area, since
425 * they can be swapped out. These are kept internally in the
426 * way they are specified externally: in time until they expire.
427 *
428 * The real time interval timer is kept in the process table slot
429 * for the process, and its value (it_value) is kept as an
430 * absolute time rather than as a delta, so that it is easy to keep
431 * periodic real-time signals from drifting.
432 *
433 * Virtual time timers are processed in the hardclock() routine of
434 * kern_clock.c. The real time timer is processed by a timeout
435 * routine, called from the softclock() routine. Since a callout
436 * may be delayed in real time due to interrupt processing in the system,
437 * it is possible for the real time timeout routine (realitexpire, given below),
438 * to be delayed in real time past when it is supposed to occur. It
439 * does not suffice, therefore, to reload the real timer .it_value from the
440 * real time timers .it_interval. Rather, we compute the next time in
441 * absolute time the timer should go off.
442 */
443 #ifndef _SYS_SYSPROTO_H_
444 struct getitimer_args {
445 u_int which;
446 struct itimerval *itv;
447 };
448 #endif
449 /* ARGSUSED */
450 int
451 getitimer(p, uap)
452 struct proc *p;
453 register struct getitimer_args *uap;
454 {
455 struct timeval ctv;
456 struct itimerval aitv;
457 int s;
458
459 if (uap->which > ITIMER_PROF)
460 return (EINVAL);
461 s = splclock(); /* XXX still needed ? */
462 if (uap->which == ITIMER_REAL) {
463 /*
464 * Convert from absolute to relative time in .it_value
465 * part of real time timer. If time for real time timer
466 * has passed return 0, else return difference between
467 * current time and time for the timer to go off.
468 */
469 aitv = p->p_realtimer;
470 if (timevalisset(&aitv.it_value)) {
471 getmicrouptime(&ctv);
472 if (timevalcmp(&aitv.it_value, &ctv, <))
473 timevalclear(&aitv.it_value);
474 else
475 timevalsub(&aitv.it_value, &ctv);
476 }
477 } else
478 aitv = p->p_stats->p_timer[uap->which];
479 splx(s);
480 return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
481 sizeof (struct itimerval)));
482 }
483
484 #ifndef _SYS_SYSPROTO_H_
485 struct setitimer_args {
486 u_int which;
487 struct itimerval *itv, *oitv;
488 };
489 #endif
490 /* ARGSUSED */
491 int
492 setitimer(p, uap)
493 struct proc *p;
494 register struct setitimer_args *uap;
495 {
496 struct itimerval aitv;
497 struct timeval ctv;
498 register struct itimerval *itvp;
499 int s, error;
500
501 if (uap->which > ITIMER_PROF)
502 return (EINVAL);
503 itvp = uap->itv;
504 if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
505 sizeof(struct itimerval))))
506 return (error);
507 if ((uap->itv = uap->oitv) &&
508 (error = getitimer(p, (struct getitimer_args *)uap)))
509 return (error);
510 if (itvp == 0)
511 return (0);
512 if (itimerfix(&aitv.it_value))
513 return (EINVAL);
514 if (!timevalisset(&aitv.it_value))
515 timevalclear(&aitv.it_interval);
516 else if (itimerfix(&aitv.it_interval))
517 return (EINVAL);
518 s = splclock(); /* XXX: still needed ? */
519 if (uap->which == ITIMER_REAL) {
520 if (timevalisset(&p->p_realtimer.it_value))
521 untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
522 if (timevalisset(&aitv.it_value))
523 p->p_ithandle = timeout(realitexpire, (caddr_t)p,
524 tvtohz(&aitv.it_value));
525 getmicrouptime(&ctv);
526 timevaladd(&aitv.it_value, &ctv);
527 p->p_realtimer = aitv;
528 } else
529 p->p_stats->p_timer[uap->which] = aitv;
530 splx(s);
531 return (0);
532 }
533
534 /*
535 * Real interval timer expired:
536 * send process whose timer expired an alarm signal.
537 * If time is not set up to reload, then just return.
538 * Else compute next time timer should go off which is > current time.
539 * This is where delay in processing this timeout causes multiple
540 * SIGALRM calls to be compressed into one.
541 * tvtohz() always adds 1 to allow for the time until the next clock
542 * interrupt being strictly less than 1 clock tick, but we don't want
543 * that here since we want to appear to be in sync with the clock
544 * interrupt even when we're delayed.
545 */
546 void
547 realitexpire(arg)
548 void *arg;
549 {
550 register struct proc *p;
551 struct timeval ctv, ntv;
552 int s;
553
554 p = (struct proc *)arg;
555 psignal(p, SIGALRM);
556 if (!timevalisset(&p->p_realtimer.it_interval)) {
557 timevalclear(&p->p_realtimer.it_value);
558 return;
559 }
560 for (;;) {
561 s = splclock(); /* XXX: still neeeded ? */
562 timevaladd(&p->p_realtimer.it_value,
563 &p->p_realtimer.it_interval);
564 getmicrouptime(&ctv);
565 if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) {
566 ntv = p->p_realtimer.it_value;
567 timevalsub(&ntv, &ctv);
568 p->p_ithandle = timeout(realitexpire, (caddr_t)p,
569 tvtohz(&ntv) - 1);
570 splx(s);
571 return;
572 }
573 splx(s);
574 }
575 }
576
577 /*
578 * Check that a proposed value to load into the .it_value or
579 * .it_interval part of an interval timer is acceptable, and
580 * fix it to have at least minimal value (i.e. if it is less
581 * than the resolution of the clock, round it up.)
582 */
583 int
584 itimerfix(tv)
585 struct timeval *tv;
586 {
587
588 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
589 tv->tv_usec < 0 || tv->tv_usec >= 1000000)
590 return (EINVAL);
591 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
592 tv->tv_usec = tick;
593 return (0);
594 }
595
596 /*
597 * Decrement an interval timer by a specified number
598 * of microseconds, which must be less than a second,
599 * i.e. < 1000000. If the timer expires, then reload
600 * it. In this case, carry over (usec - old value) to
601 * reduce the value reloaded into the timer so that
602 * the timer does not drift. This routine assumes
603 * that it is called in a context where the timers
604 * on which it is operating cannot change in value.
605 */
606 int
607 itimerdecr(itp, usec)
608 register struct itimerval *itp;
609 int usec;
610 {
611
612 if (itp->it_value.tv_usec < usec) {
613 if (itp->it_value.tv_sec == 0) {
614 /* expired, and already in next interval */
615 usec -= itp->it_value.tv_usec;
616 goto expire;
617 }
618 itp->it_value.tv_usec += 1000000;
619 itp->it_value.tv_sec--;
620 }
621 itp->it_value.tv_usec -= usec;
622 usec = 0;
623 if (timevalisset(&itp->it_value))
624 return (1);
625 /* expired, exactly at end of interval */
626 expire:
627 if (timevalisset(&itp->it_interval)) {
628 itp->it_value = itp->it_interval;
629 itp->it_value.tv_usec -= usec;
630 if (itp->it_value.tv_usec < 0) {
631 itp->it_value.tv_usec += 1000000;
632 itp->it_value.tv_sec--;
633 }
634 } else
635 itp->it_value.tv_usec = 0; /* sec is already 0 */
636 return (0);
637 }
638
639 /*
640 * Add and subtract routines for timevals.
641 * N.B.: subtract routine doesn't deal with
642 * results which are before the beginning,
643 * it just gets very confused in this case.
644 * Caveat emptor.
645 */
646 void
647 timevaladd(t1, t2)
648 struct timeval *t1, *t2;
649 {
650
651 t1->tv_sec += t2->tv_sec;
652 t1->tv_usec += t2->tv_usec;
653 timevalfix(t1);
654 }
655
656 void
657 timevalsub(t1, t2)
658 struct timeval *t1, *t2;
659 {
660
661 t1->tv_sec -= t2->tv_sec;
662 t1->tv_usec -= t2->tv_usec;
663 timevalfix(t1);
664 }
665
666 static void
667 timevalfix(t1)
668 struct timeval *t1;
669 {
670
671 if (t1->tv_usec < 0) {
672 t1->tv_sec--;
673 t1->tv_usec += 1000000;
674 }
675 if (t1->tv_usec >= 1000000) {
676 t1->tv_sec++;
677 t1->tv_usec -= 1000000;
678 }
679 }
680
681 /*
682 * ratecheck(): simple time-based rate-limit checking.
683 */
684 int
685 ratecheck(struct timeval *lasttime, const struct timeval *mininterval)
686 {
687 struct timeval tv, delta;
688 int rv = 0;
689
690 getmicrouptime(&tv); /* NB: 10ms precision */
691 delta = tv;
692 timevalsub(&delta, lasttime);
693
694 /*
695 * check for 0,0 is so that the message will be seen at least once,
696 * even if interval is huge.
697 */
698 if (timevalcmp(&delta, mininterval, >=) ||
699 (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
700 *lasttime = tv;
701 rv = 1;
702 }
703
704 return (rv);
705 }
706
707 /*
708 * ppsratecheck(): packets (or events) per second limitation.
709 *
710 * Return 0 if the limit is to be enforced (e.g. the caller
711 * should drop a packet because of the rate limitation).
712 *
713 * maxpps of 0 always causes zero to be returned. maxpps of -1
714 * always causes 1 to be returned; this effectively defeats rate
715 * limiting.
716 *
717 * Note that we maintain the struct timeval for compatibility
718 * with other bsd systems. We reuse the storage and just monitor
719 * clock ticks for minimal overhead.
720 */
721 int
722 ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
723 {
724 int now;
725
726 /*
727 * Reset the last time and counter if this is the first call
728 * or more than a second has passed since the last update of
729 * lasttime.
730 */
731 now = ticks;
732 if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) {
733 lasttime->tv_sec = now;
734 *curpps = 1;
735 return (maxpps != 0);
736 } else {
737 (*curpps)++; /* NB: ignore potential overflow */
738 return (maxpps < 0 || *curpps < maxpps);
739 }
740 }
741
Cache object: dedcb3fa821c1358b51a047655dea1d8
|