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: stable/10/sys/kern/kern_time.c 330422 2018-03-04 23:31:25Z bdrewery $"); 34116182Sobrien 35303093Skib#include "opt_ktrace.h" 36303093Skib 371541Srgrimes#include <sys/param.h> 3848274Speter#include <sys/systm.h> 39160910Sdavidxu#include <sys/limits.h> 40162954Sphk#include <sys/clock.h> 4176166Smarkm#include <sys/lock.h> 4276166Smarkm#include <sys/mutex.h> 4312221Sbde#include <sys/sysproto.h> 44153259Sdavidxu#include <sys/eventhandler.h> 451541Srgrimes#include <sys/resourcevar.h> 463308Sphk#include <sys/signalvar.h> 471541Srgrimes#include <sys/kernel.h> 48247797Sdavide#include <sys/sleepqueue.h> 49140483Sps#include <sys/syscallsubr.h> 50152983Sdavidxu#include <sys/sysctl.h> 5125583Speter#include <sys/sysent.h> 52164033Srwatson#include <sys/priv.h> 531541Srgrimes#include <sys/proc.h> 54164184Strhodes#include <sys/posix4.h> 5525656Speter#include <sys/time.h> 56151576Sdavidxu#include <sys/timers.h> 5758377Sphk#include <sys/timetc.h> 581541Srgrimes#include <sys/vnode.h> 59303093Skib#ifdef KTRACE 60303093Skib#include <sys/ktrace.h> 61303093Skib#endif 6276166Smarkm 6326335Speter#include <vm/vm.h> 6426335Speter#include <vm/vm_extern.h> 651541Srgrimes 66151576Sdavidxu#define MAX_CLOCKS (CLOCK_MONOTONIC+1) 67239347Sdavidxu#define CPUCLOCK_BIT 0x80000000 68239347Sdavidxu#define CPUCLOCK_PROCESS_BIT 0x40000000 69239347Sdavidxu#define CPUCLOCK_ID_MASK (~(CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT)) 70239347Sdavidxu#define MAKE_THREAD_CPUCLOCK(tid) (CPUCLOCK_BIT|(tid)) 71239347Sdavidxu#define MAKE_PROCESS_CPUCLOCK(pid) \ 72239347Sdavidxu (CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT|(pid)) 73151576Sdavidxu 74151576Sdavidxustatic struct kclock posix_clocks[MAX_CLOCKS]; 75151576Sdavidxustatic uma_zone_t itimer_zone = NULL; 76151576Sdavidxu 778876Srgrimes/* 781541Srgrimes * Time of day and interval timer support. 791541Srgrimes * 801541Srgrimes * These routines provide the kernel entry points to get and set 811541Srgrimes * the time-of-day and per-process interval timers. Subroutines 821541Srgrimes * here provide support for adding and subtracting timeval structures 831541Srgrimes * and decrementing interval timers, optionally reloading the interval 841541Srgrimes * timers when they expire. 851541Srgrimes */ 861541Srgrimes 8794343Sjhbstatic int settime(struct thread *, struct timeval *); 8892723Salfredstatic void timevalfix(struct timeval *); 8913016Sbde 90151576Sdavidxustatic void itimer_start(void); 91151576Sdavidxustatic int itimer_init(void *, int, int); 92151576Sdavidxustatic void itimer_fini(void *, int); 93151576Sdavidxustatic void itimer_enter(struct itimer *); 94151576Sdavidxustatic void itimer_leave(struct itimer *); 95164713Sdavidxustatic struct itimer *itimer_find(struct proc *, int); 96151576Sdavidxustatic void itimers_alloc(struct proc *); 97161302Snetchildstatic void itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp); 98161302Snetchildstatic void itimers_event_hook_exit(void *arg, struct proc *p); 99151576Sdavidxustatic int realtimer_create(struct itimer *); 100151576Sdavidxustatic int realtimer_gettime(struct itimer *, struct itimerspec *); 101151576Sdavidxustatic int realtimer_settime(struct itimer *, int, 102151576Sdavidxu struct itimerspec *, struct itimerspec *); 103151576Sdavidxustatic int realtimer_delete(struct itimer *); 104151869Sdavidxustatic void realtimer_clocktime(clockid_t, struct timespec *); 105151576Sdavidxustatic void realtimer_expire(void *); 106151576Sdavidxu 107151576Sdavidxuint register_posix_clock(int, struct kclock *); 108151576Sdavidxuvoid itimer_fire(struct itimer *it); 109151869Sdavidxuint itimespecfix(struct timespec *ts); 110151576Sdavidxu 111151576Sdavidxu#define CLOCK_CALL(clock, call, arglist) \ 112151576Sdavidxu ((*posix_clocks[clock].call) arglist) 113151576Sdavidxu 114151576SdavidxuSYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL); 115151576Sdavidxu 116151576Sdavidxu 11725583Speterstatic int 118102074Sphksettime(struct thread *td, struct timeval *tv) 11925583Speter{ 12045433Snsayer struct timeval delta, tv1, tv2; 12145438Snsayer static struct timeval maxtime, laststep; 12233690Sphk struct timespec ts; 12325583Speter int s; 12425583Speter 12525656Speter s = splclock(); 12633818Sbde microtime(&tv1); 12735029Sphk delta = *tv; 12835029Sphk timevalsub(&delta, &tv1); 12925583Speter 13025583Speter /* 13133818Sbde * If the system is secure, we do not allow the time to be 13245433Snsayer * set to a value earlier than 1 second less than the highest 13345433Snsayer * time we have yet seen. The worst a miscreant can do in 13445433Snsayer * this circumstance is "freeze" time. He couldn't go 13545433Snsayer * back to the past. 13645438Snsayer * 13745438Snsayer * We similarly do not allow the clock to be stepped more 13845438Snsayer * than one second, nor more than once per second. This allows 13945438Snsayer * a miscreant to make the clock march double-time, but no worse. 14025583Speter */ 14194343Sjhb if (securelevel_gt(td->td_ucred, 1) != 0) { 14245433Snsayer if (delta.tv_sec < 0 || delta.tv_usec < 0) { 14345437Smjacob /* 14445438Snsayer * Update maxtime to latest time we've seen. 14545437Smjacob */ 14645437Smjacob if (tv1.tv_sec > maxtime.tv_sec) 14745437Smjacob maxtime = tv1; 14845437Smjacob tv2 = *tv; 14945437Smjacob timevalsub(&tv2, &maxtime); 15045437Smjacob if (tv2.tv_sec < -1) { 15145437Smjacob tv->tv_sec = maxtime.tv_sec - 1; 15245433Snsayer printf("Time adjustment clamped to -1 second\n"); 15345433Snsayer } 15445437Smjacob } else { 15545438Snsayer if (tv1.tv_sec == laststep.tv_sec) { 15645438Snsayer splx(s); 15745438Snsayer return (EPERM); 15845438Snsayer } 15945438Snsayer if (delta.tv_sec > 1) { 16045438Snsayer tv->tv_sec = tv1.tv_sec + 1; 16145438Snsayer printf("Time adjustment clamped to +1 second\n"); 16245438Snsayer } 16345438Snsayer laststep = *tv; 16445433Snsayer } 16533818Sbde } 16633818Sbde 16733690Sphk ts.tv_sec = tv->tv_sec; 16833690Sphk ts.tv_nsec = tv->tv_usec * 1000; 16994343Sjhb mtx_lock(&Giant); 17058377Sphk tc_setclock(&ts); 17125583Speter resettodr(); 17294343Sjhb mtx_unlock(&Giant); 17325583Speter return (0); 17425583Speter} 17525583Speter 17612221Sbde#ifndef _SYS_SYSPROTO_H_ 177239347Sdavidxustruct clock_getcpuclockid2_args { 178239347Sdavidxu id_t id; 179239347Sdavidxu int which, 180239347Sdavidxu clockid_t *clock_id; 181239347Sdavidxu}; 182239347Sdavidxu#endif 183239347Sdavidxu/* ARGSUSED */ 184239347Sdavidxuint 185239347Sdavidxusys_clock_getcpuclockid2(struct thread *td, struct clock_getcpuclockid2_args *uap) 186239347Sdavidxu{ 187239347Sdavidxu clockid_t clk_id; 188253494Skib int error; 189253494Skib 190253494Skib error = kern_clock_getcpuclockid2(td, uap->id, uap->which, &clk_id); 191253494Skib if (error == 0) 192253494Skib error = copyout(&clk_id, uap->clock_id, sizeof(clockid_t)); 193253494Skib return (error); 194253494Skib} 195253494Skib 196253494Skibint 197253494Skibkern_clock_getcpuclockid2(struct thread *td, id_t id, int which, 198253494Skib clockid_t *clk_id) 199253494Skib{ 200239347Sdavidxu struct proc *p; 201239347Sdavidxu pid_t pid; 202239347Sdavidxu lwpid_t tid; 203239347Sdavidxu int error; 204239347Sdavidxu 205253494Skib switch (which) { 206239347Sdavidxu case CPUCLOCK_WHICH_PID: 207253494Skib if (id != 0) { 208277287Sdchagin error = pget(id, PGET_CANSEE | PGET_NOTID, &p); 209253494Skib if (error != 0) 210239347Sdavidxu return (error); 211277287Sdchagin PROC_UNLOCK(p); 212253494Skib pid = id; 213239347Sdavidxu } else { 214239347Sdavidxu pid = td->td_proc->p_pid; 215239347Sdavidxu } 216253494Skib *clk_id = MAKE_PROCESS_CPUCLOCK(pid); 217253494Skib return (0); 218239347Sdavidxu case CPUCLOCK_WHICH_TID: 219253494Skib tid = id == 0 ? td->td_tid : id; 220253494Skib *clk_id = MAKE_THREAD_CPUCLOCK(tid); 221253494Skib return (0); 222239347Sdavidxu default: 223239347Sdavidxu return (EINVAL); 224239347Sdavidxu } 225239347Sdavidxu} 226239347Sdavidxu 227239347Sdavidxu#ifndef _SYS_SYSPROTO_H_ 22825583Speterstruct clock_gettime_args { 22925583Speter clockid_t clock_id; 23025583Speter struct timespec *tp; 23125583Speter}; 23225583Speter#endif 23325583Speter/* ARGSUSED */ 23425583Speterint 235225617Skmacysys_clock_gettime(struct thread *td, struct clock_gettime_args *uap) 23625583Speter{ 23725583Speter struct timespec ats; 238151357Sps int error; 239151357Sps 240151357Sps error = kern_clock_gettime(td, uap->clock_id, &ats); 241151357Sps if (error == 0) 242151357Sps error = copyout(&ats, uap->tp, sizeof(ats)); 243151357Sps 244151357Sps return (error); 245151357Sps} 246151357Sps 247239347Sdavidxustatic inline void 248239347Sdavidxucputick2timespec(uint64_t runtime, struct timespec *ats) 249239347Sdavidxu{ 250239347Sdavidxu runtime = cputick2usec(runtime); 251239347Sdavidxu ats->tv_sec = runtime / 1000000; 252239347Sdavidxu ats->tv_nsec = runtime % 1000000 * 1000; 253239347Sdavidxu} 254239347Sdavidxu 255239347Sdavidxustatic void 256239347Sdavidxuget_thread_cputime(struct thread *targettd, struct timespec *ats) 257239347Sdavidxu{ 258239347Sdavidxu uint64_t runtime, curtime, switchtime; 259239347Sdavidxu 260239347Sdavidxu if (targettd == NULL) { /* current thread */ 261239347Sdavidxu critical_enter(); 262239347Sdavidxu switchtime = PCPU_GET(switchtime); 263239347Sdavidxu curtime = cpu_ticks(); 264239347Sdavidxu runtime = curthread->td_runtime; 265239347Sdavidxu critical_exit(); 266239347Sdavidxu runtime += curtime - switchtime; 267239347Sdavidxu } else { 268239347Sdavidxu thread_lock(targettd); 269239347Sdavidxu runtime = targettd->td_runtime; 270239347Sdavidxu thread_unlock(targettd); 271239347Sdavidxu } 272239347Sdavidxu cputick2timespec(runtime, ats); 273239347Sdavidxu} 274239347Sdavidxu 275239347Sdavidxustatic void 276239347Sdavidxuget_process_cputime(struct proc *targetp, struct timespec *ats) 277239347Sdavidxu{ 278239347Sdavidxu uint64_t runtime; 279239347Sdavidxu struct rusage ru; 280239347Sdavidxu 281293473Sdchagin PROC_STATLOCK(targetp); 282239347Sdavidxu rufetch(targetp, &ru); 283239347Sdavidxu runtime = targetp->p_rux.rux_runtime; 284293473Sdchagin PROC_STATUNLOCK(targetp); 285239347Sdavidxu cputick2timespec(runtime, ats); 286239347Sdavidxu} 287239347Sdavidxu 288239347Sdavidxustatic int 289239347Sdavidxuget_cputime(struct thread *td, clockid_t clock_id, struct timespec *ats) 290239347Sdavidxu{ 291239347Sdavidxu struct proc *p, *p2; 292239347Sdavidxu struct thread *td2; 293239347Sdavidxu lwpid_t tid; 294239347Sdavidxu pid_t pid; 295239347Sdavidxu int error; 296239347Sdavidxu 297239347Sdavidxu p = td->td_proc; 298239347Sdavidxu if ((clock_id & CPUCLOCK_PROCESS_BIT) == 0) { 299239347Sdavidxu tid = clock_id & CPUCLOCK_ID_MASK; 300239347Sdavidxu td2 = tdfind(tid, p->p_pid); 301239347Sdavidxu if (td2 == NULL) 302239347Sdavidxu return (EINVAL); 303239347Sdavidxu get_thread_cputime(td2, ats); 304239347Sdavidxu PROC_UNLOCK(td2->td_proc); 305239347Sdavidxu } else { 306239347Sdavidxu pid = clock_id & CPUCLOCK_ID_MASK; 307253325Skib error = pget(pid, PGET_CANSEE, &p2); 308253325Skib if (error != 0) 309239347Sdavidxu return (EINVAL); 310239347Sdavidxu get_process_cputime(p2, ats); 311239347Sdavidxu PROC_UNLOCK(p2); 312239347Sdavidxu } 313239347Sdavidxu return (0); 314239347Sdavidxu} 315239347Sdavidxu 316151357Spsint 317151357Spskern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats) 318151357Sps{ 319130884Skbyanc struct timeval sys, user; 320136152Sjhb struct proc *p; 32125583Speter 322136152Sjhb p = td->td_proc; 323151357Sps switch (clock_id) { 324152844Srwatson case CLOCK_REALTIME: /* Default to precise. */ 325152844Srwatson case CLOCK_REALTIME_PRECISE: 326151357Sps nanotime(ats); 327130654Skbyanc break; 328152844Srwatson case CLOCK_REALTIME_FAST: 329152844Srwatson getnanotime(ats); 330152844Srwatson break; 331130654Skbyanc case CLOCK_VIRTUAL: 332136152Sjhb PROC_LOCK(p); 333293473Sdchagin PROC_STATLOCK(p); 334136152Sjhb calcru(p, &user, &sys); 335293473Sdchagin PROC_STATUNLOCK(p); 336136152Sjhb PROC_UNLOCK(p); 337151357Sps TIMEVAL_TO_TIMESPEC(&user, ats); 338130654Skbyanc break; 339130654Skbyanc case CLOCK_PROF: 340136152Sjhb PROC_LOCK(p); 341293473Sdchagin PROC_STATLOCK(p); 342136152Sjhb calcru(p, &user, &sys); 343293473Sdchagin PROC_STATUNLOCK(p); 344136152Sjhb PROC_UNLOCK(p); 345130884Skbyanc timevaladd(&user, &sys); 346151357Sps TIMEVAL_TO_TIMESPEC(&user, ats); 347130654Skbyanc break; 348152844Srwatson case CLOCK_MONOTONIC: /* Default to precise. */ 349152844Srwatson case CLOCK_MONOTONIC_PRECISE: 350152585Sandre case CLOCK_UPTIME: 351152844Srwatson case CLOCK_UPTIME_PRECISE: 352151357Sps nanouptime(ats); 353130884Skbyanc break; 354152844Srwatson case CLOCK_UPTIME_FAST: 355152844Srwatson case CLOCK_MONOTONIC_FAST: 356152844Srwatson getnanouptime(ats); 357152844Srwatson break; 358152844Srwatson case CLOCK_SECOND: 359152844Srwatson ats->tv_sec = time_second; 360152844Srwatson ats->tv_nsec = 0; 361152844Srwatson break; 362175429Sdavidxu case CLOCK_THREAD_CPUTIME_ID: 363239347Sdavidxu get_thread_cputime(NULL, ats); 364175429Sdavidxu break; 365239347Sdavidxu case CLOCK_PROCESS_CPUTIME_ID: 366239347Sdavidxu PROC_LOCK(p); 367239347Sdavidxu get_process_cputime(p, ats); 368239347Sdavidxu PROC_UNLOCK(p); 369239347Sdavidxu break; 370130654Skbyanc default: 371239347Sdavidxu if ((int)clock_id >= 0) 372239347Sdavidxu return (EINVAL); 373239347Sdavidxu return (get_cputime(td, clock_id, ats)); 374130654Skbyanc } 375151357Sps return (0); 37625583Speter} 37725583Speter 37825583Speter#ifndef _SYS_SYSPROTO_H_ 37925583Speterstruct clock_settime_args { 38025583Speter clockid_t clock_id; 38125583Speter const struct timespec *tp; 38225583Speter}; 38325583Speter#endif 38425583Speter/* ARGSUSED */ 38525583Speterint 386225617Skmacysys_clock_settime(struct thread *td, struct clock_settime_args *uap) 38725583Speter{ 38825583Speter struct timespec ats; 38925583Speter int error; 39025583Speter 391151357Sps if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0) 392151357Sps return (error); 393151357Sps return (kern_clock_settime(td, uap->clock_id, &ats)); 394151357Sps} 395151357Sps 396151357Spsint 397151357Spskern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats) 398151357Sps{ 399151357Sps struct timeval atv; 400151357Sps int error; 401151357Sps 402164033Srwatson if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) 40394343Sjhb return (error); 404151357Sps if (clock_id != CLOCK_REALTIME) 40594343Sjhb return (EINVAL); 406151357Sps if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000) 40794343Sjhb return (EINVAL); 40834901Sphk /* XXX Don't convert nsec->usec and back */ 409151357Sps TIMESPEC_TO_TIMEVAL(&atv, ats); 41094343Sjhb error = settime(td, &atv); 41182746Sdillon return (error); 41225583Speter} 41325583Speter 41425583Speter#ifndef _SYS_SYSPROTO_H_ 41525583Speterstruct clock_getres_args { 41625583Speter clockid_t clock_id; 41725583Speter struct timespec *tp; 41825583Speter}; 41925583Speter#endif 42025583Speterint 421225617Skmacysys_clock_getres(struct thread *td, struct clock_getres_args *uap) 42225583Speter{ 42325583Speter struct timespec ts; 424151357Sps int error; 42525583Speter 426151357Sps if (uap->tp == NULL) 427151357Sps return (0); 428151357Sps 429151357Sps error = kern_clock_getres(td, uap->clock_id, &ts); 430151357Sps if (error == 0) 431151357Sps error = copyout(&ts, uap->tp, sizeof(ts)); 432151357Sps return (error); 433151357Sps} 434151357Sps 435151357Spsint 436151357Spskern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts) 437151357Sps{ 438151357Sps 439151357Sps ts->tv_sec = 0; 440151357Sps switch (clock_id) { 441130654Skbyanc case CLOCK_REALTIME: 442152844Srwatson case CLOCK_REALTIME_FAST: 443152844Srwatson case CLOCK_REALTIME_PRECISE: 444130654Skbyanc case CLOCK_MONOTONIC: 445152844Srwatson case CLOCK_MONOTONIC_FAST: 446152844Srwatson case CLOCK_MONOTONIC_PRECISE: 447152585Sandre case CLOCK_UPTIME: 448152844Srwatson case CLOCK_UPTIME_FAST: 449152844Srwatson case CLOCK_UPTIME_PRECISE: 450103964Sbde /* 451103964Sbde * Round up the result of the division cheaply by adding 1. 452103964Sbde * Rounding up is especially important if rounding down 453103964Sbde * would give 0. Perfect rounding is unimportant. 454103964Sbde */ 455151357Sps ts->tv_nsec = 1000000000 / tc_getfrequency() + 1; 456130654Skbyanc break; 457130654Skbyanc case CLOCK_VIRTUAL: 458130654Skbyanc case CLOCK_PROF: 459130654Skbyanc /* Accurately round up here because we can do so cheaply. */ 460151357Sps ts->tv_nsec = (1000000000 + hz - 1) / hz; 461130654Skbyanc break; 462152844Srwatson case CLOCK_SECOND: 463152844Srwatson ts->tv_sec = 1; 464152844Srwatson ts->tv_nsec = 0; 465152844Srwatson break; 466175429Sdavidxu case CLOCK_THREAD_CPUTIME_ID: 467239347Sdavidxu case CLOCK_PROCESS_CPUTIME_ID: 468239347Sdavidxu cputime: 469175429Sdavidxu /* sync with cputick2usec */ 470175429Sdavidxu ts->tv_nsec = 1000000 / cpu_tickrate(); 471175429Sdavidxu if (ts->tv_nsec == 0) 472175429Sdavidxu ts->tv_nsec = 1000; 473175429Sdavidxu break; 474130654Skbyanc default: 475239347Sdavidxu if ((int)clock_id < 0) 476239347Sdavidxu goto cputime; 477130654Skbyanc return (EINVAL); 478130654Skbyanc } 479151357Sps return (0); 48025583Speter} 48125583Speter 482248186Smavstatic uint8_t nanowait[MAXCPU]; 48325656Speter 484140481Spsint 485140481Spskern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) 48625583Speter{ 487247797Sdavide struct timespec ts; 488247797Sdavide sbintime_t sbt, sbtt, prec, tmp; 489247898Smav time_t over; 49035042Sphk int error; 49125583Speter 49228773Sbde if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) 49325656Speter return (EINVAL); 49443301Sdillon if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) 49528773Sbde return (0); 496247898Smav ts = *rqt; 497247898Smav if (ts.tv_sec > INT32_MAX / 2) { 498247898Smav over = ts.tv_sec - INT32_MAX / 2; 499247898Smav ts.tv_sec -= over; 500247898Smav } else 501247898Smav over = 0; 502247898Smav tmp = tstosbt(ts); 503247797Sdavide prec = tmp; 504247797Sdavide prec >>= tc_precexp; 505247797Sdavide if (TIMESEL(&sbt, tmp)) 506247797Sdavide sbt += tc_tick_sbt; 507247797Sdavide sbt += tmp; 508248186Smav error = tsleep_sbt(&nanowait[curcpu], PWAIT | PCATCH, "nanslp", 509248186Smav sbt, prec, C_ABSOLUTE); 510247797Sdavide if (error != EWOULDBLOCK) { 511247797Sdavide if (error == ERESTART) 512247797Sdavide error = EINTR; 513330422Sbdrewery if (TIMESEL(&sbtt, tmp)) 514330422Sbdrewery sbtt += tc_tick_sbt; 515247797Sdavide if (rmt != NULL) { 516247797Sdavide ts = sbttots(sbt - sbtt); 517247898Smav ts.tv_sec += over; 518247797Sdavide if (ts.tv_sec < 0) 519247797Sdavide timespecclear(&ts); 520247797Sdavide *rmt = ts; 52135042Sphk } 522247797Sdavide if (sbtt >= sbt) 52335042Sphk return (0); 524247797Sdavide return (error); 52526335Speter } 526247797Sdavide return (0); 52726335Speter} 52825583Speter 52926335Speter#ifndef _SYS_SYSPROTO_H_ 53026335Speterstruct nanosleep_args { 53126335Speter struct timespec *rqtp; 53226335Speter struct timespec *rmtp; 53326335Speter}; 53426335Speter#endif 53526335Speter/* ARGSUSED */ 53626335Speterint 537225617Skmacysys_nanosleep(struct thread *td, struct nanosleep_args *uap) 53826335Speter{ 53926335Speter struct timespec rmt, rqt; 54082746Sdillon int error; 54126335Speter 542107849Salfred error = copyin(uap->rqtp, &rqt, sizeof(rqt)); 54326335Speter if (error) 54426335Speter return (error); 54582746Sdillon 546109521Salfred if (uap->rmtp && 547109521Salfred !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 548109521Salfred return (EFAULT); 549140481Sps error = kern_nanosleep(td, &rqt, &rmt); 550315658Svangyzen if (error == EINTR && uap->rmtp) { 55182746Sdillon int error2; 55282746Sdillon 553107849Salfred error2 = copyout(&rmt, uap->rmtp, sizeof(rmt)); 554109521Salfred if (error2) 55582746Sdillon error = error2; 55625583Speter } 55725656Speter return (error); 55825583Speter} 55925583Speter 56026335Speter#ifndef _SYS_SYSPROTO_H_ 5611541Srgrimesstruct gettimeofday_args { 5621541Srgrimes struct timeval *tp; 5631541Srgrimes struct timezone *tzp; 5641541Srgrimes}; 56512221Sbde#endif 5661541Srgrimes/* ARGSUSED */ 5671549Srgrimesint 568225617Skmacysys_gettimeofday(struct thread *td, struct gettimeofday_args *uap) 5691541Srgrimes{ 5701541Srgrimes struct timeval atv; 571110286Stjr struct timezone rtz; 5721541Srgrimes int error = 0; 5731541Srgrimes 5741541Srgrimes if (uap->tp) { 5751541Srgrimes microtime(&atv); 57699012Salfred error = copyout(&atv, uap->tp, sizeof (atv)); 5771541Srgrimes } 57890836Sphk if (error == 0 && uap->tzp != NULL) { 579110299Sphk rtz.tz_minuteswest = tz_minuteswest; 580110299Sphk rtz.tz_dsttime = tz_dsttime; 581110286Stjr error = copyout(&rtz, uap->tzp, sizeof (rtz)); 58282746Sdillon } 5831541Srgrimes return (error); 5841541Srgrimes} 5851541Srgrimes 58612221Sbde#ifndef _SYS_SYSPROTO_H_ 5871541Srgrimesstruct settimeofday_args { 5881541Srgrimes struct timeval *tv; 5891541Srgrimes struct timezone *tzp; 5901541Srgrimes}; 59112221Sbde#endif 5921541Srgrimes/* ARGSUSED */ 5931549Srgrimesint 594225617Skmacysys_settimeofday(struct thread *td, struct settimeofday_args *uap) 5951541Srgrimes{ 596144445Sjhb struct timeval atv, *tvp; 597144445Sjhb struct timezone atz, *tzp; 598144445Sjhb int error; 5991541Srgrimes 600144445Sjhb if (uap->tv) { 601144445Sjhb error = copyin(uap->tv, &atv, sizeof(atv)); 602144445Sjhb if (error) 603144445Sjhb return (error); 604144445Sjhb tvp = &atv; 605144445Sjhb } else 606144445Sjhb tvp = NULL; 607144445Sjhb if (uap->tzp) { 608144445Sjhb error = copyin(uap->tzp, &atz, sizeof(atz)); 609144445Sjhb if (error) 610144445Sjhb return (error); 611144445Sjhb tzp = &atz; 612144445Sjhb } else 613144445Sjhb tzp = NULL; 614144445Sjhb return (kern_settimeofday(td, tvp, tzp)); 615144445Sjhb} 616144445Sjhb 617144445Sjhbint 618144445Sjhbkern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp) 619144445Sjhb{ 620144445Sjhb int error; 621144445Sjhb 622164033Srwatson error = priv_check(td, PRIV_SETTIMEOFDAY); 623144445Sjhb if (error) 62494343Sjhb return (error); 6251541Srgrimes /* Verify all parameters before changing time. */ 626144445Sjhb if (tv) { 627144445Sjhb if (tv->tv_usec < 0 || tv->tv_usec >= 1000000) 62894343Sjhb return (EINVAL); 629144445Sjhb error = settime(td, tv); 63025656Speter } 631144445Sjhb if (tzp && error == 0) { 632144445Sjhb tz_minuteswest = tzp->tz_minuteswest; 633144445Sjhb tz_dsttime = tzp->tz_dsttime; 63482746Sdillon } 63582746Sdillon return (error); 6361541Srgrimes} 637144445Sjhb 63882746Sdillon/* 639167232Srwatson * Get value of an interval timer. The process virtual and profiling virtual 640167232Srwatson * time timers are kept in the p_stats area, since they can be swapped out. 641167232Srwatson * These are kept internally in the way they are specified externally: in 642167232Srwatson * time until they expire. 6431541Srgrimes * 644167232Srwatson * The real time interval timer is kept in the process table slot for the 645167232Srwatson * process, and its value (it_value) is kept as an absolute time rather than 646167232Srwatson * as a delta, so that it is easy to keep periodic real-time signals from 647167232Srwatson * drifting. 6481541Srgrimes * 6491541Srgrimes * Virtual time timers are processed in the hardclock() routine of 650167232Srwatson * kern_clock.c. The real time timer is processed by a timeout routine, 651167232Srwatson * called from the softclock() routine. Since a callout may be delayed in 652167232Srwatson * real time due to interrupt processing in the system, it is possible for 653167232Srwatson * the real time timeout routine (realitexpire, given below), to be delayed 654167232Srwatson * in real time past when it is supposed to occur. It does not suffice, 655167232Srwatson * therefore, to reload the real timer .it_value from the real time timers 656167232Srwatson * .it_interval. Rather, we compute the next time in absolute time the timer 657167232Srwatson * should go off. 6581541Srgrimes */ 65912221Sbde#ifndef _SYS_SYSPROTO_H_ 6601541Srgrimesstruct getitimer_args { 6611541Srgrimes u_int which; 6621541Srgrimes struct itimerval *itv; 6631541Srgrimes}; 66412221Sbde#endif 6651549Srgrimesint 666225617Skmacysys_getitimer(struct thread *td, struct getitimer_args *uap) 6671541Srgrimes{ 668141470Sjhb struct itimerval aitv; 669140832Ssobomax int error; 670140832Ssobomax 671140832Ssobomax error = kern_getitimer(td, uap->which, &aitv); 672140832Ssobomax if (error != 0) 673140832Ssobomax return (error); 674140832Ssobomax return (copyout(&aitv, uap->itv, sizeof (struct itimerval))); 675140832Ssobomax} 676140832Ssobomax 677140832Ssobomaxint 678140832Ssobomaxkern_getitimer(struct thread *td, u_int which, struct itimerval *aitv) 679140832Ssobomax{ 68083366Sjulian struct proc *p = td->td_proc; 68134961Sphk struct timeval ctv; 6821541Srgrimes 683140832Ssobomax if (which > ITIMER_PROF) 6841541Srgrimes return (EINVAL); 68582746Sdillon 686140832Ssobomax if (which == ITIMER_REAL) { 6871541Srgrimes /* 68836128Sbde * Convert from absolute to relative time in .it_value 6891541Srgrimes * part of real time timer. If time for real time timer 6901541Srgrimes * has passed return 0, else return difference between 6911541Srgrimes * current time and time for the timer to go off. 6921541Srgrimes */ 693111034Stjr PROC_LOCK(p); 694140832Ssobomax *aitv = p->p_realtimer; 695111034Stjr PROC_UNLOCK(p); 696140832Ssobomax if (timevalisset(&aitv->it_value)) { 697247903Smav microuptime(&ctv); 698140832Ssobomax if (timevalcmp(&aitv->it_value, &ctv, <)) 699140832Ssobomax timevalclear(&aitv->it_value); 7001541Srgrimes else 701140832Ssobomax timevalsub(&aitv->it_value, &ctv); 70234961Sphk } 70382746Sdillon } else { 704293473Sdchagin PROC_ITIMLOCK(p); 705140832Ssobomax *aitv = p->p_stats->p_timer[which]; 706293473Sdchagin PROC_ITIMUNLOCK(p); 70782746Sdillon } 708303093Skib#ifdef KTRACE 709303093Skib if (KTRPOINT(td, KTR_STRUCT)) 710303093Skib ktritimerval(aitv); 711303093Skib#endif 712140832Ssobomax return (0); 7131541Srgrimes} 7141541Srgrimes 71512221Sbde#ifndef _SYS_SYSPROTO_H_ 7161541Srgrimesstruct setitimer_args { 7171541Srgrimes u_int which; 7181541Srgrimes struct itimerval *itv, *oitv; 7191541Srgrimes}; 72012221Sbde#endif 7211549Srgrimesint 722225617Skmacysys_setitimer(struct thread *td, struct setitimer_args *uap) 7231541Srgrimes{ 724141470Sjhb struct itimerval aitv, oitv; 725140832Ssobomax int error; 7261541Srgrimes 727111034Stjr if (uap->itv == NULL) { 728111034Stjr uap->itv = uap->oitv; 729225617Skmacy return (sys_getitimer(td, (struct getitimer_args *)uap)); 730111034Stjr } 731111034Stjr 732111034Stjr if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval)))) 7331541Srgrimes return (error); 734140832Ssobomax error = kern_setitimer(td, uap->which, &aitv, &oitv); 735140832Ssobomax if (error != 0 || uap->oitv == NULL) 736140832Ssobomax return (error); 737140832Ssobomax return (copyout(&oitv, uap->oitv, sizeof(struct itimerval))); 738140832Ssobomax} 739140832Ssobomax 740140832Ssobomaxint 741141470Sjhbkern_setitimer(struct thread *td, u_int which, struct itimerval *aitv, 742141470Sjhb struct itimerval *oitv) 743140832Ssobomax{ 744140832Ssobomax struct proc *p = td->td_proc; 745140832Ssobomax struct timeval ctv; 746247903Smav sbintime_t sbt, pr; 747140832Ssobomax 748141483Sjhb if (aitv == NULL) 749141483Sjhb return (kern_getitimer(td, which, oitv)); 750141483Sjhb 751140832Ssobomax if (which > ITIMER_PROF) 752111034Stjr return (EINVAL); 753303093Skib#ifdef KTRACE 754303093Skib if (KTRPOINT(td, KTR_STRUCT)) 755303093Skib ktritimerval(aitv); 756303093Skib#endif 757247903Smav if (itimerfix(&aitv->it_value) || 758247903Smav aitv->it_value.tv_sec > INT32_MAX / 2) 759111034Stjr return (EINVAL); 760140832Ssobomax if (!timevalisset(&aitv->it_value)) 761140832Ssobomax timevalclear(&aitv->it_interval); 762247903Smav else if (itimerfix(&aitv->it_interval) || 763247903Smav aitv->it_interval.tv_sec > INT32_MAX / 2) 764140832Ssobomax return (EINVAL); 76582746Sdillon 766140832Ssobomax if (which == ITIMER_REAL) { 767111034Stjr PROC_LOCK(p); 76835058Sphk if (timevalisset(&p->p_realtimer.it_value)) 76969286Sjake callout_stop(&p->p_itcallout); 770247903Smav microuptime(&ctv); 771140832Ssobomax if (timevalisset(&aitv->it_value)) { 772247903Smav pr = tvtosbt(aitv->it_value) >> tc_precexp; 773140832Ssobomax timevaladd(&aitv->it_value, &ctv); 774247903Smav sbt = tvtosbt(aitv->it_value); 775247903Smav callout_reset_sbt(&p->p_itcallout, sbt, pr, 776247903Smav realitexpire, p, C_ABSOLUTE); 777114980Sjhb } 778140832Ssobomax *oitv = p->p_realtimer; 779140832Ssobomax p->p_realtimer = *aitv; 780111034Stjr PROC_UNLOCK(p); 781140832Ssobomax if (timevalisset(&oitv->it_value)) { 782140832Ssobomax if (timevalcmp(&oitv->it_value, &ctv, <)) 783140832Ssobomax timevalclear(&oitv->it_value); 784111034Stjr else 785140832Ssobomax timevalsub(&oitv->it_value, &ctv); 786111034Stjr } 78782746Sdillon } else { 788264821Smav if (aitv->it_interval.tv_sec == 0 && 789264821Smav aitv->it_interval.tv_usec != 0 && 790264821Smav aitv->it_interval.tv_usec < tick) 791264821Smav aitv->it_interval.tv_usec = tick; 792264821Smav if (aitv->it_value.tv_sec == 0 && 793264821Smav aitv->it_value.tv_usec != 0 && 794264821Smav aitv->it_value.tv_usec < tick) 795264821Smav aitv->it_value.tv_usec = tick; 796293473Sdchagin PROC_ITIMLOCK(p); 797140832Ssobomax *oitv = p->p_stats->p_timer[which]; 798140832Ssobomax p->p_stats->p_timer[which] = *aitv; 799293473Sdchagin PROC_ITIMUNLOCK(p); 80082746Sdillon } 801303093Skib#ifdef KTRACE 802303093Skib if (KTRPOINT(td, KTR_STRUCT)) 803303093Skib ktritimerval(oitv); 804303093Skib#endif 805140832Ssobomax return (0); 8061541Srgrimes} 8071541Srgrimes 8081541Srgrimes/* 8091541Srgrimes * Real interval timer expired: 8101541Srgrimes * send process whose timer expired an alarm signal. 8111541Srgrimes * If time is not set up to reload, then just return. 8121541Srgrimes * Else compute next time timer should go off which is > current time. 8131541Srgrimes * This is where delay in processing this timeout causes multiple 8141541Srgrimes * SIGALRM calls to be compressed into one. 81536127Sbde * tvtohz() always adds 1 to allow for the time until the next clock 8169327Sbde * interrupt being strictly less than 1 clock tick, but we don't want 8179327Sbde * that here since we want to appear to be in sync with the clock 8189327Sbde * interrupt even when we're delayed. 8191541Srgrimes */ 8201541Srgrimesvoid 821102074Sphkrealitexpire(void *arg) 8221541Srgrimes{ 823102074Sphk struct proc *p; 824247903Smav struct timeval ctv; 825247903Smav sbintime_t isbt; 8261541Srgrimes 8271541Srgrimes p = (struct proc *)arg; 828225617Skmacy kern_psignal(p, SIGALRM); 82935058Sphk if (!timevalisset(&p->p_realtimer.it_interval)) { 83035058Sphk timevalclear(&p->p_realtimer.it_value); 831116123Sjhb if (p->p_flag & P_WEXIT) 832116123Sjhb wakeup(&p->p_itcallout); 8331541Srgrimes return; 8341541Srgrimes } 835247903Smav isbt = tvtosbt(p->p_realtimer.it_interval); 836247903Smav if (isbt >= sbt_timethreshold) 837247903Smav getmicrouptime(&ctv); 838247903Smav else 839247903Smav microuptime(&ctv); 840247903Smav do { 8411541Srgrimes timevaladd(&p->p_realtimer.it_value, 8421541Srgrimes &p->p_realtimer.it_interval); 843247903Smav } while (timevalcmp(&p->p_realtimer.it_value, &ctv, <=)); 844247903Smav callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value), 845247903Smav isbt >> tc_precexp, realitexpire, p, C_ABSOLUTE); 8461541Srgrimes} 8471541Srgrimes 8481541Srgrimes/* 8491541Srgrimes * Check that a proposed value to load into the .it_value or 8501541Srgrimes * .it_interval part of an interval timer is acceptable, and 8511541Srgrimes * fix it to have at least minimal value (i.e. if it is less 8521541Srgrimes * than the resolution of the clock, round it up.) 8531541Srgrimes */ 8541549Srgrimesint 855102074Sphkitimerfix(struct timeval *tv) 8561541Srgrimes{ 8571541Srgrimes 858151576Sdavidxu if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) 8591541Srgrimes return (EINVAL); 860247903Smav if (tv->tv_sec == 0 && tv->tv_usec != 0 && 861247903Smav tv->tv_usec < (u_int)tick / 16) 862247903Smav tv->tv_usec = (u_int)tick / 16; 8631541Srgrimes return (0); 8641541Srgrimes} 8651541Srgrimes 8661541Srgrimes/* 8671541Srgrimes * Decrement an interval timer by a specified number 8681541Srgrimes * of microseconds, which must be less than a second, 8691541Srgrimes * i.e. < 1000000. If the timer expires, then reload 8701541Srgrimes * it. In this case, carry over (usec - old value) to 8711541Srgrimes * reduce the value reloaded into the timer so that 8721541Srgrimes * the timer does not drift. This routine assumes 8731541Srgrimes * that it is called in a context where the timers 8741541Srgrimes * on which it is operating cannot change in value. 8751541Srgrimes */ 8761549Srgrimesint 877102074Sphkitimerdecr(struct itimerval *itp, int usec) 8781541Srgrimes{ 8791541Srgrimes 8801541Srgrimes if (itp->it_value.tv_usec < usec) { 8811541Srgrimes if (itp->it_value.tv_sec == 0) { 8821541Srgrimes /* expired, and already in next interval */ 8831541Srgrimes usec -= itp->it_value.tv_usec; 8841541Srgrimes goto expire; 8851541Srgrimes } 8861541Srgrimes itp->it_value.tv_usec += 1000000; 8871541Srgrimes itp->it_value.tv_sec--; 8881541Srgrimes } 8891541Srgrimes itp->it_value.tv_usec -= usec; 8901541Srgrimes usec = 0; 89135058Sphk if (timevalisset(&itp->it_value)) 8921541Srgrimes return (1); 8931541Srgrimes /* expired, exactly at end of interval */ 8941541Srgrimesexpire: 89535058Sphk if (timevalisset(&itp->it_interval)) { 8961541Srgrimes itp->it_value = itp->it_interval; 8971541Srgrimes itp->it_value.tv_usec -= usec; 8981541Srgrimes if (itp->it_value.tv_usec < 0) { 8991541Srgrimes itp->it_value.tv_usec += 1000000; 9001541Srgrimes itp->it_value.tv_sec--; 9011541Srgrimes } 9021541Srgrimes } else 9031541Srgrimes itp->it_value.tv_usec = 0; /* sec is already 0 */ 9041541Srgrimes return (0); 9051541Srgrimes} 9061541Srgrimes 9071541Srgrimes/* 9081541Srgrimes * Add and subtract routines for timevals. 9091541Srgrimes * N.B.: subtract routine doesn't deal with 9101541Srgrimes * results which are before the beginning, 9111541Srgrimes * it just gets very confused in this case. 9121541Srgrimes * Caveat emptor. 9131541Srgrimes */ 9141549Srgrimesvoid 915121523Salfredtimevaladd(struct timeval *t1, const struct timeval *t2) 9161541Srgrimes{ 9171541Srgrimes 9181541Srgrimes t1->tv_sec += t2->tv_sec; 9191541Srgrimes t1->tv_usec += t2->tv_usec; 9201541Srgrimes timevalfix(t1); 9211541Srgrimes} 9221541Srgrimes 9231549Srgrimesvoid 924121523Salfredtimevalsub(struct timeval *t1, const struct timeval *t2) 9251541Srgrimes{ 9261541Srgrimes 9271541Srgrimes t1->tv_sec -= t2->tv_sec; 9281541Srgrimes t1->tv_usec -= t2->tv_usec; 9291541Srgrimes timevalfix(t1); 9301541Srgrimes} 9311541Srgrimes 93212819Sphkstatic void 933102074Sphktimevalfix(struct timeval *t1) 9341541Srgrimes{ 9351541Srgrimes 9361541Srgrimes if (t1->tv_usec < 0) { 9371541Srgrimes t1->tv_sec--; 9381541Srgrimes t1->tv_usec += 1000000; 9391541Srgrimes } 9401541Srgrimes if (t1->tv_usec >= 1000000) { 9411541Srgrimes t1->tv_sec++; 9421541Srgrimes t1->tv_usec -= 1000000; 9431541Srgrimes } 9441541Srgrimes} 945108142Ssam 946108142Ssam/* 947108511Ssam * ratecheck(): simple time-based rate-limit checking. 948108142Ssam */ 949108142Ssamint 950108142Ssamratecheck(struct timeval *lasttime, const struct timeval *mininterval) 951108142Ssam{ 952108142Ssam struct timeval tv, delta; 953108142Ssam int rv = 0; 954108142Ssam 955108511Ssam getmicrouptime(&tv); /* NB: 10ms precision */ 956108511Ssam delta = tv; 957108511Ssam timevalsub(&delta, lasttime); 958108142Ssam 959108142Ssam /* 960108142Ssam * check for 0,0 is so that the message will be seen at least once, 961108142Ssam * even if interval is huge. 962108142Ssam */ 963108142Ssam if (timevalcmp(&delta, mininterval, >=) || 964108142Ssam (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 965108142Ssam *lasttime = tv; 966108142Ssam rv = 1; 967108142Ssam } 968108142Ssam 969108142Ssam return (rv); 970108142Ssam} 971108142Ssam 972108142Ssam/* 973108142Ssam * ppsratecheck(): packets (or events) per second limitation. 974108511Ssam * 975108511Ssam * Return 0 if the limit is to be enforced (e.g. the caller 976108511Ssam * should drop a packet because of the rate limitation). 977108511Ssam * 978111558Ssam * maxpps of 0 always causes zero to be returned. maxpps of -1 979111558Ssam * always causes 1 to be returned; this effectively defeats rate 980111558Ssam * limiting. 981111558Ssam * 982108511Ssam * Note that we maintain the struct timeval for compatibility 983108511Ssam * with other bsd systems. We reuse the storage and just monitor 984108511Ssam * clock ticks for minimal overhead. 985108142Ssam */ 986108142Ssamint 987108142Ssamppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 988108142Ssam{ 989108511Ssam int now; 990108142Ssam 991108142Ssam /* 992108511Ssam * Reset the last time and counter if this is the first call 993108511Ssam * or more than a second has passed since the last update of 994108511Ssam * lasttime. 995108142Ssam */ 996108511Ssam now = ticks; 997108511Ssam if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { 998108511Ssam lasttime->tv_sec = now; 999108511Ssam *curpps = 1; 1000111558Ssam return (maxpps != 0); 1001108511Ssam } else { 1002108511Ssam (*curpps)++; /* NB: ignore potential overflow */ 1003278686Sian return (maxpps < 0 || *curpps <= maxpps); 1004108511Ssam } 1005108142Ssam} 1006151576Sdavidxu 1007151576Sdavidxustatic void 1008151576Sdavidxuitimer_start(void) 1009151576Sdavidxu{ 1010151576Sdavidxu struct kclock rt_clock = { 1011151576Sdavidxu .timer_create = realtimer_create, 1012151576Sdavidxu .timer_delete = realtimer_delete, 1013151576Sdavidxu .timer_settime = realtimer_settime, 1014151576Sdavidxu .timer_gettime = realtimer_gettime, 1015164713Sdavidxu .event_hook = NULL 1016151576Sdavidxu }; 1017151576Sdavidxu 1018151576Sdavidxu itimer_zone = uma_zcreate("itimer", sizeof(struct itimer), 1019151576Sdavidxu NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0); 1020151576Sdavidxu register_posix_clock(CLOCK_REALTIME, &rt_clock); 1021151576Sdavidxu register_posix_clock(CLOCK_MONOTONIC, &rt_clock); 1022152983Sdavidxu p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L); 1023152983Sdavidxu p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX); 1024152983Sdavidxu p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX); 1025161302Snetchild EVENTHANDLER_REGISTER(process_exit, itimers_event_hook_exit, 1026153259Sdavidxu (void *)ITIMER_EV_EXIT, EVENTHANDLER_PRI_ANY); 1027161302Snetchild EVENTHANDLER_REGISTER(process_exec, itimers_event_hook_exec, 1028153259Sdavidxu (void *)ITIMER_EV_EXEC, EVENTHANDLER_PRI_ANY); 1029151576Sdavidxu} 1030151576Sdavidxu 1031151576Sdavidxuint 1032151576Sdavidxuregister_posix_clock(int clockid, struct kclock *clk) 1033151576Sdavidxu{ 1034151576Sdavidxu if ((unsigned)clockid >= MAX_CLOCKS) { 1035151576Sdavidxu printf("%s: invalid clockid\n", __func__); 1036151576Sdavidxu return (0); 1037151576Sdavidxu } 1038151576Sdavidxu posix_clocks[clockid] = *clk; 1039151576Sdavidxu return (1); 1040151576Sdavidxu} 1041151576Sdavidxu 1042151576Sdavidxustatic int 1043151576Sdavidxuitimer_init(void *mem, int size, int flags) 1044151576Sdavidxu{ 1045151576Sdavidxu struct itimer *it; 1046151576Sdavidxu 1047151576Sdavidxu it = (struct itimer *)mem; 1048151576Sdavidxu mtx_init(&it->it_mtx, "itimer lock", NULL, MTX_DEF); 1049151576Sdavidxu return (0); 1050151576Sdavidxu} 1051151576Sdavidxu 1052151576Sdavidxustatic void 1053151576Sdavidxuitimer_fini(void *mem, int size) 1054151576Sdavidxu{ 1055151576Sdavidxu struct itimer *it; 1056151576Sdavidxu 1057151576Sdavidxu it = (struct itimer *)mem; 1058151576Sdavidxu mtx_destroy(&it->it_mtx); 1059151576Sdavidxu} 1060151576Sdavidxu 1061151576Sdavidxustatic void 1062151576Sdavidxuitimer_enter(struct itimer *it) 1063151576Sdavidxu{ 1064151576Sdavidxu 1065151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1066151576Sdavidxu it->it_usecount++; 1067151576Sdavidxu} 1068151576Sdavidxu 1069151576Sdavidxustatic void 1070151576Sdavidxuitimer_leave(struct itimer *it) 1071151576Sdavidxu{ 1072151576Sdavidxu 1073151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1074151576Sdavidxu KASSERT(it->it_usecount > 0, ("invalid it_usecount")); 1075151576Sdavidxu 1076151576Sdavidxu if (--it->it_usecount == 0 && (it->it_flags & ITF_WANTED) != 0) 1077151576Sdavidxu wakeup(it); 1078151576Sdavidxu} 1079151576Sdavidxu 1080151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1081156134Sdavidxustruct ktimer_create_args { 1082151576Sdavidxu clockid_t clock_id; 1083151576Sdavidxu struct sigevent * evp; 1084156134Sdavidxu int * timerid; 1085151576Sdavidxu}; 1086151576Sdavidxu#endif 1087151576Sdavidxuint 1088225617Skmacysys_ktimer_create(struct thread *td, struct ktimer_create_args *uap) 1089151576Sdavidxu{ 1090253530Skib struct sigevent *evp, ev; 1091156134Sdavidxu int id; 1092151576Sdavidxu int error; 1093151576Sdavidxu 1094253530Skib if (uap->evp == NULL) { 1095253530Skib evp = NULL; 1096253530Skib } else { 1097151576Sdavidxu error = copyin(uap->evp, &ev, sizeof(ev)); 1098151576Sdavidxu if (error != 0) 1099151576Sdavidxu return (error); 1100253530Skib evp = &ev; 1101253530Skib } 1102253530Skib error = kern_ktimer_create(td, uap->clock_id, evp, &id, -1); 1103151576Sdavidxu if (error == 0) { 1104156134Sdavidxu error = copyout(&id, uap->timerid, sizeof(int)); 1105151576Sdavidxu if (error != 0) 1106253530Skib kern_ktimer_delete(td, id); 1107151576Sdavidxu } 1108151576Sdavidxu return (error); 1109151576Sdavidxu} 1110151576Sdavidxu 1111253530Skibint 1112253530Skibkern_ktimer_create(struct thread *td, clockid_t clock_id, struct sigevent *evp, 1113253530Skib int *timerid, int preset_id) 1114151576Sdavidxu{ 1115151576Sdavidxu struct proc *p = td->td_proc; 1116151576Sdavidxu struct itimer *it; 1117151576Sdavidxu int id; 1118151576Sdavidxu int error; 1119151576Sdavidxu 1120151576Sdavidxu if (clock_id < 0 || clock_id >= MAX_CLOCKS) 1121151576Sdavidxu return (EINVAL); 1122151576Sdavidxu 1123151576Sdavidxu if (posix_clocks[clock_id].timer_create == NULL) 1124151576Sdavidxu return (EINVAL); 1125151576Sdavidxu 1126151576Sdavidxu if (evp != NULL) { 1127151576Sdavidxu if (evp->sigev_notify != SIGEV_NONE && 1128151869Sdavidxu evp->sigev_notify != SIGEV_SIGNAL && 1129151869Sdavidxu evp->sigev_notify != SIGEV_THREAD_ID) 1130151576Sdavidxu return (EINVAL); 1131151869Sdavidxu if ((evp->sigev_notify == SIGEV_SIGNAL || 1132151869Sdavidxu evp->sigev_notify == SIGEV_THREAD_ID) && 1133151576Sdavidxu !_SIG_VALID(evp->sigev_signo)) 1134151576Sdavidxu return (EINVAL); 1135151576Sdavidxu } 1136151576Sdavidxu 1137151585Sdavidxu if (p->p_itimers == NULL) 1138151576Sdavidxu itimers_alloc(p); 1139151576Sdavidxu 1140151576Sdavidxu it = uma_zalloc(itimer_zone, M_WAITOK); 1141151576Sdavidxu it->it_flags = 0; 1142151576Sdavidxu it->it_usecount = 0; 1143151576Sdavidxu it->it_active = 0; 1144151869Sdavidxu timespecclear(&it->it_time.it_value); 1145151869Sdavidxu timespecclear(&it->it_time.it_interval); 1146151576Sdavidxu it->it_overrun = 0; 1147151576Sdavidxu it->it_overrun_last = 0; 1148151576Sdavidxu it->it_clockid = clock_id; 1149151576Sdavidxu it->it_timerid = -1; 1150151576Sdavidxu it->it_proc = p; 1151151576Sdavidxu ksiginfo_init(&it->it_ksi); 1152151576Sdavidxu it->it_ksi.ksi_flags |= KSI_INS | KSI_EXT; 1153151576Sdavidxu error = CLOCK_CALL(clock_id, timer_create, (it)); 1154151576Sdavidxu if (error != 0) 1155151576Sdavidxu goto out; 1156151576Sdavidxu 1157151576Sdavidxu PROC_LOCK(p); 1158151576Sdavidxu if (preset_id != -1) { 1159151576Sdavidxu KASSERT(preset_id >= 0 && preset_id < 3, ("invalid preset_id")); 1160151576Sdavidxu id = preset_id; 1161151585Sdavidxu if (p->p_itimers->its_timers[id] != NULL) { 1162151576Sdavidxu PROC_UNLOCK(p); 1163151576Sdavidxu error = 0; 1164151576Sdavidxu goto out; 1165151576Sdavidxu } 1166151576Sdavidxu } else { 1167151576Sdavidxu /* 1168151576Sdavidxu * Find a free timer slot, skipping those reserved 1169151576Sdavidxu * for setitimer(). 1170151576Sdavidxu */ 1171151576Sdavidxu for (id = 3; id < TIMER_MAX; id++) 1172151585Sdavidxu if (p->p_itimers->its_timers[id] == NULL) 1173151576Sdavidxu break; 1174151576Sdavidxu if (id == TIMER_MAX) { 1175151576Sdavidxu PROC_UNLOCK(p); 1176151576Sdavidxu error = EAGAIN; 1177151576Sdavidxu goto out; 1178151576Sdavidxu } 1179151576Sdavidxu } 1180151576Sdavidxu it->it_timerid = id; 1181151585Sdavidxu p->p_itimers->its_timers[id] = it; 1182151576Sdavidxu if (evp != NULL) 1183151576Sdavidxu it->it_sigev = *evp; 1184151576Sdavidxu else { 1185151576Sdavidxu it->it_sigev.sigev_notify = SIGEV_SIGNAL; 1186151576Sdavidxu switch (clock_id) { 1187151576Sdavidxu default: 1188151576Sdavidxu case CLOCK_REALTIME: 1189151576Sdavidxu it->it_sigev.sigev_signo = SIGALRM; 1190151576Sdavidxu break; 1191151576Sdavidxu case CLOCK_VIRTUAL: 1192151576Sdavidxu it->it_sigev.sigev_signo = SIGVTALRM; 1193151576Sdavidxu break; 1194151576Sdavidxu case CLOCK_PROF: 1195151576Sdavidxu it->it_sigev.sigev_signo = SIGPROF; 1196151576Sdavidxu break; 1197151576Sdavidxu } 1198152029Sdavidxu it->it_sigev.sigev_value.sival_int = id; 1199151576Sdavidxu } 1200151576Sdavidxu 1201151869Sdavidxu if (it->it_sigev.sigev_notify == SIGEV_SIGNAL || 1202151869Sdavidxu it->it_sigev.sigev_notify == SIGEV_THREAD_ID) { 1203151576Sdavidxu it->it_ksi.ksi_signo = it->it_sigev.sigev_signo; 1204151576Sdavidxu it->it_ksi.ksi_code = SI_TIMER; 1205151576Sdavidxu it->it_ksi.ksi_value = it->it_sigev.sigev_value; 1206151576Sdavidxu it->it_ksi.ksi_timerid = id; 1207151576Sdavidxu } 1208151576Sdavidxu PROC_UNLOCK(p); 1209151576Sdavidxu *timerid = id; 1210151576Sdavidxu return (0); 1211151576Sdavidxu 1212151576Sdavidxuout: 1213151576Sdavidxu ITIMER_LOCK(it); 1214151576Sdavidxu CLOCK_CALL(it->it_clockid, timer_delete, (it)); 1215151576Sdavidxu ITIMER_UNLOCK(it); 1216151576Sdavidxu uma_zfree(itimer_zone, it); 1217151576Sdavidxu return (error); 1218151576Sdavidxu} 1219151576Sdavidxu 1220151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1221156134Sdavidxustruct ktimer_delete_args { 1222156134Sdavidxu int timerid; 1223151576Sdavidxu}; 1224151576Sdavidxu#endif 1225151576Sdavidxuint 1226225617Skmacysys_ktimer_delete(struct thread *td, struct ktimer_delete_args *uap) 1227151576Sdavidxu{ 1228253530Skib 1229253530Skib return (kern_ktimer_delete(td, uap->timerid)); 1230151576Sdavidxu} 1231151576Sdavidxu 1232151576Sdavidxustatic struct itimer * 1233164713Sdavidxuitimer_find(struct proc *p, int timerid) 1234151576Sdavidxu{ 1235151576Sdavidxu struct itimer *it; 1236151576Sdavidxu 1237151576Sdavidxu PROC_LOCK_ASSERT(p, MA_OWNED); 1238190301Scperciva if ((p->p_itimers == NULL) || 1239190301Scperciva (timerid < 0) || (timerid >= TIMER_MAX) || 1240151585Sdavidxu (it = p->p_itimers->its_timers[timerid]) == NULL) { 1241151576Sdavidxu return (NULL); 1242151576Sdavidxu } 1243151576Sdavidxu ITIMER_LOCK(it); 1244164713Sdavidxu if ((it->it_flags & ITF_DELETING) != 0) { 1245151576Sdavidxu ITIMER_UNLOCK(it); 1246151576Sdavidxu it = NULL; 1247151576Sdavidxu } 1248151576Sdavidxu return (it); 1249151576Sdavidxu} 1250151576Sdavidxu 1251253530Skibint 1252253530Skibkern_ktimer_delete(struct thread *td, int timerid) 1253151576Sdavidxu{ 1254151576Sdavidxu struct proc *p = td->td_proc; 1255151576Sdavidxu struct itimer *it; 1256151576Sdavidxu 1257151576Sdavidxu PROC_LOCK(p); 1258164713Sdavidxu it = itimer_find(p, timerid); 1259151576Sdavidxu if (it == NULL) { 1260151576Sdavidxu PROC_UNLOCK(p); 1261151576Sdavidxu return (EINVAL); 1262151576Sdavidxu } 1263151576Sdavidxu PROC_UNLOCK(p); 1264151576Sdavidxu 1265151576Sdavidxu it->it_flags |= ITF_DELETING; 1266151576Sdavidxu while (it->it_usecount > 0) { 1267151576Sdavidxu it->it_flags |= ITF_WANTED; 1268151576Sdavidxu msleep(it, &it->it_mtx, PPAUSE, "itimer", 0); 1269151576Sdavidxu } 1270151576Sdavidxu it->it_flags &= ~ITF_WANTED; 1271151576Sdavidxu CLOCK_CALL(it->it_clockid, timer_delete, (it)); 1272151576Sdavidxu ITIMER_UNLOCK(it); 1273151576Sdavidxu 1274151576Sdavidxu PROC_LOCK(p); 1275151576Sdavidxu if (KSI_ONQ(&it->it_ksi)) 1276151576Sdavidxu sigqueue_take(&it->it_ksi); 1277151585Sdavidxu p->p_itimers->its_timers[timerid] = NULL; 1278151576Sdavidxu PROC_UNLOCK(p); 1279151576Sdavidxu uma_zfree(itimer_zone, it); 1280151576Sdavidxu return (0); 1281151576Sdavidxu} 1282151576Sdavidxu 1283151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1284156134Sdavidxustruct ktimer_settime_args { 1285156134Sdavidxu int timerid; 1286151576Sdavidxu int flags; 1287151576Sdavidxu const struct itimerspec * value; 1288151576Sdavidxu struct itimerspec * ovalue; 1289151576Sdavidxu}; 1290151576Sdavidxu#endif 1291151576Sdavidxuint 1292225617Skmacysys_ktimer_settime(struct thread *td, struct ktimer_settime_args *uap) 1293151576Sdavidxu{ 1294151576Sdavidxu struct itimerspec val, oval, *ovalp; 1295151576Sdavidxu int error; 1296151576Sdavidxu 1297151576Sdavidxu error = copyin(uap->value, &val, sizeof(val)); 1298151576Sdavidxu if (error != 0) 1299151576Sdavidxu return (error); 1300253530Skib ovalp = uap->ovalue != NULL ? &oval : NULL; 1301253530Skib error = kern_ktimer_settime(td, uap->timerid, uap->flags, &val, ovalp); 1302253530Skib if (error == 0 && uap->ovalue != NULL) 1303253530Skib error = copyout(ovalp, uap->ovalue, sizeof(*ovalp)); 1304253530Skib return (error); 1305253530Skib} 1306151576Sdavidxu 1307253530Skibint 1308253530Skibkern_ktimer_settime(struct thread *td, int timer_id, int flags, 1309253530Skib struct itimerspec *val, struct itimerspec *oval) 1310253530Skib{ 1311253530Skib struct proc *p; 1312253530Skib struct itimer *it; 1313253530Skib int error; 1314253530Skib 1315253530Skib p = td->td_proc; 1316151576Sdavidxu PROC_LOCK(p); 1317253530Skib if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) { 1318151576Sdavidxu PROC_UNLOCK(p); 1319151576Sdavidxu error = EINVAL; 1320151576Sdavidxu } else { 1321151576Sdavidxu PROC_UNLOCK(p); 1322151576Sdavidxu itimer_enter(it); 1323253530Skib error = CLOCK_CALL(it->it_clockid, timer_settime, (it, 1324253530Skib flags, val, oval)); 1325151576Sdavidxu itimer_leave(it); 1326151576Sdavidxu ITIMER_UNLOCK(it); 1327151576Sdavidxu } 1328151576Sdavidxu return (error); 1329151576Sdavidxu} 1330151576Sdavidxu 1331151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1332156134Sdavidxustruct ktimer_gettime_args { 1333156134Sdavidxu int timerid; 1334151576Sdavidxu struct itimerspec * value; 1335151576Sdavidxu}; 1336151576Sdavidxu#endif 1337151576Sdavidxuint 1338225617Skmacysys_ktimer_gettime(struct thread *td, struct ktimer_gettime_args *uap) 1339151576Sdavidxu{ 1340151576Sdavidxu struct itimerspec val; 1341151576Sdavidxu int error; 1342151576Sdavidxu 1343253530Skib error = kern_ktimer_gettime(td, uap->timerid, &val); 1344253530Skib if (error == 0) 1345253530Skib error = copyout(&val, uap->value, sizeof(val)); 1346253530Skib return (error); 1347253530Skib} 1348253530Skib 1349253530Skibint 1350253530Skibkern_ktimer_gettime(struct thread *td, int timer_id, struct itimerspec *val) 1351253530Skib{ 1352253530Skib struct proc *p; 1353253530Skib struct itimer *it; 1354253530Skib int error; 1355253530Skib 1356253530Skib p = td->td_proc; 1357151576Sdavidxu PROC_LOCK(p); 1358253530Skib if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) { 1359151576Sdavidxu PROC_UNLOCK(p); 1360151576Sdavidxu error = EINVAL; 1361151576Sdavidxu } else { 1362151576Sdavidxu PROC_UNLOCK(p); 1363151576Sdavidxu itimer_enter(it); 1364253530Skib error = CLOCK_CALL(it->it_clockid, timer_gettime, (it, val)); 1365151576Sdavidxu itimer_leave(it); 1366151576Sdavidxu ITIMER_UNLOCK(it); 1367151576Sdavidxu } 1368151576Sdavidxu return (error); 1369151576Sdavidxu} 1370151576Sdavidxu 1371151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1372151576Sdavidxustruct timer_getoverrun_args { 1373156134Sdavidxu int timerid; 1374151576Sdavidxu}; 1375151576Sdavidxu#endif 1376151576Sdavidxuint 1377225617Skmacysys_ktimer_getoverrun(struct thread *td, struct ktimer_getoverrun_args *uap) 1378151576Sdavidxu{ 1379270042Sbz 1380270042Sbz return (kern_ktimer_getoverrun(td, uap->timerid)); 1381270042Sbz} 1382270042Sbz 1383270042Sbzint 1384270042Sbzkern_ktimer_getoverrun(struct thread *td, int timer_id) 1385270042Sbz{ 1386151576Sdavidxu struct proc *p = td->td_proc; 1387151576Sdavidxu struct itimer *it; 1388151576Sdavidxu int error ; 1389151576Sdavidxu 1390151576Sdavidxu PROC_LOCK(p); 1391270042Sbz if (timer_id < 3 || 1392270042Sbz (it = itimer_find(p, timer_id)) == NULL) { 1393151576Sdavidxu PROC_UNLOCK(p); 1394151576Sdavidxu error = EINVAL; 1395151576Sdavidxu } else { 1396151576Sdavidxu td->td_retval[0] = it->it_overrun_last; 1397151576Sdavidxu ITIMER_UNLOCK(it); 1398151869Sdavidxu PROC_UNLOCK(p); 1399151576Sdavidxu error = 0; 1400151576Sdavidxu } 1401151576Sdavidxu return (error); 1402151576Sdavidxu} 1403151576Sdavidxu 1404151576Sdavidxustatic int 1405151576Sdavidxurealtimer_create(struct itimer *it) 1406151576Sdavidxu{ 1407151576Sdavidxu callout_init_mtx(&it->it_callout, &it->it_mtx, 0); 1408151576Sdavidxu return (0); 1409151576Sdavidxu} 1410151576Sdavidxu 1411151576Sdavidxustatic int 1412151576Sdavidxurealtimer_delete(struct itimer *it) 1413151576Sdavidxu{ 1414151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1415164713Sdavidxu 1416184067Sdavidxu /* 1417184067Sdavidxu * clear timer's value and interval to tell realtimer_expire 1418184067Sdavidxu * to not rearm the timer. 1419184067Sdavidxu */ 1420184067Sdavidxu timespecclear(&it->it_time.it_value); 1421184067Sdavidxu timespecclear(&it->it_time.it_interval); 1422164713Sdavidxu ITIMER_UNLOCK(it); 1423164713Sdavidxu callout_drain(&it->it_callout); 1424164713Sdavidxu ITIMER_LOCK(it); 1425151576Sdavidxu return (0); 1426151576Sdavidxu} 1427151576Sdavidxu 1428151576Sdavidxustatic int 1429151576Sdavidxurealtimer_gettime(struct itimer *it, struct itimerspec *ovalue) 1430151576Sdavidxu{ 1431151869Sdavidxu struct timespec cts; 1432151576Sdavidxu 1433151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1434151576Sdavidxu 1435151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1436151869Sdavidxu *ovalue = it->it_time; 1437151576Sdavidxu if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) { 1438151869Sdavidxu timespecsub(&ovalue->it_value, &cts); 1439151576Sdavidxu if (ovalue->it_value.tv_sec < 0 || 1440151576Sdavidxu (ovalue->it_value.tv_sec == 0 && 1441151576Sdavidxu ovalue->it_value.tv_nsec == 0)) { 1442151576Sdavidxu ovalue->it_value.tv_sec = 0; 1443151576Sdavidxu ovalue->it_value.tv_nsec = 1; 1444151576Sdavidxu } 1445151576Sdavidxu } 1446151576Sdavidxu return (0); 1447151576Sdavidxu} 1448151576Sdavidxu 1449151576Sdavidxustatic int 1450151576Sdavidxurealtimer_settime(struct itimer *it, int flags, 1451151576Sdavidxu struct itimerspec *value, struct itimerspec *ovalue) 1452151576Sdavidxu{ 1453151869Sdavidxu struct timespec cts, ts; 1454151869Sdavidxu struct timeval tv; 1455151869Sdavidxu struct itimerspec val; 1456151576Sdavidxu 1457151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1458151576Sdavidxu 1459151869Sdavidxu val = *value; 1460151869Sdavidxu if (itimespecfix(&val.it_value)) 1461151576Sdavidxu return (EINVAL); 1462151576Sdavidxu 1463151869Sdavidxu if (timespecisset(&val.it_value)) { 1464151869Sdavidxu if (itimespecfix(&val.it_interval)) 1465151576Sdavidxu return (EINVAL); 1466151576Sdavidxu } else { 1467151869Sdavidxu timespecclear(&val.it_interval); 1468151576Sdavidxu } 1469151576Sdavidxu 1470151576Sdavidxu if (ovalue != NULL) 1471151576Sdavidxu realtimer_gettime(it, ovalue); 1472151576Sdavidxu 1473151576Sdavidxu it->it_time = val; 1474151869Sdavidxu if (timespecisset(&val.it_value)) { 1475151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1476151869Sdavidxu ts = val.it_value; 1477151576Sdavidxu if ((flags & TIMER_ABSTIME) == 0) { 1478151576Sdavidxu /* Convert to absolute time. */ 1479151869Sdavidxu timespecadd(&it->it_time.it_value, &cts); 1480151576Sdavidxu } else { 1481151869Sdavidxu timespecsub(&ts, &cts); 1482151576Sdavidxu /* 1483151869Sdavidxu * We don't care if ts is negative, tztohz will 1484151576Sdavidxu * fix it. 1485151576Sdavidxu */ 1486151576Sdavidxu } 1487151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1488151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), 1489151576Sdavidxu realtimer_expire, it); 1490151576Sdavidxu } else { 1491151576Sdavidxu callout_stop(&it->it_callout); 1492151576Sdavidxu } 1493151576Sdavidxu 1494151576Sdavidxu return (0); 1495151576Sdavidxu} 1496151576Sdavidxu 1497151576Sdavidxustatic void 1498151869Sdavidxurealtimer_clocktime(clockid_t id, struct timespec *ts) 1499151576Sdavidxu{ 1500151576Sdavidxu if (id == CLOCK_REALTIME) 1501151869Sdavidxu getnanotime(ts); 1502151576Sdavidxu else /* CLOCK_MONOTONIC */ 1503151869Sdavidxu getnanouptime(ts); 1504151576Sdavidxu} 1505151576Sdavidxu 1506151869Sdavidxuint 1507156134Sdavidxuitimer_accept(struct proc *p, int timerid, ksiginfo_t *ksi) 1508151869Sdavidxu{ 1509151869Sdavidxu struct itimer *it; 1510151869Sdavidxu 1511151869Sdavidxu PROC_LOCK_ASSERT(p, MA_OWNED); 1512164713Sdavidxu it = itimer_find(p, timerid); 1513151869Sdavidxu if (it != NULL) { 1514151869Sdavidxu ksi->ksi_overrun = it->it_overrun; 1515151869Sdavidxu it->it_overrun_last = it->it_overrun; 1516151869Sdavidxu it->it_overrun = 0; 1517151869Sdavidxu ITIMER_UNLOCK(it); 1518151869Sdavidxu return (0); 1519151869Sdavidxu } 1520151869Sdavidxu return (EINVAL); 1521151869Sdavidxu} 1522151869Sdavidxu 1523151869Sdavidxuint 1524151869Sdavidxuitimespecfix(struct timespec *ts) 1525151869Sdavidxu{ 1526151869Sdavidxu 1527151869Sdavidxu if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) 1528151869Sdavidxu return (EINVAL); 1529151869Sdavidxu if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000) 1530151869Sdavidxu ts->tv_nsec = tick * 1000; 1531151869Sdavidxu return (0); 1532151869Sdavidxu} 1533151869Sdavidxu 1534151576Sdavidxu/* Timeout callback for realtime timer */ 1535151576Sdavidxustatic void 1536151576Sdavidxurealtimer_expire(void *arg) 1537151576Sdavidxu{ 1538151869Sdavidxu struct timespec cts, ts; 1539151869Sdavidxu struct timeval tv; 1540151576Sdavidxu struct itimer *it; 1541151576Sdavidxu 1542151576Sdavidxu it = (struct itimer *)arg; 1543151576Sdavidxu 1544151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1545151576Sdavidxu /* Only fire if time is reached. */ 1546151869Sdavidxu if (timespeccmp(&cts, &it->it_time.it_value, >=)) { 1547151869Sdavidxu if (timespecisset(&it->it_time.it_interval)) { 1548151869Sdavidxu timespecadd(&it->it_time.it_value, 1549151869Sdavidxu &it->it_time.it_interval); 1550151869Sdavidxu while (timespeccmp(&cts, &it->it_time.it_value, >=)) { 1551152983Sdavidxu if (it->it_overrun < INT_MAX) 1552152983Sdavidxu it->it_overrun++; 1553152983Sdavidxu else 1554152983Sdavidxu it->it_ksi.ksi_errno = ERANGE; 1555151869Sdavidxu timespecadd(&it->it_time.it_value, 1556151869Sdavidxu &it->it_time.it_interval); 1557151576Sdavidxu } 1558151576Sdavidxu } else { 1559151576Sdavidxu /* single shot timer ? */ 1560151869Sdavidxu timespecclear(&it->it_time.it_value); 1561151576Sdavidxu } 1562151869Sdavidxu if (timespecisset(&it->it_time.it_value)) { 1563151869Sdavidxu ts = it->it_time.it_value; 1564151869Sdavidxu timespecsub(&ts, &cts); 1565151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1566151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), 1567151576Sdavidxu realtimer_expire, it); 1568151576Sdavidxu } 1569184067Sdavidxu itimer_enter(it); 1570151576Sdavidxu ITIMER_UNLOCK(it); 1571151576Sdavidxu itimer_fire(it); 1572151576Sdavidxu ITIMER_LOCK(it); 1573184067Sdavidxu itimer_leave(it); 1574151869Sdavidxu } else if (timespecisset(&it->it_time.it_value)) { 1575151869Sdavidxu ts = it->it_time.it_value; 1576151869Sdavidxu timespecsub(&ts, &cts); 1577151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1578151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire, 1579151576Sdavidxu it); 1580151576Sdavidxu } 1581151576Sdavidxu} 1582151576Sdavidxu 1583151576Sdavidxuvoid 1584151576Sdavidxuitimer_fire(struct itimer *it) 1585151576Sdavidxu{ 1586151576Sdavidxu struct proc *p = it->it_proc; 1587213642Sdavidxu struct thread *td; 1588151576Sdavidxu 1589151869Sdavidxu if (it->it_sigev.sigev_notify == SIGEV_SIGNAL || 1590151869Sdavidxu it->it_sigev.sigev_notify == SIGEV_THREAD_ID) { 1591213642Sdavidxu if (sigev_findtd(p, &it->it_sigev, &td) != 0) { 1592213642Sdavidxu ITIMER_LOCK(it); 1593213642Sdavidxu timespecclear(&it->it_time.it_value); 1594213642Sdavidxu timespecclear(&it->it_time.it_interval); 1595213642Sdavidxu callout_stop(&it->it_callout); 1596213642Sdavidxu ITIMER_UNLOCK(it); 1597213642Sdavidxu return; 1598213642Sdavidxu } 1599151993Sdavidxu if (!KSI_ONQ(&it->it_ksi)) { 1600152983Sdavidxu it->it_ksi.ksi_errno = 0; 1601213642Sdavidxu ksiginfo_set_sigev(&it->it_ksi, &it->it_sigev); 1602213642Sdavidxu tdsendsignal(p, td, it->it_ksi.ksi_signo, &it->it_ksi); 1603151993Sdavidxu } else { 1604152983Sdavidxu if (it->it_overrun < INT_MAX) 1605152983Sdavidxu it->it_overrun++; 1606152983Sdavidxu else 1607152983Sdavidxu it->it_ksi.ksi_errno = ERANGE; 1608151576Sdavidxu } 1609151576Sdavidxu PROC_UNLOCK(p); 1610151576Sdavidxu } 1611151576Sdavidxu} 1612151576Sdavidxu 1613151576Sdavidxustatic void 1614151576Sdavidxuitimers_alloc(struct proc *p) 1615151576Sdavidxu{ 1616151585Sdavidxu struct itimers *its; 1617151585Sdavidxu int i; 1618151576Sdavidxu 1619151585Sdavidxu its = malloc(sizeof (struct itimers), M_SUBPROC, M_WAITOK | M_ZERO); 1620151585Sdavidxu LIST_INIT(&its->its_virtual); 1621151585Sdavidxu LIST_INIT(&its->its_prof); 1622151585Sdavidxu TAILQ_INIT(&its->its_worklist); 1623151585Sdavidxu for (i = 0; i < TIMER_MAX; i++) 1624151585Sdavidxu its->its_timers[i] = NULL; 1625151576Sdavidxu PROC_LOCK(p); 1626151585Sdavidxu if (p->p_itimers == NULL) { 1627151585Sdavidxu p->p_itimers = its; 1628151576Sdavidxu PROC_UNLOCK(p); 1629151585Sdavidxu } 1630151585Sdavidxu else { 1631151576Sdavidxu PROC_UNLOCK(p); 1632151585Sdavidxu free(its, M_SUBPROC); 1633151576Sdavidxu } 1634151576Sdavidxu} 1635151576Sdavidxu 1636161302Snetchildstatic void 1637161302Snetchilditimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp __unused) 1638161302Snetchild{ 1639164713Sdavidxu itimers_event_hook_exit(arg, p); 1640161302Snetchild} 1641161302Snetchild 1642151576Sdavidxu/* Clean up timers when some process events are being triggered. */ 1643153259Sdavidxustatic void 1644161302Snetchilditimers_event_hook_exit(void *arg, struct proc *p) 1645151576Sdavidxu{ 1646151576Sdavidxu struct itimers *its; 1647151576Sdavidxu struct itimer *it; 1648153267Sdavidxu int event = (int)(intptr_t)arg; 1649151576Sdavidxu int i; 1650151576Sdavidxu 1651151585Sdavidxu if (p->p_itimers != NULL) { 1652151585Sdavidxu its = p->p_itimers; 1653151576Sdavidxu for (i = 0; i < MAX_CLOCKS; ++i) { 1654151576Sdavidxu if (posix_clocks[i].event_hook != NULL) 1655151576Sdavidxu CLOCK_CALL(i, event_hook, (p, i, event)); 1656151576Sdavidxu } 1657151576Sdavidxu /* 1658151576Sdavidxu * According to susv3, XSI interval timers should be inherited 1659151576Sdavidxu * by new image. 1660151576Sdavidxu */ 1661151576Sdavidxu if (event == ITIMER_EV_EXEC) 1662151576Sdavidxu i = 3; 1663151576Sdavidxu else if (event == ITIMER_EV_EXIT) 1664151576Sdavidxu i = 0; 1665151576Sdavidxu else 1666151576Sdavidxu panic("unhandled event"); 1667151576Sdavidxu for (; i < TIMER_MAX; ++i) { 1668164713Sdavidxu if ((it = its->its_timers[i]) != NULL) 1669253530Skib kern_ktimer_delete(curthread, i); 1670151576Sdavidxu } 1671151576Sdavidxu if (its->its_timers[0] == NULL && 1672151576Sdavidxu its->its_timers[1] == NULL && 1673151576Sdavidxu its->its_timers[2] == NULL) { 1674151585Sdavidxu free(its, M_SUBPROC); 1675151585Sdavidxu p->p_itimers = NULL; 1676151576Sdavidxu } 1677151576Sdavidxu } 1678151576Sdavidxu} 1679