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 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#)kern_time.c 8.1 (Berkeley) 6/10/93 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include "opt_mac.h" 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/lock.h> 40 #include <sys/mutex.h> 41 #include <sys/sysproto.h> 42 #include <sys/resourcevar.h> 43 #include <sys/signalvar.h> 44 #include <sys/kernel.h> 45 #include <sys/mac.h> 46 #include <sys/sysent.h> 47 #include <sys/proc.h> 48 #include <sys/time.h> 49 #include <sys/timetc.h> 50 #include <sys/vnode.h> 51 52 #include <vm/vm.h> 53 #include <vm/vm_extern.h> 54 55 int tz_minuteswest; 56 int tz_dsttime; 57 58 /* 59 * Time of day and interval timer support. 60 * 61 * These routines provide the kernel entry points to get and set 62 * the time-of-day and per-process interval timers. Subroutines 63 * here provide support for adding and subtracting timeval structures 64 * and decrementing interval timers, optionally reloading the interval 65 * timers when they expire. 66 */ 67 68 static int nanosleep1(struct thread *td, struct timespec *rqt, 69 struct timespec *rmt); 70 static int settime(struct thread *, struct timeval *); 71 static void timevalfix(struct timeval *); 72 static void no_lease_updatetime(int); 73 74 static void 75 no_lease_updatetime(deltat) 76 int deltat; 77 { 78 } 79 80 void (*lease_updatetime)(int) = no_lease_updatetime; 81 82 static int 83 settime(struct thread *td, struct timeval *tv) 84 { 85 struct timeval delta, tv1, tv2; 86 static struct timeval maxtime, laststep; 87 struct timespec ts; 88 int s; 89 90 s = splclock(); 91 microtime(&tv1); 92 delta = *tv; 93 timevalsub(&delta, &tv1); 94 95 /* 96 * If the system is secure, we do not allow the time to be 97 * set to a value earlier than 1 second less than the highest 98 * time we have yet seen. The worst a miscreant can do in 99 * this circumstance is "freeze" time. He couldn't go 100 * back to the past. 101 * 102 * We similarly do not allow the clock to be stepped more 103 * than one second, nor more than once per second. This allows 104 * a miscreant to make the clock march double-time, but no worse. 105 */ 106 if (securelevel_gt(td->td_ucred, 1) != 0) { 107 if (delta.tv_sec < 0 || delta.tv_usec < 0) { 108 /* 109 * Update maxtime to latest time we've seen. 110 */ 111 if (tv1.tv_sec > maxtime.tv_sec) 112 maxtime = tv1; 113 tv2 = *tv; 114 timevalsub(&tv2, &maxtime); 115 if (tv2.tv_sec < -1) { 116 tv->tv_sec = maxtime.tv_sec - 1; 117 printf("Time adjustment clamped to -1 second\n"); 118 } 119 } else { 120 if (tv1.tv_sec == laststep.tv_sec) { 121 splx(s); 122 return (EPERM); 123 } 124 if (delta.tv_sec > 1) { 125 tv->tv_sec = tv1.tv_sec + 1; 126 printf("Time adjustment clamped to +1 second\n"); 127 } 128 laststep = *tv; 129 } 130 } 131 132 ts.tv_sec = tv->tv_sec; 133 ts.tv_nsec = tv->tv_usec * 1000; 134 mtx_lock(&Giant); 135 tc_setclock(&ts); 136 (void) splsoftclock(); 137 lease_updatetime(delta.tv_sec); 138 splx(s); 139 resettodr(); 140 mtx_unlock(&Giant); 141 return (0); 142 } 143 144 #ifndef _SYS_SYSPROTO_H_ 145 struct clock_gettime_args { 146 clockid_t clock_id; 147 struct timespec *tp; 148 }; 149 #endif 150 151 /* 152 * MPSAFE 153 */ 154 /* ARGSUSED */ 155 int 156 clock_gettime(struct thread *td, struct clock_gettime_args *uap) 157 { 158 struct timespec ats; 159 struct timeval sys, user; 160 struct proc *p; 161 162 p = td->td_proc; 163 switch (uap->clock_id) { 164 case CLOCK_REALTIME: 165 nanotime(&ats); 166 break; 167 case CLOCK_VIRTUAL: 168 PROC_LOCK(p); 169 calcru(p, &user, &sys); 170 PROC_UNLOCK(p); 171 TIMEVAL_TO_TIMESPEC(&user, &ats); 172 break; 173 case CLOCK_PROF: 174 PROC_LOCK(p); 175 calcru(p, &user, &sys); 176 PROC_UNLOCK(p); 177 timevaladd(&user, &sys); 178 TIMEVAL_TO_TIMESPEC(&user, &ats); 179 break; 180 case CLOCK_MONOTONIC: 181 nanouptime(&ats); 182 break; 183 default: 184 return (EINVAL); 185 } 186 return (copyout(&ats, uap->tp, sizeof(ats))); 187 } 188 189 #ifndef _SYS_SYSPROTO_H_ 190 struct clock_settime_args { 191 clockid_t clock_id; 192 const struct timespec *tp; 193 }; 194 #endif 195 196 /* 197 * MPSAFE 198 */ 199 /* ARGSUSED */ 200 int 201 clock_settime(struct thread *td, struct clock_settime_args *uap) 202 { 203 struct timeval atv; 204 struct timespec ats; 205 int error; 206 207 #ifdef MAC 208 error = mac_check_system_settime(td->td_ucred); 209 if (error) 210 return (error); 211 #endif 212 if ((error = suser(td)) != 0) 213 return (error); 214 if (uap->clock_id != CLOCK_REALTIME) 215 return (EINVAL); 216 if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0) 217 return (error); 218 if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000) 219 return (EINVAL); 220 /* XXX Don't convert nsec->usec and back */ 221 TIMESPEC_TO_TIMEVAL(&atv, &ats); 222 error = settime(td, &atv); 223 return (error); 224 } 225 226 #ifndef _SYS_SYSPROTO_H_ 227 struct clock_getres_args { 228 clockid_t clock_id; 229 struct timespec *tp; 230 }; 231 #endif 232 233 int 234 clock_getres(struct thread *td, struct clock_getres_args *uap) 235 { 236 struct timespec ts; 237 238 ts.tv_sec = 0; 239 switch (uap->clock_id) { 240 case CLOCK_REALTIME: 241 case CLOCK_MONOTONIC: 242 /* 243 * Round up the result of the division cheaply by adding 1. 244 * Rounding up is especially important if rounding down 245 * would give 0. Perfect rounding is unimportant. 246 */ 247 ts.tv_nsec = 1000000000 / tc_getfrequency() + 1; 248 break; 249 case CLOCK_VIRTUAL: 250 case CLOCK_PROF: 251 /* Accurately round up here because we can do so cheaply. */ 252 ts.tv_nsec = (1000000000 + hz - 1) / hz; 253 break; 254 default: 255 return (EINVAL); 256 } 257 if (uap->tp == NULL) 258 return (0); 259 return (copyout(&ts, uap->tp, sizeof(ts))); 260 } 261 262 static int nanowait; 263 264 static int 265 nanosleep1(struct thread *td, struct timespec *rqt, struct timespec *rmt) 266 { 267 struct timespec ts, ts2, ts3; 268 struct timeval tv; 269 int error; 270 271 if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) 272 return (EINVAL); 273 if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) 274 return (0); 275 getnanouptime(&ts); 276 timespecadd(&ts, rqt); 277 TIMESPEC_TO_TIMEVAL(&tv, rqt); 278 for (;;) { 279 error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", 280 tvtohz(&tv)); 281 getnanouptime(&ts2); 282 if (error != EWOULDBLOCK) { 283 if (error == ERESTART) 284 error = EINTR; 285 if (rmt != NULL) { 286 timespecsub(&ts, &ts2); 287 if (ts.tv_sec < 0) 288 timespecclear(&ts); 289 *rmt = ts; 290 } 291 return (error); 292 } 293 if (timespeccmp(&ts2, &ts, >=)) 294 return (0); 295 ts3 = ts; 296 timespecsub(&ts3, &ts2); 297 TIMESPEC_TO_TIMEVAL(&tv, &ts3); 298 } 299 } 300 301 #ifndef _SYS_SYSPROTO_H_ 302 struct nanosleep_args { 303 struct timespec *rqtp; 304 struct timespec *rmtp; 305 }; 306 #endif 307 308 /* 309 * MPSAFE 310 */ 311 /* ARGSUSED */ 312 int 313 nanosleep(struct thread *td, struct nanosleep_args *uap) 314 { 315 struct timespec rmt, rqt; 316 int error; 317 318 error = copyin(uap->rqtp, &rqt, sizeof(rqt)); 319 if (error) 320 return (error); 321 322 if (uap->rmtp && 323 !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 324 return (EFAULT); 325 error = nanosleep1(td, &rqt, &rmt); 326 if (error && uap->rmtp) { 327 int error2; 328 329 error2 = copyout(&rmt, uap->rmtp, sizeof(rmt)); 330 if (error2) 331 error = error2; 332 } 333 return (error); 334 } 335 336 #ifndef _SYS_SYSPROTO_H_ 337 struct gettimeofday_args { 338 struct timeval *tp; 339 struct timezone *tzp; 340 }; 341 #endif 342 /* 343 * MPSAFE 344 */ 345 /* ARGSUSED */ 346 int 347 gettimeofday(struct thread *td, struct gettimeofday_args *uap) 348 { 349 struct timeval atv; 350 struct timezone rtz; 351 int error = 0; 352 353 if (uap->tp) { 354 microtime(&atv); 355 error = copyout(&atv, uap->tp, sizeof (atv)); 356 } 357 if (error == 0 && uap->tzp != NULL) { 358 rtz.tz_minuteswest = tz_minuteswest; 359 rtz.tz_dsttime = tz_dsttime; 360 error = copyout(&rtz, uap->tzp, sizeof (rtz)); 361 } 362 return (error); 363 } 364 365 #ifndef _SYS_SYSPROTO_H_ 366 struct settimeofday_args { 367 struct timeval *tv; 368 struct timezone *tzp; 369 }; 370 #endif 371 /* 372 * MPSAFE 373 */ 374 /* ARGSUSED */ 375 int 376 settimeofday(struct thread *td, struct settimeofday_args *uap) 377 { 378 struct timeval atv; 379 struct timezone atz; 380 int error = 0; 381 382 #ifdef MAC 383 error = mac_check_system_settime(td->td_ucred); 384 if (error) 385 return (error); 386 #endif 387 if ((error = suser(td))) 388 return (error); 389 /* Verify all parameters before changing time. */ 390 if (uap->tv) { 391 if ((error = copyin(uap->tv, &atv, sizeof(atv)))) 392 return (error); 393 if (atv.tv_usec < 0 || atv.tv_usec >= 1000000) 394 return (EINVAL); 395 } 396 if (uap->tzp && 397 (error = copyin(uap->tzp, &atz, sizeof(atz)))) 398 return (error); 399 400 if (uap->tv && (error = settime(td, &atv))) 401 return (error); 402 if (uap->tzp) { 403 tz_minuteswest = atz.tz_minuteswest; 404 tz_dsttime = atz.tz_dsttime; 405 } 406 return (error); 407 } 408 /* 409 * Get value of an interval timer. The process virtual and 410 * profiling virtual time timers are kept in the p_stats area, since 411 * they can be swapped out. These are kept internally in the 412 * way they are specified externally: in time until they expire. 413 * 414 * The real time interval timer is kept in the process table slot 415 * for the process, and its value (it_value) is kept as an 416 * absolute time rather than as a delta, so that it is easy to keep 417 * periodic real-time signals from drifting. 418 * 419 * Virtual time timers are processed in the hardclock() routine of 420 * kern_clock.c. The real time timer is processed by a timeout 421 * routine, called from the softclock() routine. Since a callout 422 * may be delayed in real time due to interrupt processing in the system, 423 * it is possible for the real time timeout routine (realitexpire, given below), 424 * to be delayed in real time past when it is supposed to occur. It 425 * does not suffice, therefore, to reload the real timer .it_value from the 426 * real time timers .it_interval. Rather, we compute the next time in 427 * absolute time the timer should go off. 428 */ 429 #ifndef _SYS_SYSPROTO_H_ 430 struct getitimer_args { 431 u_int which; 432 struct itimerval *itv; 433 }; 434 #endif 435 /* 436 * MPSAFE 437 */ 438 int 439 getitimer(struct thread *td, struct getitimer_args *uap) 440 { 441 struct proc *p = td->td_proc; 442 struct timeval ctv; 443 struct itimerval aitv; 444 445 if (uap->which > ITIMER_PROF) 446 return (EINVAL); 447 448 if (uap->which == ITIMER_REAL) { 449 /* 450 * Convert from absolute to relative time in .it_value 451 * part of real time timer. If time for real time timer 452 * has passed return 0, else return difference between 453 * current time and time for the timer to go off. 454 */ 455 PROC_LOCK(p); 456 aitv = p->p_realtimer; 457 PROC_UNLOCK(p); 458 if (timevalisset(&aitv.it_value)) { 459 getmicrouptime(&ctv); 460 if (timevalcmp(&aitv.it_value, &ctv, <)) 461 timevalclear(&aitv.it_value); 462 else 463 timevalsub(&aitv.it_value, &ctv); 464 } 465 } else { 466 mtx_lock_spin(&sched_lock); 467 aitv = p->p_stats->p_timer[uap->which]; 468 mtx_unlock_spin(&sched_lock); 469 } 470 return (copyout(&aitv, uap->itv, sizeof (struct itimerval))); 471 } 472 473 #ifndef _SYS_SYSPROTO_H_ 474 struct setitimer_args { 475 u_int which; 476 struct itimerval *itv, *oitv; 477 }; 478 #endif 479 /* 480 * MPSAFE 481 */ 482 int 483 setitimer(struct thread *td, struct setitimer_args *uap) 484 { 485 struct proc *p = td->td_proc; 486 struct itimerval aitv, oitv; 487 struct timeval ctv; 488 int error; 489 490 if (uap->itv == NULL) { 491 uap->itv = uap->oitv; 492 return (getitimer(td, (struct getitimer_args *)uap)); 493 } 494 495 if (uap->which > ITIMER_PROF) 496 return (EINVAL); 497 if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval)))) 498 return (error); 499 if (itimerfix(&aitv.it_value)) 500 return (EINVAL); 501 if (!timevalisset(&aitv.it_value)) 502 timevalclear(&aitv.it_interval); 503 else if (itimerfix(&aitv.it_interval)) 504 return (EINVAL); 505 506 if (uap->which == ITIMER_REAL) { 507 PROC_LOCK(p); 508 if (timevalisset(&p->p_realtimer.it_value)) 509 callout_stop(&p->p_itcallout); 510 getmicrouptime(&ctv); 511 if (timevalisset(&aitv.it_value)) { 512 callout_reset(&p->p_itcallout, tvtohz(&aitv.it_value), 513 realitexpire, p); 514 timevaladd(&aitv.it_value, &ctv); 515 } 516 oitv = p->p_realtimer; 517 p->p_realtimer = aitv; 518 PROC_UNLOCK(p); 519 if (timevalisset(&oitv.it_value)) { 520 if (timevalcmp(&oitv.it_value, &ctv, <)) 521 timevalclear(&oitv.it_value); 522 else 523 timevalsub(&oitv.it_value, &ctv); 524 } 525 } else { 526 mtx_lock_spin(&sched_lock); 527 oitv = p->p_stats->p_timer[uap->which]; 528 p->p_stats->p_timer[uap->which] = aitv; 529 mtx_unlock_spin(&sched_lock); 530 } 531 if (uap->oitv == NULL) 532 return (0); 533 return (copyout(&oitv, uap->oitv, sizeof(struct itimerval))); 534 } 535 536 /* 537 * Real interval timer expired: 538 * send process whose timer expired an alarm signal. 539 * If time is not set up to reload, then just return. 540 * Else compute next time timer should go off which is > current time. 541 * This is where delay in processing this timeout causes multiple 542 * SIGALRM calls to be compressed into one. 543 * tvtohz() always adds 1 to allow for the time until the next clock 544 * interrupt being strictly less than 1 clock tick, but we don't want 545 * that here since we want to appear to be in sync with the clock 546 * interrupt even when we're delayed. 547 */ 548 void 549 realitexpire(void *arg) 550 { 551 struct proc *p; 552 struct timeval ctv, ntv; 553 554 p = (struct proc *)arg; 555 PROC_LOCK(p); 556 psignal(p, SIGALRM); 557 if (!timevalisset(&p->p_realtimer.it_interval)) { 558 timevalclear(&p->p_realtimer.it_value); 559 if (p->p_flag & P_WEXIT) 560 wakeup(&p->p_itcallout); 561 PROC_UNLOCK(p); 562 return; 563 } 564 for (;;) { 565 timevaladd(&p->p_realtimer.it_value, 566 &p->p_realtimer.it_interval); 567 getmicrouptime(&ctv); 568 if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) { 569 ntv = p->p_realtimer.it_value; 570 timevalsub(&ntv, &ctv); 571 callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1, 572 realitexpire, p); 573 PROC_UNLOCK(p); 574 return; 575 } 576 } 577 /*NOTREACHED*/ 578 } 579 580 /* 581 * Check that a proposed value to load into the .it_value or 582 * .it_interval part of an interval timer is acceptable, and 583 * fix it to have at least minimal value (i.e. if it is less 584 * than the resolution of the clock, round it up.) 585 */ 586 int 587 itimerfix(struct timeval *tv) 588 { 589 590 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 591 tv->tv_usec < 0 || tv->tv_usec >= 1000000) 592 return (EINVAL); 593 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 594 tv->tv_usec = tick; 595 return (0); 596 } 597 598 /* 599 * Decrement an interval timer by a specified number 600 * of microseconds, which must be less than a second, 601 * i.e. < 1000000. If the timer expires, then reload 602 * it. In this case, carry over (usec - old value) to 603 * reduce the value reloaded into the timer so that 604 * the timer does not drift. This routine assumes 605 * that it is called in a context where the timers 606 * on which it is operating cannot change in value. 607 */ 608 int 609 itimerdecr(struct itimerval *itp, 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(struct timeval *t1, const struct timeval *t2) 648 { 649 650 t1->tv_sec += t2->tv_sec; 651 t1->tv_usec += t2->tv_usec; 652 timevalfix(t1); 653 } 654 655 void 656 timevalsub(struct timeval *t1, const struct timeval *t2) 657 { 658 659 t1->tv_sec -= t2->tv_sec; 660 t1->tv_usec -= t2->tv_usec; 661 timevalfix(t1); 662 } 663 664 static void 665 timevalfix(struct timeval *t1) 666 { 667 668 if (t1->tv_usec < 0) { 669 t1->tv_sec--; 670 t1->tv_usec += 1000000; 671 } 672 if (t1->tv_usec >= 1000000) { 673 t1->tv_sec++; 674 t1->tv_usec -= 1000000; 675 } 676 } 677 678 /* 679 * ratecheck(): simple time-based rate-limit checking. 680 */ 681 int 682 ratecheck(struct timeval *lasttime, const struct timeval *mininterval) 683 { 684 struct timeval tv, delta; 685 int rv = 0; 686 687 getmicrouptime(&tv); /* NB: 10ms precision */ 688 delta = tv; 689 timevalsub(&delta, lasttime); 690 691 /* 692 * check for 0,0 is so that the message will be seen at least once, 693 * even if interval is huge. 694 */ 695 if (timevalcmp(&delta, mininterval, >=) || 696 (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 697 *lasttime = tv; 698 rv = 1; 699 } 700 701 return (rv); 702 } 703 704 /* 705 * ppsratecheck(): packets (or events) per second limitation. 706 * 707 * Return 0 if the limit is to be enforced (e.g. the caller 708 * should drop a packet because of the rate limitation). 709 * 710 * maxpps of 0 always causes zero to be returned. maxpps of -1 711 * always causes 1 to be returned; this effectively defeats rate 712 * limiting. 713 * 714 * Note that we maintain the struct timeval for compatibility 715 * with other bsd systems. We reuse the storage and just monitor 716 * clock ticks for minimal overhead. 717 */ 718 int 719 ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 720 { 721 int now; 722 723 /* 724 * Reset the last time and counter if this is the first call 725 * or more than a second has passed since the last update of 726 * lasttime. 727 */ 728 now = ticks; 729 if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { 730 lasttime->tv_sec = now; 731 *curpps = 1; 732 return (maxpps != 0); 733 } else { 734 (*curpps)++; /* NB: ignore potential overflow */ 735 return (maxpps < 0 || *curpps < maxpps); 736 } 737 } 738