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