kern_time.c revision 140832
1139804Simp/*- 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 4. Neither the name of the University nor the names of its contributors 141541Srgrimes * may be used to endorse or promote products derived from this software 151541Srgrimes * without specific prior written permission. 161541Srgrimes * 171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271541Srgrimes * SUCH DAMAGE. 281541Srgrimes * 291541Srgrimes * @(#)kern_time.c 8.1 (Berkeley) 6/10/93 301541Srgrimes */ 311541Srgrimes 32116182Sobrien#include <sys/cdefs.h> 33116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/kern_time.c 140832 2005-01-25 21:28:28Z sobomax $"); 34116182Sobrien 35106369Srwatson#include "opt_mac.h" 36106369Srwatson 371541Srgrimes#include <sys/param.h> 3848274Speter#include <sys/systm.h> 3976166Smarkm#include <sys/lock.h> 4076166Smarkm#include <sys/mutex.h> 4112221Sbde#include <sys/sysproto.h> 421541Srgrimes#include <sys/resourcevar.h> 433308Sphk#include <sys/signalvar.h> 441541Srgrimes#include <sys/kernel.h> 45106369Srwatson#include <sys/mac.h> 46140483Sps#include <sys/syscallsubr.h> 4725583Speter#include <sys/sysent.h> 481541Srgrimes#include <sys/proc.h> 4925656Speter#include <sys/time.h> 5058377Sphk#include <sys/timetc.h> 511541Srgrimes#include <sys/vnode.h> 5276166Smarkm 5326335Speter#include <vm/vm.h> 5426335Speter#include <vm/vm_extern.h> 551541Srgrimes 56110299Sphkint tz_minuteswest; 57110299Sphkint tz_dsttime; 589369Sdg 598876Srgrimes/* 601541Srgrimes * Time of day and interval timer support. 611541Srgrimes * 621541Srgrimes * These routines provide the kernel entry points to get and set 631541Srgrimes * the time-of-day and per-process interval timers. Subroutines 641541Srgrimes * here provide support for adding and subtracting timeval structures 651541Srgrimes * and decrementing interval timers, optionally reloading the interval 661541Srgrimes * timers when they expire. 671541Srgrimes */ 681541Srgrimes 6994343Sjhbstatic int settime(struct thread *, struct timeval *); 7092723Salfredstatic void timevalfix(struct timeval *); 7192723Salfredstatic void no_lease_updatetime(int); 7213016Sbde 7330739Sphkstatic void 7430739Sphkno_lease_updatetime(deltat) 7530739Sphk int deltat; 7630739Sphk{ 7730739Sphk} 7830739Sphk 7992723Salfredvoid (*lease_updatetime)(int) = no_lease_updatetime; 8030739Sphk 8125583Speterstatic int 82102074Sphksettime(struct thread *td, struct timeval *tv) 8325583Speter{ 8445433Snsayer struct timeval delta, tv1, tv2; 8545438Snsayer static struct timeval maxtime, laststep; 8633690Sphk struct timespec ts; 8725583Speter int s; 8825583Speter 8925656Speter s = splclock(); 9033818Sbde microtime(&tv1); 9135029Sphk delta = *tv; 9235029Sphk timevalsub(&delta, &tv1); 9325583Speter 9425583Speter /* 9533818Sbde * If the system is secure, we do not allow the time to be 9645433Snsayer * set to a value earlier than 1 second less than the highest 9745433Snsayer * time we have yet seen. The worst a miscreant can do in 9845433Snsayer * this circumstance is "freeze" time. He couldn't go 9945433Snsayer * back to the past. 10045438Snsayer * 10145438Snsayer * We similarly do not allow the clock to be stepped more 10245438Snsayer * than one second, nor more than once per second. This allows 10345438Snsayer * a miscreant to make the clock march double-time, but no worse. 10425583Speter */ 10594343Sjhb if (securelevel_gt(td->td_ucred, 1) != 0) { 10645433Snsayer if (delta.tv_sec < 0 || delta.tv_usec < 0) { 10745437Smjacob /* 10845438Snsayer * Update maxtime to latest time we've seen. 10945437Smjacob */ 11045437Smjacob if (tv1.tv_sec > maxtime.tv_sec) 11145437Smjacob maxtime = tv1; 11245437Smjacob tv2 = *tv; 11345437Smjacob timevalsub(&tv2, &maxtime); 11445437Smjacob if (tv2.tv_sec < -1) { 11545437Smjacob tv->tv_sec = maxtime.tv_sec - 1; 11645433Snsayer printf("Time adjustment clamped to -1 second\n"); 11745433Snsayer } 11845437Smjacob } else { 11945438Snsayer if (tv1.tv_sec == laststep.tv_sec) { 12045438Snsayer splx(s); 12145438Snsayer return (EPERM); 12245438Snsayer } 12345438Snsayer if (delta.tv_sec > 1) { 12445438Snsayer tv->tv_sec = tv1.tv_sec + 1; 12545438Snsayer printf("Time adjustment clamped to +1 second\n"); 12645438Snsayer } 12745438Snsayer laststep = *tv; 12845433Snsayer } 12933818Sbde } 13033818Sbde 13133690Sphk ts.tv_sec = tv->tv_sec; 13233690Sphk ts.tv_nsec = tv->tv_usec * 1000; 13394343Sjhb mtx_lock(&Giant); 13458377Sphk tc_setclock(&ts); 13525583Speter (void) splsoftclock(); 13625583Speter lease_updatetime(delta.tv_sec); 13725583Speter splx(s); 13825583Speter resettodr(); 13994343Sjhb mtx_unlock(&Giant); 14025583Speter return (0); 14125583Speter} 14225583Speter 14312221Sbde#ifndef _SYS_SYSPROTO_H_ 14425583Speterstruct clock_gettime_args { 14525583Speter clockid_t clock_id; 14625583Speter struct timespec *tp; 14725583Speter}; 14825583Speter#endif 14925656Speter 15082746Sdillon/* 15182746Sdillon * MPSAFE 15282746Sdillon */ 15325583Speter/* ARGSUSED */ 15425583Speterint 155102074Sphkclock_gettime(struct thread *td, struct clock_gettime_args *uap) 15625583Speter{ 15725583Speter struct timespec ats; 158130884Skbyanc struct timeval sys, user; 159136152Sjhb struct proc *p; 16025583Speter 161136152Sjhb p = td->td_proc; 162130654Skbyanc switch (uap->clock_id) { 163130654Skbyanc case CLOCK_REALTIME: 164111300Sphk nanotime(&ats); 165130654Skbyanc break; 166130654Skbyanc case CLOCK_VIRTUAL: 167136152Sjhb PROC_LOCK(p); 168136152Sjhb calcru(p, &user, &sys); 169136152Sjhb PROC_UNLOCK(p); 170130654Skbyanc TIMEVAL_TO_TIMESPEC(&user, &ats); 171130654Skbyanc break; 172130654Skbyanc case CLOCK_PROF: 173136152Sjhb PROC_LOCK(p); 174136152Sjhb calcru(p, &user, &sys); 175136152Sjhb PROC_UNLOCK(p); 176130884Skbyanc timevaladd(&user, &sys); 177130884Skbyanc TIMEVAL_TO_TIMESPEC(&user, &ats); 178130654Skbyanc break; 179130884Skbyanc case CLOCK_MONOTONIC: 180130884Skbyanc nanouptime(&ats); 181130884Skbyanc break; 182130654Skbyanc default: 183111315Sphk return (EINVAL); 184130654Skbyanc } 185107849Salfred return (copyout(&ats, uap->tp, sizeof(ats))); 18625583Speter} 18725583Speter 18825583Speter#ifndef _SYS_SYSPROTO_H_ 18925583Speterstruct clock_settime_args { 19025583Speter clockid_t clock_id; 19125583Speter const struct timespec *tp; 19225583Speter}; 19325583Speter#endif 19425656Speter 19582746Sdillon/* 19682746Sdillon * MPSAFE 19782746Sdillon */ 19825583Speter/* ARGSUSED */ 19925583Speterint 200102074Sphkclock_settime(struct thread *td, struct clock_settime_args *uap) 20125583Speter{ 20225583Speter struct timeval atv; 20325583Speter struct timespec ats; 20425583Speter int error; 20525583Speter 206106369Srwatson#ifdef MAC 207106369Srwatson error = mac_check_system_settime(td->td_ucred); 208106369Srwatson if (error) 209106369Srwatson return (error); 210106369Srwatson#endif 21193593Sjhb if ((error = suser(td)) != 0) 21294343Sjhb return (error); 213107849Salfred if (uap->clock_id != CLOCK_REALTIME) 21494343Sjhb return (EINVAL); 215107849Salfred if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0) 21694343Sjhb return (error); 21794343Sjhb if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000) 21894343Sjhb return (EINVAL); 21934901Sphk /* XXX Don't convert nsec->usec and back */ 22025583Speter TIMESPEC_TO_TIMEVAL(&atv, &ats); 22194343Sjhb error = settime(td, &atv); 22282746Sdillon return (error); 22325583Speter} 22425583Speter 22525583Speter#ifndef _SYS_SYSPROTO_H_ 22625583Speterstruct clock_getres_args { 22725583Speter clockid_t clock_id; 22825583Speter struct timespec *tp; 22925583Speter}; 23025583Speter#endif 23125656Speter 23225583Speterint 233102074Sphkclock_getres(struct thread *td, struct clock_getres_args *uap) 23425583Speter{ 23525583Speter struct timespec ts; 23625583Speter 237130654Skbyanc ts.tv_sec = 0; 238130654Skbyanc switch (uap->clock_id) { 239130654Skbyanc case CLOCK_REALTIME: 240130654Skbyanc case CLOCK_MONOTONIC: 241103964Sbde /* 242103964Sbde * Round up the result of the division cheaply by adding 1. 243103964Sbde * Rounding up is especially important if rounding down 244103964Sbde * would give 0. Perfect rounding is unimportant. 245103964Sbde */ 246103964Sbde ts.tv_nsec = 1000000000 / tc_getfrequency() + 1; 247130654Skbyanc break; 248130654Skbyanc case CLOCK_VIRTUAL: 249130654Skbyanc case CLOCK_PROF: 250130654Skbyanc /* Accurately round up here because we can do so cheaply. */ 251130654Skbyanc ts.tv_nsec = (1000000000 + hz - 1) / hz; 252130654Skbyanc break; 253130654Skbyanc default: 254130654Skbyanc return (EINVAL); 255130654Skbyanc } 256130884Skbyanc if (uap->tp == NULL) 257130884Skbyanc return (0); 258130884Skbyanc return (copyout(&ts, uap->tp, sizeof(ts))); 25925583Speter} 26025583Speter 26126335Speterstatic int nanowait; 26225656Speter 263140481Spsint 264140481Spskern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) 26525583Speter{ 26635045Sphk struct timespec ts, ts2, ts3; 26735042Sphk struct timeval tv; 26835042Sphk int error; 26925583Speter 27028773Sbde if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) 27125656Speter return (EINVAL); 27243301Sdillon if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) 27328773Sbde return (0); 27436119Sphk getnanouptime(&ts); 27535029Sphk timespecadd(&ts, rqt); 27635042Sphk TIMESPEC_TO_TIMEVAL(&tv, rqt); 27735042Sphk for (;;) { 27835042Sphk error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", 27935042Sphk tvtohz(&tv)); 28036119Sphk getnanouptime(&ts2); 28135042Sphk if (error != EWOULDBLOCK) { 28235042Sphk if (error == ERESTART) 28335042Sphk error = EINTR; 28435042Sphk if (rmt != NULL) { 28535042Sphk timespecsub(&ts, &ts2); 28635042Sphk if (ts.tv_sec < 0) 28735042Sphk timespecclear(&ts); 28835042Sphk *rmt = ts; 28935042Sphk } 29035042Sphk return (error); 29135042Sphk } 29235029Sphk if (timespeccmp(&ts2, &ts, >=)) 29335042Sphk return (0); 29435045Sphk ts3 = ts; 29535045Sphk timespecsub(&ts3, &ts2); 29635045Sphk TIMESPEC_TO_TIMEVAL(&tv, &ts3); 29726335Speter } 29826335Speter} 29925583Speter 30026335Speter#ifndef _SYS_SYSPROTO_H_ 30126335Speterstruct nanosleep_args { 30226335Speter struct timespec *rqtp; 30326335Speter struct timespec *rmtp; 30426335Speter}; 30526335Speter#endif 30626335Speter 30782746Sdillon/* 30882746Sdillon * MPSAFE 30982746Sdillon */ 31026335Speter/* ARGSUSED */ 31126335Speterint 312102074Sphknanosleep(struct thread *td, struct nanosleep_args *uap) 31326335Speter{ 31426335Speter struct timespec rmt, rqt; 31582746Sdillon int error; 31626335Speter 317107849Salfred error = copyin(uap->rqtp, &rqt, sizeof(rqt)); 31826335Speter if (error) 31926335Speter return (error); 32082746Sdillon 321109521Salfred if (uap->rmtp && 322109521Salfred !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 323109521Salfred return (EFAULT); 324140481Sps error = kern_nanosleep(td, &rqt, &rmt); 325107849Salfred if (error && uap->rmtp) { 32682746Sdillon int error2; 32782746Sdillon 328107849Salfred error2 = copyout(&rmt, uap->rmtp, sizeof(rmt)); 329109521Salfred if (error2) 33082746Sdillon error = error2; 33125583Speter } 33225656Speter return (error); 33325583Speter} 33425583Speter 33526335Speter#ifndef _SYS_SYSPROTO_H_ 3361541Srgrimesstruct gettimeofday_args { 3371541Srgrimes struct timeval *tp; 3381541Srgrimes struct timezone *tzp; 3391541Srgrimes}; 34012221Sbde#endif 34182746Sdillon/* 34282746Sdillon * MPSAFE 34382746Sdillon */ 3441541Srgrimes/* ARGSUSED */ 3451549Srgrimesint 346102074Sphkgettimeofday(struct thread *td, struct gettimeofday_args *uap) 3471541Srgrimes{ 3481541Srgrimes struct timeval atv; 349110286Stjr struct timezone rtz; 3501541Srgrimes int error = 0; 3511541Srgrimes 3521541Srgrimes if (uap->tp) { 3531541Srgrimes microtime(&atv); 35499012Salfred error = copyout(&atv, uap->tp, sizeof (atv)); 3551541Srgrimes } 35690836Sphk if (error == 0 && uap->tzp != NULL) { 357110299Sphk rtz.tz_minuteswest = tz_minuteswest; 358110299Sphk rtz.tz_dsttime = tz_dsttime; 359110286Stjr error = copyout(&rtz, uap->tzp, sizeof (rtz)); 36082746Sdillon } 3611541Srgrimes return (error); 3621541Srgrimes} 3631541Srgrimes 36412221Sbde#ifndef _SYS_SYSPROTO_H_ 3651541Srgrimesstruct settimeofday_args { 3661541Srgrimes struct timeval *tv; 3671541Srgrimes struct timezone *tzp; 3681541Srgrimes}; 36912221Sbde#endif 37082746Sdillon/* 37182746Sdillon * MPSAFE 37282746Sdillon */ 3731541Srgrimes/* ARGSUSED */ 3741549Srgrimesint 375102074Sphksettimeofday(struct thread *td, struct settimeofday_args *uap) 3761541Srgrimes{ 37725656Speter struct timeval atv; 3781541Srgrimes struct timezone atz; 37982746Sdillon int error = 0; 3801541Srgrimes 381106369Srwatson#ifdef MAC 382106369Srwatson error = mac_check_system_settime(td->td_ucred); 383106369Srwatson if (error) 384106369Srwatson return (error); 385106369Srwatson#endif 38693593Sjhb if ((error = suser(td))) 38794343Sjhb return (error); 3881541Srgrimes /* Verify all parameters before changing time. */ 38925656Speter if (uap->tv) { 39099012Salfred if ((error = copyin(uap->tv, &atv, sizeof(atv)))) 39194343Sjhb return (error); 39294343Sjhb if (atv.tv_usec < 0 || atv.tv_usec >= 1000000) 39394343Sjhb return (EINVAL); 39425656Speter } 3951541Srgrimes if (uap->tzp && 39699012Salfred (error = copyin(uap->tzp, &atz, sizeof(atz)))) 39794343Sjhb return (error); 39894343Sjhb 39994343Sjhb if (uap->tv && (error = settime(td, &atv))) 40094343Sjhb return (error); 40194343Sjhb if (uap->tzp) { 402110299Sphk tz_minuteswest = atz.tz_minuteswest; 403110299Sphk tz_dsttime = atz.tz_dsttime; 40482746Sdillon } 40582746Sdillon return (error); 4061541Srgrimes} 40782746Sdillon/* 4081541Srgrimes * Get value of an interval timer. The process virtual and 4091541Srgrimes * profiling virtual time timers are kept in the p_stats area, since 4101541Srgrimes * they can be swapped out. These are kept internally in the 4111541Srgrimes * way they are specified externally: in time until they expire. 4121541Srgrimes * 4131541Srgrimes * The real time interval timer is kept in the process table slot 4141541Srgrimes * for the process, and its value (it_value) is kept as an 4151541Srgrimes * absolute time rather than as a delta, so that it is easy to keep 4161541Srgrimes * periodic real-time signals from drifting. 4171541Srgrimes * 4181541Srgrimes * Virtual time timers are processed in the hardclock() routine of 4191541Srgrimes * kern_clock.c. The real time timer is processed by a timeout 4201541Srgrimes * routine, called from the softclock() routine. Since a callout 4211541Srgrimes * may be delayed in real time due to interrupt processing in the system, 4221541Srgrimes * it is possible for the real time timeout routine (realitexpire, given below), 4231541Srgrimes * to be delayed in real time past when it is supposed to occur. It 4241541Srgrimes * does not suffice, therefore, to reload the real timer .it_value from the 4251541Srgrimes * real time timers .it_interval. Rather, we compute the next time in 4261541Srgrimes * absolute time the timer should go off. 4271541Srgrimes */ 42812221Sbde#ifndef _SYS_SYSPROTO_H_ 4291541Srgrimesstruct getitimer_args { 4301541Srgrimes u_int which; 4311541Srgrimes struct itimerval *itv; 4321541Srgrimes}; 43312221Sbde#endif 43482746Sdillon/* 43582746Sdillon * MPSAFE 43682746Sdillon */ 4371549Srgrimesint 438102074Sphkgetitimer(struct thread *td, struct getitimer_args *uap) 4391541Srgrimes{ 440140832Ssobomax int error; 441140832Ssobomax struct itimerval aitv; 442140832Ssobomax 443140832Ssobomax error = kern_getitimer(td, uap->which, &aitv); 444140832Ssobomax if (error != 0) 445140832Ssobomax return (error); 446140832Ssobomax return (copyout(&aitv, uap->itv, sizeof (struct itimerval))); 447140832Ssobomax} 448140832Ssobomax 449140832Ssobomaxint 450140832Ssobomaxkern_getitimer(struct thread *td, u_int which, struct itimerval *aitv) 451140832Ssobomax{ 45283366Sjulian struct proc *p = td->td_proc; 45334961Sphk struct timeval ctv; 4541541Srgrimes 455140832Ssobomax if (which > ITIMER_PROF) 4561541Srgrimes return (EINVAL); 45782746Sdillon 458140832Ssobomax if (which == ITIMER_REAL) { 4591541Srgrimes /* 46036128Sbde * Convert from absolute to relative time in .it_value 4611541Srgrimes * part of real time timer. If time for real time timer 4621541Srgrimes * has passed return 0, else return difference between 4631541Srgrimes * current time and time for the timer to go off. 4641541Srgrimes */ 465111034Stjr PROC_LOCK(p); 466140832Ssobomax *aitv = p->p_realtimer; 467111034Stjr PROC_UNLOCK(p); 468140832Ssobomax if (timevalisset(&aitv->it_value)) { 46936119Sphk getmicrouptime(&ctv); 470140832Ssobomax if (timevalcmp(&aitv->it_value, &ctv, <)) 471140832Ssobomax timevalclear(&aitv->it_value); 4721541Srgrimes else 473140832Ssobomax timevalsub(&aitv->it_value, &ctv); 47434961Sphk } 47582746Sdillon } else { 476111034Stjr mtx_lock_spin(&sched_lock); 477140832Ssobomax *aitv = p->p_stats->p_timer[which]; 478111034Stjr mtx_unlock_spin(&sched_lock); 47982746Sdillon } 480140832Ssobomax return (0); 4811541Srgrimes} 4821541Srgrimes 48312221Sbde#ifndef _SYS_SYSPROTO_H_ 4841541Srgrimesstruct setitimer_args { 4851541Srgrimes u_int which; 4861541Srgrimes struct itimerval *itv, *oitv; 4871541Srgrimes}; 48812221Sbde#endif 489140832Ssobomax 49082746Sdillon/* 49182746Sdillon * MPSAFE 49282746Sdillon */ 4931549Srgrimesint 494102074Sphksetitimer(struct thread *td, struct setitimer_args *uap) 4951541Srgrimes{ 496140832Ssobomax int error; 497111034Stjr struct itimerval aitv, oitv; 4981541Srgrimes 499111034Stjr if (uap->itv == NULL) { 500111034Stjr uap->itv = uap->oitv; 501111034Stjr return (getitimer(td, (struct getitimer_args *)uap)); 502111034Stjr } 503111034Stjr 504111034Stjr if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval)))) 5051541Srgrimes return (error); 506140832Ssobomax error = kern_setitimer(td, uap->which, &aitv, &oitv); 507140832Ssobomax if (error != 0 || uap->oitv == NULL) 508140832Ssobomax return (error); 509140832Ssobomax 510140832Ssobomax return (copyout(&oitv, uap->oitv, sizeof(struct itimerval))); 511140832Ssobomax} 512140832Ssobomax 513140832Ssobomaxint 514140832Ssobomaxkern_setitimer(struct thread *td, u_int which, struct itimerval *aitv, struct itimerval *oitv) 515140832Ssobomax{ 516140832Ssobomax struct proc *p = td->td_proc; 517140832Ssobomax struct timeval ctv; 518140832Ssobomax 519140832Ssobomax if (which > ITIMER_PROF) 520111034Stjr return (EINVAL); 521140832Ssobomax if (itimerfix(&aitv->it_value)) 522111034Stjr return (EINVAL); 523140832Ssobomax if (!timevalisset(&aitv->it_value)) 524140832Ssobomax timevalclear(&aitv->it_interval); 525140832Ssobomax else if (itimerfix(&aitv->it_interval)) 526140832Ssobomax return (EINVAL); 52782746Sdillon 528140832Ssobomax if (which == ITIMER_REAL) { 529111034Stjr PROC_LOCK(p); 53035058Sphk if (timevalisset(&p->p_realtimer.it_value)) 53169286Sjake callout_stop(&p->p_itcallout); 532114980Sjhb getmicrouptime(&ctv); 533140832Ssobomax if (timevalisset(&aitv->it_value)) { 534140832Ssobomax callout_reset(&p->p_itcallout, tvtohz(&aitv->it_value), 53569286Sjake realitexpire, p); 536140832Ssobomax timevaladd(&aitv->it_value, &ctv); 537114980Sjhb } 538140832Ssobomax *oitv = p->p_realtimer; 539140832Ssobomax p->p_realtimer = *aitv; 540111034Stjr PROC_UNLOCK(p); 541140832Ssobomax if (timevalisset(&oitv->it_value)) { 542140832Ssobomax if (timevalcmp(&oitv->it_value, &ctv, <)) 543140832Ssobomax timevalclear(&oitv->it_value); 544111034Stjr else 545140832Ssobomax timevalsub(&oitv->it_value, &ctv); 546111034Stjr } 54782746Sdillon } else { 548111034Stjr mtx_lock_spin(&sched_lock); 549140832Ssobomax *oitv = p->p_stats->p_timer[which]; 550140832Ssobomax p->p_stats->p_timer[which] = *aitv; 551111034Stjr mtx_unlock_spin(&sched_lock); 55282746Sdillon } 553140832Ssobomax return (0); 5541541Srgrimes} 5551541Srgrimes 5561541Srgrimes/* 5571541Srgrimes * Real interval timer expired: 5581541Srgrimes * send process whose timer expired an alarm signal. 5591541Srgrimes * If time is not set up to reload, then just return. 5601541Srgrimes * Else compute next time timer should go off which is > current time. 5611541Srgrimes * This is where delay in processing this timeout causes multiple 5621541Srgrimes * SIGALRM calls to be compressed into one. 56336127Sbde * tvtohz() always adds 1 to allow for the time until the next clock 5649327Sbde * interrupt being strictly less than 1 clock tick, but we don't want 5659327Sbde * that here since we want to appear to be in sync with the clock 5669327Sbde * interrupt even when we're delayed. 5671541Srgrimes */ 5681541Srgrimesvoid 569102074Sphkrealitexpire(void *arg) 5701541Srgrimes{ 571102074Sphk struct proc *p; 57235044Sphk struct timeval ctv, ntv; 5731541Srgrimes 5741541Srgrimes p = (struct proc *)arg; 57573916Sjhb PROC_LOCK(p); 5761541Srgrimes psignal(p, SIGALRM); 57735058Sphk if (!timevalisset(&p->p_realtimer.it_interval)) { 57835058Sphk timevalclear(&p->p_realtimer.it_value); 579116123Sjhb if (p->p_flag & P_WEXIT) 580116123Sjhb wakeup(&p->p_itcallout); 58173916Sjhb PROC_UNLOCK(p); 5821541Srgrimes return; 5831541Srgrimes } 5841541Srgrimes for (;;) { 5851541Srgrimes timevaladd(&p->p_realtimer.it_value, 5861541Srgrimes &p->p_realtimer.it_interval); 58736119Sphk getmicrouptime(&ctv); 58835058Sphk if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) { 58935044Sphk ntv = p->p_realtimer.it_value; 59035044Sphk timevalsub(&ntv, &ctv); 59169286Sjake callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1, 59269286Sjake realitexpire, p); 59373916Sjhb PROC_UNLOCK(p); 5941541Srgrimes return; 5951541Srgrimes } 5961541Srgrimes } 59773916Sjhb /*NOTREACHED*/ 5981541Srgrimes} 5991541Srgrimes 6001541Srgrimes/* 6011541Srgrimes * Check that a proposed value to load into the .it_value or 6021541Srgrimes * .it_interval part of an interval timer is acceptable, and 6031541Srgrimes * fix it to have at least minimal value (i.e. if it is less 6041541Srgrimes * than the resolution of the clock, round it up.) 6051541Srgrimes */ 6061549Srgrimesint 607102074Sphkitimerfix(struct timeval *tv) 6081541Srgrimes{ 6091541Srgrimes 6101541Srgrimes if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 6111541Srgrimes tv->tv_usec < 0 || tv->tv_usec >= 1000000) 6121541Srgrimes return (EINVAL); 6131541Srgrimes if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 6141541Srgrimes tv->tv_usec = tick; 6151541Srgrimes return (0); 6161541Srgrimes} 6171541Srgrimes 6181541Srgrimes/* 6191541Srgrimes * Decrement an interval timer by a specified number 6201541Srgrimes * of microseconds, which must be less than a second, 6211541Srgrimes * i.e. < 1000000. If the timer expires, then reload 6221541Srgrimes * it. In this case, carry over (usec - old value) to 6231541Srgrimes * reduce the value reloaded into the timer so that 6241541Srgrimes * the timer does not drift. This routine assumes 6251541Srgrimes * that it is called in a context where the timers 6261541Srgrimes * on which it is operating cannot change in value. 6271541Srgrimes */ 6281549Srgrimesint 629102074Sphkitimerdecr(struct itimerval *itp, int usec) 6301541Srgrimes{ 6311541Srgrimes 6321541Srgrimes if (itp->it_value.tv_usec < usec) { 6331541Srgrimes if (itp->it_value.tv_sec == 0) { 6341541Srgrimes /* expired, and already in next interval */ 6351541Srgrimes usec -= itp->it_value.tv_usec; 6361541Srgrimes goto expire; 6371541Srgrimes } 6381541Srgrimes itp->it_value.tv_usec += 1000000; 6391541Srgrimes itp->it_value.tv_sec--; 6401541Srgrimes } 6411541Srgrimes itp->it_value.tv_usec -= usec; 6421541Srgrimes usec = 0; 64335058Sphk if (timevalisset(&itp->it_value)) 6441541Srgrimes return (1); 6451541Srgrimes /* expired, exactly at end of interval */ 6461541Srgrimesexpire: 64735058Sphk if (timevalisset(&itp->it_interval)) { 6481541Srgrimes itp->it_value = itp->it_interval; 6491541Srgrimes itp->it_value.tv_usec -= usec; 6501541Srgrimes if (itp->it_value.tv_usec < 0) { 6511541Srgrimes itp->it_value.tv_usec += 1000000; 6521541Srgrimes itp->it_value.tv_sec--; 6531541Srgrimes } 6541541Srgrimes } else 6551541Srgrimes itp->it_value.tv_usec = 0; /* sec is already 0 */ 6561541Srgrimes return (0); 6571541Srgrimes} 6581541Srgrimes 6591541Srgrimes/* 6601541Srgrimes * Add and subtract routines for timevals. 6611541Srgrimes * N.B.: subtract routine doesn't deal with 6621541Srgrimes * results which are before the beginning, 6631541Srgrimes * it just gets very confused in this case. 6641541Srgrimes * Caveat emptor. 6651541Srgrimes */ 6661549Srgrimesvoid 667121523Salfredtimevaladd(struct timeval *t1, const struct timeval *t2) 6681541Srgrimes{ 6691541Srgrimes 6701541Srgrimes t1->tv_sec += t2->tv_sec; 6711541Srgrimes t1->tv_usec += t2->tv_usec; 6721541Srgrimes timevalfix(t1); 6731541Srgrimes} 6741541Srgrimes 6751549Srgrimesvoid 676121523Salfredtimevalsub(struct timeval *t1, const struct timeval *t2) 6771541Srgrimes{ 6781541Srgrimes 6791541Srgrimes t1->tv_sec -= t2->tv_sec; 6801541Srgrimes t1->tv_usec -= t2->tv_usec; 6811541Srgrimes timevalfix(t1); 6821541Srgrimes} 6831541Srgrimes 68412819Sphkstatic void 685102074Sphktimevalfix(struct timeval *t1) 6861541Srgrimes{ 6871541Srgrimes 6881541Srgrimes if (t1->tv_usec < 0) { 6891541Srgrimes t1->tv_sec--; 6901541Srgrimes t1->tv_usec += 1000000; 6911541Srgrimes } 6921541Srgrimes if (t1->tv_usec >= 1000000) { 6931541Srgrimes t1->tv_sec++; 6941541Srgrimes t1->tv_usec -= 1000000; 6951541Srgrimes } 6961541Srgrimes} 697108142Ssam 698108142Ssam/* 699108511Ssam * ratecheck(): simple time-based rate-limit checking. 700108142Ssam */ 701108142Ssamint 702108142Ssamratecheck(struct timeval *lasttime, const struct timeval *mininterval) 703108142Ssam{ 704108142Ssam struct timeval tv, delta; 705108142Ssam int rv = 0; 706108142Ssam 707108511Ssam getmicrouptime(&tv); /* NB: 10ms precision */ 708108511Ssam delta = tv; 709108511Ssam timevalsub(&delta, lasttime); 710108142Ssam 711108142Ssam /* 712108142Ssam * check for 0,0 is so that the message will be seen at least once, 713108142Ssam * even if interval is huge. 714108142Ssam */ 715108142Ssam if (timevalcmp(&delta, mininterval, >=) || 716108142Ssam (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 717108142Ssam *lasttime = tv; 718108142Ssam rv = 1; 719108142Ssam } 720108142Ssam 721108142Ssam return (rv); 722108142Ssam} 723108142Ssam 724108142Ssam/* 725108142Ssam * ppsratecheck(): packets (or events) per second limitation. 726108511Ssam * 727108511Ssam * Return 0 if the limit is to be enforced (e.g. the caller 728108511Ssam * should drop a packet because of the rate limitation). 729108511Ssam * 730111558Ssam * maxpps of 0 always causes zero to be returned. maxpps of -1 731111558Ssam * always causes 1 to be returned; this effectively defeats rate 732111558Ssam * limiting. 733111558Ssam * 734108511Ssam * Note that we maintain the struct timeval for compatibility 735108511Ssam * with other bsd systems. We reuse the storage and just monitor 736108511Ssam * clock ticks for minimal overhead. 737108142Ssam */ 738108142Ssamint 739108142Ssamppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 740108142Ssam{ 741108511Ssam int now; 742108142Ssam 743108142Ssam /* 744108511Ssam * Reset the last time and counter if this is the first call 745108511Ssam * or more than a second has passed since the last update of 746108511Ssam * lasttime. 747108142Ssam */ 748108511Ssam now = ticks; 749108511Ssam if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { 750108511Ssam lasttime->tv_sec = now; 751108511Ssam *curpps = 1; 752111558Ssam return (maxpps != 0); 753108511Ssam } else { 754108511Ssam (*curpps)++; /* NB: ignore potential overflow */ 755108511Ssam return (maxpps < 0 || *curpps < maxpps); 756108511Ssam } 757108142Ssam} 758