kern_time.c revision 1.98 1 /* $NetBSD: kern_time.c,v 1.98 2005/12/05 00:16:34 christos Exp $ */
2
3 /*-
4 * Copyright (c) 2000, 2004, 2005 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. Neither the name of the University nor the names of its contributors
52 * may be used to endorse or promote products derived from this software
53 * without specific prior written permission.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * SUCH DAMAGE.
66 *
67 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95
68 */
69
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.98 2005/12/05 00:16:34 christos Exp $");
72
73 #include "fs_nfs.h"
74 #include "opt_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/sa.h>
83 #include <sys/savar.h>
84 #include <sys/vnode.h>
85 #include <sys/signalvar.h>
86 #include <sys/syslog.h>
87 #include <sys/timevar.h>
88
89 #include <sys/mount.h>
90 #include <sys/syscallargs.h>
91
92 #include <uvm/uvm_extern.h>
93
94 #if defined(NFS) || defined(NFSSERVER)
95 #include <nfs/rpcv2.h>
96 #include <nfs/nfsproto.h>
97 #include <nfs/nfs.h>
98 #include <nfs/nfs_var.h>
99 #endif
100
101 #include <machine/cpu.h>
102
103 POOL_INIT(ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl",
104 &pool_allocator_nointr);
105 POOL_INIT(ptimers_pool, sizeof(struct ptimers), 0, 0, 0, "ptimerspl",
106 &pool_allocator_nointr);
107
108 static void timerupcall(struct lwp *, void *);
109
110 /* Time of day and interval timer support.
111 *
112 * These routines provide the kernel entry points to get and set
113 * the time-of-day and per-process interval timers. Subroutines
114 * here provide support for adding and subtracting timeval structures
115 * and decrementing interval timers, optionally reloading the interval
116 * timers when they expire.
117 */
118
119 /* This function is used by clock_settime and settimeofday */
120 int
121 settime(struct proc *p, struct timespec *ts)
122 {
123 struct timeval delta, tv;
124 struct cpu_info *ci;
125 int s;
126
127 /*
128 * Don't allow the time to be set forward so far it will wrap
129 * and become negative, thus allowing an attacker to bypass
130 * the next check below. The cutoff is 1 year before rollover
131 * occurs, so even if the attacker uses adjtime(2) to move
132 * the time past the cutoff, it will take a very long time
133 * to get to the wrap point.
134 *
135 * XXX: we check against INT_MAX since on 64-bit
136 * platforms, sizeof(int) != sizeof(long) and
137 * time_t is 32 bits even when atv.tv_sec is 64 bits.
138 */
139 if (ts->tv_sec > INT_MAX - 365*24*60*60) {
140 struct proc *pp = p->p_pptr;
141 log(LOG_WARNING, "pid %d (%s) "
142 "invoked by uid %d ppid %d (%s) "
143 "tried to set clock forward to %ld\n",
144 p->p_pid, p->p_comm, pp->p_ucred->cr_uid,
145 pp->p_pid, pp->p_comm, (long)ts->tv_sec);
146 return (EPERM);
147 }
148 TIMESPEC_TO_TIMEVAL(&tv, ts);
149
150 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
151 s = splclock();
152 timersub(&tv, &time, &delta);
153 if ((delta.tv_sec < 0 || delta.tv_usec < 0) && securelevel > 1) {
154 splx(s);
155 return (EPERM);
156 }
157 #ifdef notyet
158 if ((delta.tv_sec < 86400) && securelevel > 0) {
159 splx(s);
160 return (EPERM);
161 }
162 #endif
163 time = tv;
164 (void) spllowersoftclock();
165 timeradd(&boottime, &delta, &boottime);
166 /*
167 * XXXSMP
168 * This is wrong. We should traverse a list of all
169 * CPUs and add the delta to the runtime of those
170 * CPUs which have a process on them.
171 */
172 ci = curcpu();
173 timeradd(&ci->ci_schedstate.spc_runtime, &delta,
174 &ci->ci_schedstate.spc_runtime);
175 # if (defined(NFS) && !defined (NFS_V2_ONLY)) || defined(NFSSERVER)
176 nqnfs_lease_updatetime(delta.tv_sec);
177 # endif
178 splx(s);
179 resettodr();
180 return (0);
181 }
182
183 /* ARGSUSED */
184 int
185 sys_clock_gettime(struct lwp *l, void *v, register_t *retval)
186 {
187 struct sys_clock_gettime_args /* {
188 syscallarg(clockid_t) clock_id;
189 syscallarg(struct timespec *) tp;
190 } */ *uap = v;
191 clockid_t clock_id;
192 struct timeval atv;
193 struct timespec ats;
194 int s;
195
196 clock_id = SCARG(uap, clock_id);
197 switch (clock_id) {
198 case CLOCK_REALTIME:
199 nanotime(&ats);
200 break;
201 case CLOCK_MONOTONIC:
202 /* XXX "hz" granularity */
203 s = splclock();
204 atv = mono_time;
205 splx(s);
206 TIMEVAL_TO_TIMESPEC(&atv,&ats);
207 break;
208 default:
209 return (EINVAL);
210 }
211
212 return copyout(&ats, SCARG(uap, tp), sizeof(ats));
213 }
214
215 /* ARGSUSED */
216 int
217 sys_clock_settime(struct lwp *l, void *v, register_t *retval)
218 {
219 struct sys_clock_settime_args /* {
220 syscallarg(clockid_t) clock_id;
221 syscallarg(const struct timespec *) tp;
222 } */ *uap = v;
223 struct proc *p = l->l_proc;
224 int error;
225
226 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
227 return (error);
228
229 return (clock_settime1(p, SCARG(uap, clock_id), SCARG(uap, tp)));
230 }
231
232
233 int
234 clock_settime1(struct proc *p, clockid_t clock_id, const struct timespec *tp)
235 {
236 struct timespec ats;
237 int error;
238
239 if ((error = copyin(tp, &ats, sizeof(ats))) != 0)
240 return (error);
241
242 switch (clock_id) {
243 case CLOCK_REALTIME:
244 if ((error = settime(p, &ats)) != 0)
245 return (error);
246 break;
247 case CLOCK_MONOTONIC:
248 return (EINVAL); /* read-only clock */
249 default:
250 return (EINVAL);
251 }
252
253 return 0;
254 }
255
256 int
257 sys_clock_getres(struct lwp *l, void *v, register_t *retval)
258 {
259 struct sys_clock_getres_args /* {
260 syscallarg(clockid_t) clock_id;
261 syscallarg(struct timespec *) tp;
262 } */ *uap = v;
263 clockid_t clock_id;
264 struct timespec ts;
265 int error = 0;
266
267 clock_id = SCARG(uap, clock_id);
268 switch (clock_id) {
269 case CLOCK_REALTIME:
270 case CLOCK_MONOTONIC:
271 ts.tv_sec = 0;
272 ts.tv_nsec = 1000000000 / hz;
273 break;
274 default:
275 return (EINVAL);
276 }
277
278 if (SCARG(uap, tp))
279 error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
280
281 return error;
282 }
283
284 /* ARGSUSED */
285 int
286 sys_nanosleep(struct lwp *l, void *v, register_t *retval)
287 {
288 static int nanowait;
289 struct sys_nanosleep_args/* {
290 syscallarg(struct timespec *) rqtp;
291 syscallarg(struct timespec *) rmtp;
292 } */ *uap = v;
293 struct timespec rqt;
294 struct timespec rmt;
295 struct timeval atv, utv;
296 int error, s, timo;
297
298 error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec));
299 if (error)
300 return (error);
301
302 TIMESPEC_TO_TIMEVAL(&atv,&rqt);
303 if (itimerfix(&atv))
304 return (EINVAL);
305
306 s = splclock();
307 timeradd(&atv,&time,&atv);
308 timo = hzto(&atv);
309 /*
310 * Avoid inadvertantly sleeping forever
311 */
312 if (timo == 0)
313 timo = 1;
314 splx(s);
315
316 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
317 if (error == ERESTART)
318 error = EINTR;
319 if (error == EWOULDBLOCK)
320 error = 0;
321
322 if (SCARG(uap, rmtp)) {
323 int error1;
324
325 s = splclock();
326 utv = time;
327 splx(s);
328
329 timersub(&atv, &utv, &utv);
330 if (utv.tv_sec < 0)
331 timerclear(&utv);
332
333 TIMEVAL_TO_TIMESPEC(&utv,&rmt);
334 error1 = copyout((caddr_t)&rmt, (caddr_t)SCARG(uap,rmtp),
335 sizeof(rmt));
336 if (error1)
337 return (error1);
338 }
339
340 return error;
341 }
342
343 /* ARGSUSED */
344 int
345 sys_gettimeofday(struct lwp *l, void *v, register_t *retval)
346 {
347 struct sys_gettimeofday_args /* {
348 syscallarg(struct timeval *) tp;
349 syscallarg(void *) tzp; really "struct timezone *"
350 } */ *uap = v;
351 struct timeval atv;
352 int error = 0;
353 struct timezone tzfake;
354
355 if (SCARG(uap, tp)) {
356 microtime(&atv);
357 error = copyout(&atv, SCARG(uap, tp), sizeof(atv));
358 if (error)
359 return (error);
360 }
361 if (SCARG(uap, tzp)) {
362 /*
363 * NetBSD has no kernel notion of time zone, so we just
364 * fake up a timezone struct and return it if demanded.
365 */
366 tzfake.tz_minuteswest = 0;
367 tzfake.tz_dsttime = 0;
368 error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake));
369 }
370 return (error);
371 }
372
373 /* ARGSUSED */
374 int
375 sys_settimeofday(struct lwp *l, void *v, register_t *retval)
376 {
377 struct sys_settimeofday_args /* {
378 syscallarg(const struct timeval *) tv;
379 syscallarg(const void *) tzp; really "const struct timezone *"
380 } */ *uap = v;
381 struct proc *p = l->l_proc;
382 int error;
383
384 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
385 return (error);
386
387 return settimeofday1(SCARG(uap, tv), SCARG(uap, tzp), p);
388 }
389
390 int
391 settimeofday1(const struct timeval *utv, const struct timezone *utzp,
392 struct proc *p)
393 {
394 struct timeval atv;
395 struct timespec ts;
396 int error;
397
398 /* Verify all parameters before changing time. */
399 /*
400 * NetBSD has no kernel notion of time zone, and only an
401 * obsolete program would try to set it, so we log a warning.
402 */
403 if (utzp)
404 log(LOG_WARNING, "pid %d attempted to set the "
405 "(obsolete) kernel time zone\n", p->p_pid);
406
407 if (utv == NULL)
408 return 0;
409
410 if ((error = copyin(utv, &atv, sizeof(atv))) != 0)
411 return error;
412 TIMEVAL_TO_TIMESPEC(&atv, &ts);
413 return settime(p, &ts);
414 }
415
416 int tickdelta; /* current clock skew, us. per tick */
417 long timedelta; /* unapplied time correction, us. */
418 long bigadj = 1000000; /* use 10x skew above bigadj us. */
419 int time_adjusted; /* set if an adjustment is made */
420
421 /* ARGSUSED */
422 int
423 sys_adjtime(struct lwp *l, void *v, register_t *retval)
424 {
425 struct sys_adjtime_args /* {
426 syscallarg(const struct timeval *) delta;
427 syscallarg(struct timeval *) olddelta;
428 } */ *uap = v;
429 struct proc *p = l->l_proc;
430 int error;
431
432 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
433 return (error);
434
435 return adjtime1(SCARG(uap, delta), SCARG(uap, olddelta), p);
436 }
437
438 int
439 adjtime1(const struct timeval *delta, struct timeval *olddelta, struct proc *p)
440 {
441 struct timeval atv;
442 long ndelta, ntickdelta, odelta;
443 int error;
444 int s;
445
446 error = copyin(delta, &atv, sizeof(struct timeval));
447 if (error)
448 return (error);
449
450 /*
451 * Compute the total correction and the rate at which to apply it.
452 * Round the adjustment down to a whole multiple of the per-tick
453 * delta, so that after some number of incremental changes in
454 * hardclock(), tickdelta will become zero, lest the correction
455 * overshoot and start taking us away from the desired final time.
456 */
457 ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
458 if (ndelta > bigadj || ndelta < -bigadj)
459 ntickdelta = 10 * tickadj;
460 else
461 ntickdelta = tickadj;
462 if (ndelta % ntickdelta)
463 ndelta = ndelta / ntickdelta * ntickdelta;
464
465 /*
466 * To make hardclock()'s job easier, make the per-tick delta negative
467 * if we want time to run slower; then hardclock can simply compute
468 * tick + tickdelta, and subtract tickdelta from timedelta.
469 */
470 if (ndelta < 0)
471 ntickdelta = -ntickdelta;
472 if (ndelta != 0)
473 /* We need to save the system clock time during shutdown */
474 time_adjusted |= 1;
475 s = splclock();
476 odelta = timedelta;
477 timedelta = ndelta;
478 tickdelta = ntickdelta;
479 splx(s);
480
481 if (olddelta) {
482 atv.tv_sec = odelta / 1000000;
483 atv.tv_usec = odelta % 1000000;
484 error = copyout(&atv, olddelta, sizeof(struct timeval));
485 }
486 return error;
487 }
488
489 /*
490 * Interval timer support. Both the BSD getitimer() family and the POSIX
491 * timer_*() family of routines are supported.
492 *
493 * All timers are kept in an array pointed to by p_timers, which is
494 * allocated on demand - many processes don't use timers at all. The
495 * first three elements in this array are reserved for the BSD timers:
496 * element 0 is ITIMER_REAL, element 1 is ITIMER_VIRTUAL, and element
497 * 2 is ITIMER_PROF. The rest may be allocated by the timer_create()
498 * syscall.
499 *
500 * Realtime timers are kept in the ptimer structure as an absolute
501 * time; virtual time timers are kept as a linked list of deltas.
502 * Virtual time timers are processed in the hardclock() routine of
503 * kern_clock.c. The real time timer is processed by a callout
504 * routine, called from the softclock() routine. Since a callout may
505 * be delayed in real time due to interrupt processing in the system,
506 * it is possible for the real time timeout routine (realtimeexpire,
507 * given below), to be delayed in real time past when it is supposed
508 * to occur. It does not suffice, therefore, to reload the real timer
509 * .it_value from the real time timers .it_interval. Rather, we
510 * compute the next time in absolute time the timer should go off. */
511
512 /* Allocate a POSIX realtime timer. */
513 int
514 sys_timer_create(struct lwp *l, void *v, register_t *retval)
515 {
516 struct sys_timer_create_args /* {
517 syscallarg(clockid_t) clock_id;
518 syscallarg(struct sigevent *) evp;
519 syscallarg(timer_t *) timerid;
520 } */ *uap = v;
521
522 return timer_create1(SCARG(uap, timerid), SCARG(uap, clock_id),
523 SCARG(uap, evp), copyin, l->l_proc);
524 }
525
526 int
527 timer_create1(timer_t *tid, clockid_t id, struct sigevent *evp,
528 copyin_t fetch_event, struct proc *p)
529 {
530 int error;
531 timer_t timerid;
532 struct ptimer *pt;
533
534 if (id < CLOCK_REALTIME ||
535 id > CLOCK_PROF)
536 return (EINVAL);
537
538 if (p->p_timers == NULL)
539 timers_alloc(p);
540
541 /* Find a free timer slot, skipping those reserved for setitimer(). */
542 for (timerid = 3; timerid < TIMER_MAX; timerid++)
543 if (p->p_timers->pts_timers[timerid] == NULL)
544 break;
545
546 if (timerid == TIMER_MAX)
547 return EAGAIN;
548
549 pt = pool_get(&ptimer_pool, PR_WAITOK);
550 if (evp) {
551 if (((error =
552 (*fetch_event)(evp, &pt->pt_ev, sizeof(pt->pt_ev))) != 0) ||
553 ((pt->pt_ev.sigev_notify < SIGEV_NONE) ||
554 (pt->pt_ev.sigev_notify > SIGEV_SA))) {
555 pool_put(&ptimer_pool, pt);
556 return (error ? error : EINVAL);
557 }
558 } else {
559 pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
560 switch (id) {
561 case CLOCK_REALTIME:
562 pt->pt_ev.sigev_signo = SIGALRM;
563 break;
564 case CLOCK_VIRTUAL:
565 pt->pt_ev.sigev_signo = SIGVTALRM;
566 break;
567 case CLOCK_PROF:
568 pt->pt_ev.sigev_signo = SIGPROF;
569 break;
570 }
571 pt->pt_ev.sigev_value.sival_int = timerid;
572 }
573 pt->pt_info.ksi_signo = pt->pt_ev.sigev_signo;
574 pt->pt_info.ksi_errno = 0;
575 pt->pt_info.ksi_code = 0;
576 pt->pt_info.ksi_pid = p->p_pid;
577 pt->pt_info.ksi_uid = p->p_cred->p_ruid;
578 pt->pt_info.ksi_sigval = pt->pt_ev.sigev_value;
579
580 pt->pt_type = id;
581 pt->pt_proc = p;
582 pt->pt_overruns = 0;
583 pt->pt_poverruns = 0;
584 pt->pt_entry = timerid;
585 timerclear(&pt->pt_time.it_value);
586 if (id == CLOCK_REALTIME)
587 callout_init(&pt->pt_ch);
588 else
589 pt->pt_active = 0;
590
591 p->p_timers->pts_timers[timerid] = pt;
592
593 return copyout(&timerid, tid, sizeof(timerid));
594 }
595
596 /* Delete a POSIX realtime timer */
597 int
598 sys_timer_delete(struct lwp *l, void *v, register_t *retval)
599 {
600 struct sys_timer_delete_args /* {
601 syscallarg(timer_t) timerid;
602 } */ *uap = v;
603 struct proc *p = l->l_proc;
604 timer_t timerid;
605 struct ptimer *pt, *ptn;
606 int s;
607
608 timerid = SCARG(uap, timerid);
609
610 if ((p->p_timers == NULL) ||
611 (timerid < 2) || (timerid >= TIMER_MAX) ||
612 ((pt = p->p_timers->pts_timers[timerid]) == NULL))
613 return (EINVAL);
614
615 if (pt->pt_type == CLOCK_REALTIME)
616 callout_stop(&pt->pt_ch);
617 else if (pt->pt_active) {
618 s = splclock();
619 ptn = LIST_NEXT(pt, pt_list);
620 LIST_REMOVE(pt, pt_list);
621 for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
622 timeradd(&pt->pt_time.it_value, &ptn->pt_time.it_value,
623 &ptn->pt_time.it_value);
624 splx(s);
625 }
626
627 p->p_timers->pts_timers[timerid] = NULL;
628 pool_put(&ptimer_pool, pt);
629
630 return (0);
631 }
632
633 /*
634 * Set up the given timer. The value in pt->pt_time.it_value is taken
635 * to be an absolute time for CLOCK_REALTIME timers and a relative
636 * time for virtual timers.
637 * Must be called at splclock().
638 */
639 void
640 timer_settime(struct ptimer *pt)
641 {
642 struct ptimer *ptn, *pptn;
643 struct ptlist *ptl;
644
645 if (pt->pt_type == CLOCK_REALTIME) {
646 callout_stop(&pt->pt_ch);
647 if (timerisset(&pt->pt_time.it_value)) {
648 /*
649 * Don't need to check hzto() return value, here.
650 * callout_reset() does it for us.
651 */
652 callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value),
653 realtimerexpire, pt);
654 }
655 } else {
656 if (pt->pt_active) {
657 ptn = LIST_NEXT(pt, pt_list);
658 LIST_REMOVE(pt, pt_list);
659 for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list))
660 timeradd(&pt->pt_time.it_value,
661 &ptn->pt_time.it_value,
662 &ptn->pt_time.it_value);
663 }
664 if (timerisset(&pt->pt_time.it_value)) {
665 if (pt->pt_type == CLOCK_VIRTUAL)
666 ptl = &pt->pt_proc->p_timers->pts_virtual;
667 else
668 ptl = &pt->pt_proc->p_timers->pts_prof;
669
670 for (ptn = LIST_FIRST(ptl), pptn = NULL;
671 ptn && timercmp(&pt->pt_time.it_value,
672 &ptn->pt_time.it_value, >);
673 pptn = ptn, ptn = LIST_NEXT(ptn, pt_list))
674 timersub(&pt->pt_time.it_value,
675 &ptn->pt_time.it_value,
676 &pt->pt_time.it_value);
677
678 if (pptn)
679 LIST_INSERT_AFTER(pptn, pt, pt_list);
680 else
681 LIST_INSERT_HEAD(ptl, pt, pt_list);
682
683 for ( ; ptn ; ptn = LIST_NEXT(ptn, pt_list))
684 timersub(&ptn->pt_time.it_value,
685 &pt->pt_time.it_value,
686 &ptn->pt_time.it_value);
687
688 pt->pt_active = 1;
689 } else
690 pt->pt_active = 0;
691 }
692 }
693
694 void
695 timer_gettime(struct ptimer *pt, struct itimerval *aitv)
696 {
697 struct ptimer *ptn;
698
699 *aitv = pt->pt_time;
700 if (pt->pt_type == CLOCK_REALTIME) {
701 /*
702 * Convert from absolute to relative time in .it_value
703 * part of real time timer. If time for real time
704 * timer has passed return 0, else return difference
705 * between current time and time for the timer to go
706 * off.
707 */
708 if (timerisset(&aitv->it_value)) {
709 if (timercmp(&aitv->it_value, &time, <))
710 timerclear(&aitv->it_value);
711 else
712 timersub(&aitv->it_value, &time,
713 &aitv->it_value);
714 }
715 } else if (pt->pt_active) {
716 if (pt->pt_type == CLOCK_VIRTUAL)
717 ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_virtual);
718 else
719 ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_prof);
720 for ( ; ptn && ptn != pt; ptn = LIST_NEXT(ptn, pt_list))
721 timeradd(&aitv->it_value,
722 &ptn->pt_time.it_value, &aitv->it_value);
723 KASSERT(ptn != NULL); /* pt should be findable on the list */
724 } else
725 timerclear(&aitv->it_value);
726 }
727
728
729
730 /* Set and arm a POSIX realtime timer */
731 int
732 sys_timer_settime(struct lwp *l, void *v, register_t *retval)
733 {
734 struct sys_timer_settime_args /* {
735 syscallarg(timer_t) timerid;
736 syscallarg(int) flags;
737 syscallarg(const struct itimerspec *) value;
738 syscallarg(struct itimerspec *) ovalue;
739 } */ *uap = v;
740 int error;
741 struct itimerspec value, ovalue, *ovp = NULL;
742
743 if ((error = copyin(SCARG(uap, value), &value,
744 sizeof(struct itimerspec))) != 0)
745 return (error);
746
747 if (SCARG(uap, ovalue))
748 ovp = &ovalue;
749
750 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp,
751 SCARG(uap, flags), l->l_proc)) != 0)
752 return error;
753
754 if (ovp)
755 return copyout(&ovalue, SCARG(uap, ovalue),
756 sizeof(struct itimerspec));
757 return 0;
758 }
759
760 int
761 dotimer_settime(int timerid, struct itimerspec *value,
762 struct itimerspec *ovalue, int flags, struct proc *p)
763 {
764 int s;
765 struct itimerval val, oval;
766 struct ptimer *pt;
767
768 if ((p->p_timers == NULL) ||
769 (timerid < 2) || (timerid >= TIMER_MAX) ||
770 ((pt = p->p_timers->pts_timers[timerid]) == NULL))
771 return (EINVAL);
772
773 TIMESPEC_TO_TIMEVAL(&val.it_value, &value->it_value);
774 TIMESPEC_TO_TIMEVAL(&val.it_interval, &value->it_interval);
775 if (itimerfix(&val.it_value) || itimerfix(&val.it_interval))
776 return (EINVAL);
777
778 oval = pt->pt_time;
779 pt->pt_time = val;
780
781 s = splclock();
782 /*
783 * If we've been passed a relative time for a realtime timer,
784 * convert it to absolute; if an absolute time for a virtual
785 * timer, convert it to relative and make sure we don't set it
786 * to zero, which would cancel the timer, or let it go
787 * negative, which would confuse the comparison tests.
788 */
789 if (timerisset(&pt->pt_time.it_value)) {
790 if (pt->pt_type == CLOCK_REALTIME) {
791 if ((flags & TIMER_ABSTIME) == 0)
792 timeradd(&pt->pt_time.it_value, &time,
793 &pt->pt_time.it_value);
794 } else {
795 if ((flags & TIMER_ABSTIME) != 0) {
796 timersub(&pt->pt_time.it_value, &time,
797 &pt->pt_time.it_value);
798 if (!timerisset(&pt->pt_time.it_value) ||
799 pt->pt_time.it_value.tv_sec < 0) {
800 pt->pt_time.it_value.tv_sec = 0;
801 pt->pt_time.it_value.tv_usec = 1;
802 }
803 }
804 }
805 }
806
807 timer_settime(pt);
808 splx(s);
809
810 if (ovalue) {
811 TIMEVAL_TO_TIMESPEC(&oval.it_value, &ovalue->it_value);
812 TIMEVAL_TO_TIMESPEC(&oval.it_interval, &ovalue->it_interval);
813 }
814
815 return (0);
816 }
817
818 /* Return the time remaining until a POSIX timer fires. */
819 int
820 sys_timer_gettime(struct lwp *l, void *v, register_t *retval)
821 {
822 struct sys_timer_gettime_args /* {
823 syscallarg(timer_t) timerid;
824 syscallarg(struct itimerspec *) value;
825 } */ *uap = v;
826 struct itimerspec its;
827 int error;
828
829 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc,
830 &its)) != 0)
831 return error;
832
833 return copyout(&its, SCARG(uap, value), sizeof(its));
834 }
835
836 int
837 dotimer_gettime(int timerid, struct proc *p, struct itimerspec *its)
838 {
839 int s;
840 struct ptimer *pt;
841 struct itimerval aitv;
842
843 if ((p->p_timers == NULL) ||
844 (timerid < 2) || (timerid >= TIMER_MAX) ||
845 ((pt = p->p_timers->pts_timers[timerid]) == NULL))
846 return (EINVAL);
847
848 s = splclock();
849 timer_gettime(pt, &aitv);
850 splx(s);
851
852 TIMEVAL_TO_TIMESPEC(&aitv.it_interval, &its->it_interval);
853 TIMEVAL_TO_TIMESPEC(&aitv.it_value, &its->it_value);
854
855 return 0;
856 }
857
858 /*
859 * Return the count of the number of times a periodic timer expired
860 * while a notification was already pending. The counter is reset when
861 * a timer expires and a notification can be posted.
862 */
863 int
864 sys_timer_getoverrun(struct lwp *l, void *v, register_t *retval)
865 {
866 struct sys_timer_getoverrun_args /* {
867 syscallarg(timer_t) timerid;
868 } */ *uap = v;
869 struct proc *p = l->l_proc;
870 int timerid;
871 struct ptimer *pt;
872
873 timerid = SCARG(uap, timerid);
874
875 if ((p->p_timers == NULL) ||
876 (timerid < 2) || (timerid >= TIMER_MAX) ||
877 ((pt = p->p_timers->pts_timers[timerid]) == NULL))
878 return (EINVAL);
879
880 *retval = pt->pt_poverruns;
881
882 return (0);
883 }
884
885 /* Glue function that triggers an upcall; called from userret(). */
886 static void
887 timerupcall(struct lwp *l, void *arg)
888 {
889 struct ptimers *pt = (struct ptimers *)arg;
890 unsigned int i, fired, done;
891
892 KDASSERT(l->l_proc->p_sa);
893 /* Bail out if we do not own the virtual processor */
894 if (l->l_savp->savp_lwp != l)
895 return ;
896
897 KERNEL_PROC_LOCK(l);
898
899 fired = pt->pts_fired;
900 done = 0;
901 while ((i = ffs(fired)) != 0) {
902 siginfo_t *si;
903 int mask = 1 << --i;
904 int f;
905
906 f = l->l_flag & L_SA;
907 l->l_flag &= ~L_SA;
908 si = siginfo_alloc(PR_WAITOK);
909 si->_info = pt->pts_timers[i]->pt_info.ksi_info;
910 if (sa_upcall(l, SA_UPCALL_SIGEV | SA_UPCALL_DEFER, NULL, l,
911 sizeof(*si), si, siginfo_free) != 0) {
912 siginfo_free(si);
913 /* XXX What do we do here?? */
914 } else
915 done |= mask;
916 fired &= ~mask;
917 l->l_flag |= f;
918 }
919 pt->pts_fired &= ~done;
920 if (pt->pts_fired == 0)
921 l->l_proc->p_userret = NULL;
922
923 KERNEL_PROC_UNLOCK(l);
924 }
925
926
927 /*
928 * Real interval timer expired:
929 * send process whose timer expired an alarm signal.
930 * If time is not set up to reload, then just return.
931 * Else compute next time timer should go off which is > current time.
932 * This is where delay in processing this timeout causes multiple
933 * SIGALRM calls to be compressed into one.
934 */
935 void
936 realtimerexpire(void *arg)
937 {
938 struct ptimer *pt;
939 int s;
940
941 pt = (struct ptimer *)arg;
942
943 itimerfire(pt);
944
945 if (!timerisset(&pt->pt_time.it_interval)) {
946 timerclear(&pt->pt_time.it_value);
947 return;
948 }
949 for (;;) {
950 s = splclock();
951 timeradd(&pt->pt_time.it_value,
952 &pt->pt_time.it_interval, &pt->pt_time.it_value);
953 if (timercmp(&pt->pt_time.it_value, &time, >)) {
954 /*
955 * Don't need to check hzto() return value, here.
956 * callout_reset() does it for us.
957 */
958 callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value),
959 realtimerexpire, pt);
960 splx(s);
961 return;
962 }
963 splx(s);
964 pt->pt_overruns++;
965 }
966 }
967
968 /* BSD routine to get the value of an interval timer. */
969 /* ARGSUSED */
970 int
971 sys_getitimer(struct lwp *l, void *v, register_t *retval)
972 {
973 struct sys_getitimer_args /* {
974 syscallarg(int) which;
975 syscallarg(struct itimerval *) itv;
976 } */ *uap = v;
977 struct proc *p = l->l_proc;
978 struct itimerval aitv;
979 int error;
980
981 error = dogetitimer(p, SCARG(uap, which), &aitv);
982 if (error)
983 return error;
984 return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)));
985 }
986
987 int
988 dogetitimer(struct proc *p, int which, struct itimerval *itvp)
989 {
990 int s;
991
992 if ((u_int)which > ITIMER_PROF)
993 return (EINVAL);
994
995 if ((p->p_timers == NULL) || (p->p_timers->pts_timers[which] == NULL)){
996 timerclear(&itvp->it_value);
997 timerclear(&itvp->it_interval);
998 } else {
999 s = splclock();
1000 timer_gettime(p->p_timers->pts_timers[which], itvp);
1001 splx(s);
1002 }
1003
1004 return 0;
1005 }
1006
1007 /* BSD routine to set/arm an interval timer. */
1008 /* ARGSUSED */
1009 int
1010 sys_setitimer(struct lwp *l, void *v, register_t *retval)
1011 {
1012 struct sys_setitimer_args /* {
1013 syscallarg(int) which;
1014 syscallarg(const struct itimerval *) itv;
1015 syscallarg(struct itimerval *) oitv;
1016 } */ *uap = v;
1017 struct proc *p = l->l_proc;
1018 int which = SCARG(uap, which);
1019 struct sys_getitimer_args getargs;
1020 const struct itimerval *itvp;
1021 struct itimerval aitv;
1022 int error;
1023
1024 if ((u_int)which > ITIMER_PROF)
1025 return (EINVAL);
1026 itvp = SCARG(uap, itv);
1027 if (itvp &&
1028 (error = copyin(itvp, &aitv, sizeof(struct itimerval)) != 0))
1029 return (error);
1030 if (SCARG(uap, oitv) != NULL) {
1031 SCARG(&getargs, which) = which;
1032 SCARG(&getargs, itv) = SCARG(uap, oitv);
1033 if ((error = sys_getitimer(l, &getargs, retval)) != 0)
1034 return (error);
1035 }
1036 if (itvp == 0)
1037 return (0);
1038
1039 return dosetitimer(p, which, &aitv);
1040 }
1041
1042 int
1043 dosetitimer(struct proc *p, int which, struct itimerval *itvp)
1044 {
1045 struct ptimer *pt;
1046 int s;
1047
1048 if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval))
1049 return (EINVAL);
1050
1051 /*
1052 * Don't bother allocating data structures if the process just
1053 * wants to clear the timer.
1054 */
1055 if (!timerisset(&itvp->it_value) &&
1056 ((p->p_timers == NULL) ||(p->p_timers->pts_timers[which] == NULL)))
1057 return (0);
1058
1059 if (p->p_timers == NULL)
1060 timers_alloc(p);
1061 if (p->p_timers->pts_timers[which] == NULL) {
1062 pt = pool_get(&ptimer_pool, PR_WAITOK);
1063 pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
1064 pt->pt_ev.sigev_value.sival_int = which;
1065 pt->pt_overruns = 0;
1066 pt->pt_proc = p;
1067 pt->pt_type = which;
1068 pt->pt_entry = which;
1069 switch (which) {
1070 case ITIMER_REAL:
1071 callout_init(&pt->pt_ch);
1072 pt->pt_ev.sigev_signo = SIGALRM;
1073 break;
1074 case ITIMER_VIRTUAL:
1075 pt->pt_active = 0;
1076 pt->pt_ev.sigev_signo = SIGVTALRM;
1077 break;
1078 case ITIMER_PROF:
1079 pt->pt_active = 0;
1080 pt->pt_ev.sigev_signo = SIGPROF;
1081 break;
1082 }
1083 } else
1084 pt = p->p_timers->pts_timers[which];
1085
1086 pt->pt_time = *itvp;
1087 p->p_timers->pts_timers[which] = pt;
1088
1089 s = splclock();
1090 if ((which == ITIMER_REAL) && timerisset(&pt->pt_time.it_value)) {
1091 /* Convert to absolute time */
1092 timeradd(&pt->pt_time.it_value, &time, &pt->pt_time.it_value);
1093 }
1094 timer_settime(pt);
1095 splx(s);
1096
1097 return (0);
1098 }
1099
1100 /* Utility routines to manage the array of pointers to timers. */
1101 void
1102 timers_alloc(struct proc *p)
1103 {
1104 int i;
1105 struct ptimers *pts;
1106
1107 pts = pool_get(&ptimers_pool, 0);
1108 LIST_INIT(&pts->pts_virtual);
1109 LIST_INIT(&pts->pts_prof);
1110 for (i = 0; i < TIMER_MAX; i++)
1111 pts->pts_timers[i] = NULL;
1112 pts->pts_fired = 0;
1113 p->p_timers = pts;
1114 }
1115
1116 /*
1117 * Clean up the per-process timers. If "which" is set to TIMERS_ALL,
1118 * then clean up all timers and free all the data structures. If
1119 * "which" is set to TIMERS_POSIX, only clean up the timers allocated
1120 * by timer_create(), not the BSD setitimer() timers, and only free the
1121 * structure if none of those remain.
1122 */
1123 void
1124 timers_free(struct proc *p, int which)
1125 {
1126 int i, s;
1127 struct ptimers *pts;
1128 struct ptimer *pt, *ptn;
1129 struct timeval tv;
1130
1131 if (p->p_timers) {
1132 pts = p->p_timers;
1133 if (which == TIMERS_ALL)
1134 i = 0;
1135 else {
1136 s = splclock();
1137 timerclear(&tv);
1138 for (ptn = LIST_FIRST(&p->p_timers->pts_virtual);
1139 ptn && ptn != pts->pts_timers[ITIMER_VIRTUAL];
1140 ptn = LIST_NEXT(ptn, pt_list))
1141 timeradd(&tv, &ptn->pt_time.it_value, &tv);
1142 LIST_FIRST(&p->p_timers->pts_virtual) = NULL;
1143 if (ptn) {
1144 timeradd(&tv, &ptn->pt_time.it_value,
1145 &ptn->pt_time.it_value);
1146 LIST_INSERT_HEAD(&p->p_timers->pts_virtual,
1147 ptn, pt_list);
1148 }
1149
1150 timerclear(&tv);
1151 for (ptn = LIST_FIRST(&p->p_timers->pts_prof);
1152 ptn && ptn != pts->pts_timers[ITIMER_PROF];
1153 ptn = LIST_NEXT(ptn, pt_list))
1154 timeradd(&tv, &ptn->pt_time.it_value, &tv);
1155 LIST_FIRST(&p->p_timers->pts_prof) = NULL;
1156 if (ptn) {
1157 timeradd(&tv, &ptn->pt_time.it_value,
1158 &ptn->pt_time.it_value);
1159 LIST_INSERT_HEAD(&p->p_timers->pts_prof, ptn,
1160 pt_list);
1161 }
1162 splx(s);
1163 i = 3;
1164 }
1165 for ( ; i < TIMER_MAX; i++)
1166 if ((pt = pts->pts_timers[i]) != NULL) {
1167 if (pt->pt_type == CLOCK_REALTIME)
1168 callout_stop(&pt->pt_ch);
1169 pts->pts_timers[i] = NULL;
1170 pool_put(&ptimer_pool, pt);
1171 }
1172 if ((pts->pts_timers[0] == NULL) &&
1173 (pts->pts_timers[1] == NULL) &&
1174 (pts->pts_timers[2] == NULL)) {
1175 p->p_timers = NULL;
1176 pool_put(&ptimers_pool, pts);
1177 }
1178 }
1179 }
1180
1181 /*
1182 * Check that a proposed value to load into the .it_value or
1183 * .it_interval part of an interval timer is acceptable, and
1184 * fix it to have at least minimal value (i.e. if it is less
1185 * than the resolution of the clock, round it up.)
1186 */
1187 int
1188 itimerfix(struct timeval *tv)
1189 {
1190
1191 if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000)
1192 return (EINVAL);
1193 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
1194 tv->tv_usec = tick;
1195 return (0);
1196 }
1197
1198 /*
1199 * Decrement an interval timer by a specified number
1200 * of microseconds, which must be less than a second,
1201 * i.e. < 1000000. If the timer expires, then reload
1202 * it. In this case, carry over (usec - old value) to
1203 * reduce the value reloaded into the timer so that
1204 * the timer does not drift. This routine assumes
1205 * that it is called in a context where the timers
1206 * on which it is operating cannot change in value.
1207 */
1208 int
1209 itimerdecr(struct ptimer *pt, int usec)
1210 {
1211 struct itimerval *itp;
1212
1213 itp = &pt->pt_time;
1214 if (itp->it_value.tv_usec < usec) {
1215 if (itp->it_value.tv_sec == 0) {
1216 /* expired, and already in next interval */
1217 usec -= itp->it_value.tv_usec;
1218 goto expire;
1219 }
1220 itp->it_value.tv_usec += 1000000;
1221 itp->it_value.tv_sec--;
1222 }
1223 itp->it_value.tv_usec -= usec;
1224 usec = 0;
1225 if (timerisset(&itp->it_value))
1226 return (1);
1227 /* expired, exactly at end of interval */
1228 expire:
1229 if (timerisset(&itp->it_interval)) {
1230 itp->it_value = itp->it_interval;
1231 itp->it_value.tv_usec -= usec;
1232 if (itp->it_value.tv_usec < 0) {
1233 itp->it_value.tv_usec += 1000000;
1234 itp->it_value.tv_sec--;
1235 }
1236 timer_settime(pt);
1237 } else
1238 itp->it_value.tv_usec = 0; /* sec is already 0 */
1239 return (0);
1240 }
1241
1242 void
1243 itimerfire(struct ptimer *pt)
1244 {
1245 struct proc *p = pt->pt_proc;
1246 struct sadata_vp *vp;
1247 int s;
1248 unsigned int i;
1249
1250 if (pt->pt_ev.sigev_notify == SIGEV_SIGNAL) {
1251 /*
1252 * No RT signal infrastructure exists at this time;
1253 * just post the signal number and throw away the
1254 * value.
1255 */
1256 if (sigismember(&p->p_sigctx.ps_siglist, pt->pt_ev.sigev_signo))
1257 pt->pt_overruns++;
1258 else {
1259 ksiginfo_t ksi;
1260 (void)memset(&ksi, 0, sizeof(ksi));
1261 ksi.ksi_signo = pt->pt_ev.sigev_signo;
1262 ksi.ksi_code = SI_TIMER;
1263 ksi.ksi_sigval = pt->pt_ev.sigev_value;
1264 pt->pt_poverruns = pt->pt_overruns;
1265 pt->pt_overruns = 0;
1266 kpsignal(p, &ksi, NULL);
1267 }
1268 } else if (pt->pt_ev.sigev_notify == SIGEV_SA && (p->p_flag & P_SA)) {
1269 /* Cause the process to generate an upcall when it returns. */
1270
1271 if (p->p_userret == NULL) {
1272 /*
1273 * XXX stop signals can be processed inside tsleep,
1274 * which can be inside sa_yield's inner loop, which
1275 * makes testing for sa_idle alone insuffucent to
1276 * determine if we really should call setrunnable.
1277 */
1278 pt->pt_poverruns = pt->pt_overruns;
1279 pt->pt_overruns = 0;
1280 i = 1 << pt->pt_entry;
1281 p->p_timers->pts_fired = i;
1282 p->p_userret = timerupcall;
1283 p->p_userret_arg = p->p_timers;
1284
1285 SCHED_LOCK(s);
1286 SLIST_FOREACH(vp, &p->p_sa->sa_vps, savp_next) {
1287 if (vp->savp_lwp->l_flag & L_SA_IDLE) {
1288 vp->savp_lwp->l_flag &= ~L_SA_IDLE;
1289 sched_wakeup(vp->savp_lwp);
1290 break;
1291 }
1292 }
1293 SCHED_UNLOCK(s);
1294 } else if (p->p_userret == timerupcall) {
1295 i = 1 << pt->pt_entry;
1296 if ((p->p_timers->pts_fired & i) == 0) {
1297 pt->pt_poverruns = pt->pt_overruns;
1298 pt->pt_overruns = 0;
1299 p->p_timers->pts_fired |= i;
1300 } else
1301 pt->pt_overruns++;
1302 } else {
1303 pt->pt_overruns++;
1304 if ((p->p_flag & P_WEXIT) == 0)
1305 printf("itimerfire(%d): overrun %d on timer %x (userret is %p)\n",
1306 p->p_pid, pt->pt_overruns,
1307 pt->pt_ev.sigev_value.sival_int,
1308 p->p_userret);
1309 }
1310 }
1311
1312 }
1313
1314 /*
1315 * ratecheck(): simple time-based rate-limit checking. see ratecheck(9)
1316 * for usage and rationale.
1317 */
1318 int
1319 ratecheck(struct timeval *lasttime, const struct timeval *mininterval)
1320 {
1321 struct timeval tv, delta;
1322 int s, rv = 0;
1323
1324 s = splclock();
1325 tv = mono_time;
1326 splx(s);
1327
1328 timersub(&tv, lasttime, &delta);
1329
1330 /*
1331 * check for 0,0 is so that the message will be seen at least once,
1332 * even if interval is huge.
1333 */
1334 if (timercmp(&delta, mininterval, >=) ||
1335 (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
1336 *lasttime = tv;
1337 rv = 1;
1338 }
1339
1340 return (rv);
1341 }
1342
1343 /*
1344 * ppsratecheck(): packets (or events) per second limitation.
1345 */
1346 int
1347 ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
1348 {
1349 struct timeval tv, delta;
1350 int s, rv;
1351
1352 s = splclock();
1353 tv = mono_time;
1354 splx(s);
1355
1356 timersub(&tv, lasttime, &delta);
1357
1358 /*
1359 * check for 0,0 is so that the message will be seen at least once.
1360 * if more than one second have passed since the last update of
1361 * lasttime, reset the counter.
1362 *
1363 * we do increment *curpps even in *curpps < maxpps case, as some may
1364 * try to use *curpps for stat purposes as well.
1365 */
1366 if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) ||
1367 delta.tv_sec >= 1) {
1368 *lasttime = tv;
1369 *curpps = 0;
1370 }
1371 if (maxpps < 0)
1372 rv = 1;
1373 else if (*curpps < maxpps)
1374 rv = 1;
1375 else
1376 rv = 0;
1377
1378 #if 1 /*DIAGNOSTIC?*/
1379 /* be careful about wrap-around */
1380 if (*curpps + 1 > *curpps)
1381 *curpps = *curpps + 1;
1382 #else
1383 /*
1384 * assume that there's not too many calls to this function.
1385 * not sure if the assumption holds, as it depends on *caller's*
1386 * behavior, not the behavior of this function.
1387 * IMHO it is wrong to make assumption on the caller's behavior,
1388 * so the above #if is #if 1, not #ifdef DIAGNOSTIC.
1389 */
1390 *curpps = *curpps + 1;
1391 #endif
1392
1393 return (rv);
1394 }
1395