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$"); 34116182Sobrien 351541Srgrimes#include <sys/param.h> 3648274Speter#include <sys/systm.h> 37160910Sdavidxu#include <sys/limits.h> 38162954Sphk#include <sys/clock.h> 3976166Smarkm#include <sys/lock.h> 4076166Smarkm#include <sys/mutex.h> 4112221Sbde#include <sys/sysproto.h> 42153259Sdavidxu#include <sys/eventhandler.h> 431541Srgrimes#include <sys/resourcevar.h> 443308Sphk#include <sys/signalvar.h> 451541Srgrimes#include <sys/kernel.h> 46247797Sdavide#include <sys/sleepqueue.h> 47140483Sps#include <sys/syscallsubr.h> 48152983Sdavidxu#include <sys/sysctl.h> 4925583Speter#include <sys/sysent.h> 50164033Srwatson#include <sys/priv.h> 511541Srgrimes#include <sys/proc.h> 52164184Strhodes#include <sys/posix4.h> 5325656Speter#include <sys/time.h> 54151576Sdavidxu#include <sys/timers.h> 5558377Sphk#include <sys/timetc.h> 561541Srgrimes#include <sys/vnode.h> 5776166Smarkm 5826335Speter#include <vm/vm.h> 5926335Speter#include <vm/vm_extern.h> 601541Srgrimes 61151576Sdavidxu#define MAX_CLOCKS (CLOCK_MONOTONIC+1) 62239347Sdavidxu#define CPUCLOCK_BIT 0x80000000 63239347Sdavidxu#define CPUCLOCK_PROCESS_BIT 0x40000000 64239347Sdavidxu#define CPUCLOCK_ID_MASK (~(CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT)) 65239347Sdavidxu#define MAKE_THREAD_CPUCLOCK(tid) (CPUCLOCK_BIT|(tid)) 66239347Sdavidxu#define MAKE_PROCESS_CPUCLOCK(pid) \ 67239347Sdavidxu (CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT|(pid)) 68151576Sdavidxu 69151576Sdavidxustatic struct kclock posix_clocks[MAX_CLOCKS]; 70151576Sdavidxustatic uma_zone_t itimer_zone = NULL; 71151576Sdavidxu 728876Srgrimes/* 731541Srgrimes * Time of day and interval timer support. 741541Srgrimes * 751541Srgrimes * These routines provide the kernel entry points to get and set 761541Srgrimes * the time-of-day and per-process interval timers. Subroutines 771541Srgrimes * here provide support for adding and subtracting timeval structures 781541Srgrimes * and decrementing interval timers, optionally reloading the interval 791541Srgrimes * timers when they expire. 801541Srgrimes */ 811541Srgrimes 8294343Sjhbstatic int settime(struct thread *, struct timeval *); 8392723Salfredstatic void timevalfix(struct timeval *); 8413016Sbde 85151576Sdavidxustatic void itimer_start(void); 86151576Sdavidxustatic int itimer_init(void *, int, int); 87151576Sdavidxustatic void itimer_fini(void *, int); 88151576Sdavidxustatic void itimer_enter(struct itimer *); 89151576Sdavidxustatic void itimer_leave(struct itimer *); 90164713Sdavidxustatic struct itimer *itimer_find(struct proc *, int); 91151576Sdavidxustatic void itimers_alloc(struct proc *); 92161302Snetchildstatic void itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp); 93161302Snetchildstatic void itimers_event_hook_exit(void *arg, struct proc *p); 94151576Sdavidxustatic int realtimer_create(struct itimer *); 95151576Sdavidxustatic int realtimer_gettime(struct itimer *, struct itimerspec *); 96151576Sdavidxustatic int realtimer_settime(struct itimer *, int, 97151576Sdavidxu struct itimerspec *, struct itimerspec *); 98151576Sdavidxustatic int realtimer_delete(struct itimer *); 99151869Sdavidxustatic void realtimer_clocktime(clockid_t, struct timespec *); 100151576Sdavidxustatic void realtimer_expire(void *); 101151576Sdavidxu 102151576Sdavidxuint register_posix_clock(int, struct kclock *); 103151576Sdavidxuvoid itimer_fire(struct itimer *it); 104151869Sdavidxuint itimespecfix(struct timespec *ts); 105151576Sdavidxu 106151576Sdavidxu#define CLOCK_CALL(clock, call, arglist) \ 107151576Sdavidxu ((*posix_clocks[clock].call) arglist) 108151576Sdavidxu 109151576SdavidxuSYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL); 110151576Sdavidxu 111151576Sdavidxu 11225583Speterstatic int 113102074Sphksettime(struct thread *td, struct timeval *tv) 11425583Speter{ 11545433Snsayer struct timeval delta, tv1, tv2; 11645438Snsayer static struct timeval maxtime, laststep; 11733690Sphk struct timespec ts; 11825583Speter int s; 11925583Speter 12025656Speter s = splclock(); 12133818Sbde microtime(&tv1); 12235029Sphk delta = *tv; 12335029Sphk timevalsub(&delta, &tv1); 12425583Speter 12525583Speter /* 12633818Sbde * If the system is secure, we do not allow the time to be 12745433Snsayer * set to a value earlier than 1 second less than the highest 12845433Snsayer * time we have yet seen. The worst a miscreant can do in 12945433Snsayer * this circumstance is "freeze" time. He couldn't go 13045433Snsayer * back to the past. 13145438Snsayer * 13245438Snsayer * We similarly do not allow the clock to be stepped more 13345438Snsayer * than one second, nor more than once per second. This allows 13445438Snsayer * a miscreant to make the clock march double-time, but no worse. 13525583Speter */ 13694343Sjhb if (securelevel_gt(td->td_ucred, 1) != 0) { 13745433Snsayer if (delta.tv_sec < 0 || delta.tv_usec < 0) { 13845437Smjacob /* 13945438Snsayer * Update maxtime to latest time we've seen. 14045437Smjacob */ 14145437Smjacob if (tv1.tv_sec > maxtime.tv_sec) 14245437Smjacob maxtime = tv1; 14345437Smjacob tv2 = *tv; 14445437Smjacob timevalsub(&tv2, &maxtime); 14545437Smjacob if (tv2.tv_sec < -1) { 14645437Smjacob tv->tv_sec = maxtime.tv_sec - 1; 14745433Snsayer printf("Time adjustment clamped to -1 second\n"); 14845433Snsayer } 14945437Smjacob } else { 15045438Snsayer if (tv1.tv_sec == laststep.tv_sec) { 15145438Snsayer splx(s); 15245438Snsayer return (EPERM); 15345438Snsayer } 15445438Snsayer if (delta.tv_sec > 1) { 15545438Snsayer tv->tv_sec = tv1.tv_sec + 1; 15645438Snsayer printf("Time adjustment clamped to +1 second\n"); 15745438Snsayer } 15845438Snsayer laststep = *tv; 15945433Snsayer } 16033818Sbde } 16133818Sbde 16233690Sphk ts.tv_sec = tv->tv_sec; 16333690Sphk ts.tv_nsec = tv->tv_usec * 1000; 16494343Sjhb mtx_lock(&Giant); 16558377Sphk tc_setclock(&ts); 16625583Speter resettodr(); 16794343Sjhb mtx_unlock(&Giant); 16825583Speter return (0); 16925583Speter} 17025583Speter 17112221Sbde#ifndef _SYS_SYSPROTO_H_ 172239347Sdavidxustruct clock_getcpuclockid2_args { 173239347Sdavidxu id_t id; 174239347Sdavidxu int which, 175239347Sdavidxu clockid_t *clock_id; 176239347Sdavidxu}; 177239347Sdavidxu#endif 178239347Sdavidxu/* ARGSUSED */ 179239347Sdavidxuint 180239347Sdavidxusys_clock_getcpuclockid2(struct thread *td, struct clock_getcpuclockid2_args *uap) 181239347Sdavidxu{ 182239347Sdavidxu clockid_t clk_id; 183253494Skib int error; 184253494Skib 185253494Skib error = kern_clock_getcpuclockid2(td, uap->id, uap->which, &clk_id); 186253494Skib if (error == 0) 187253494Skib error = copyout(&clk_id, uap->clock_id, sizeof(clockid_t)); 188253494Skib return (error); 189253494Skib} 190253494Skib 191253494Skibint 192253494Skibkern_clock_getcpuclockid2(struct thread *td, id_t id, int which, 193253494Skib clockid_t *clk_id) 194253494Skib{ 195239347Sdavidxu struct proc *p; 196239347Sdavidxu pid_t pid; 197239347Sdavidxu lwpid_t tid; 198239347Sdavidxu int error; 199239347Sdavidxu 200253494Skib switch (which) { 201239347Sdavidxu case CPUCLOCK_WHICH_PID: 202253494Skib if (id != 0) { 203253494Skib p = pfind(id); 204239347Sdavidxu if (p == NULL) 205239347Sdavidxu return (ESRCH); 206239347Sdavidxu error = p_cansee(td, p); 207239347Sdavidxu PROC_UNLOCK(p); 208253494Skib if (error != 0) 209239347Sdavidxu return (error); 210253494Skib pid = id; 211239347Sdavidxu } else { 212239347Sdavidxu pid = td->td_proc->p_pid; 213239347Sdavidxu } 214253494Skib *clk_id = MAKE_PROCESS_CPUCLOCK(pid); 215253494Skib return (0); 216239347Sdavidxu case CPUCLOCK_WHICH_TID: 217253494Skib tid = id == 0 ? td->td_tid : id; 218253494Skib *clk_id = MAKE_THREAD_CPUCLOCK(tid); 219253494Skib return (0); 220239347Sdavidxu default: 221239347Sdavidxu return (EINVAL); 222239347Sdavidxu } 223239347Sdavidxu} 224239347Sdavidxu 225239347Sdavidxu#ifndef _SYS_SYSPROTO_H_ 22625583Speterstruct clock_gettime_args { 22725583Speter clockid_t clock_id; 22825583Speter struct timespec *tp; 22925583Speter}; 23025583Speter#endif 23125583Speter/* ARGSUSED */ 23225583Speterint 233225617Skmacysys_clock_gettime(struct thread *td, struct clock_gettime_args *uap) 23425583Speter{ 23525583Speter struct timespec ats; 236151357Sps int error; 237151357Sps 238151357Sps error = kern_clock_gettime(td, uap->clock_id, &ats); 239151357Sps if (error == 0) 240151357Sps error = copyout(&ats, uap->tp, sizeof(ats)); 241151357Sps 242151357Sps return (error); 243151357Sps} 244151357Sps 245239347Sdavidxustatic inline void 246239347Sdavidxucputick2timespec(uint64_t runtime, struct timespec *ats) 247239347Sdavidxu{ 248239347Sdavidxu runtime = cputick2usec(runtime); 249239347Sdavidxu ats->tv_sec = runtime / 1000000; 250239347Sdavidxu ats->tv_nsec = runtime % 1000000 * 1000; 251239347Sdavidxu} 252239347Sdavidxu 253239347Sdavidxustatic void 254239347Sdavidxuget_thread_cputime(struct thread *targettd, struct timespec *ats) 255239347Sdavidxu{ 256239347Sdavidxu uint64_t runtime, curtime, switchtime; 257239347Sdavidxu 258239347Sdavidxu if (targettd == NULL) { /* current thread */ 259239347Sdavidxu critical_enter(); 260239347Sdavidxu switchtime = PCPU_GET(switchtime); 261239347Sdavidxu curtime = cpu_ticks(); 262239347Sdavidxu runtime = curthread->td_runtime; 263239347Sdavidxu critical_exit(); 264239347Sdavidxu runtime += curtime - switchtime; 265239347Sdavidxu } else { 266239347Sdavidxu thread_lock(targettd); 267239347Sdavidxu runtime = targettd->td_runtime; 268239347Sdavidxu thread_unlock(targettd); 269239347Sdavidxu } 270239347Sdavidxu cputick2timespec(runtime, ats); 271239347Sdavidxu} 272239347Sdavidxu 273239347Sdavidxustatic void 274239347Sdavidxuget_process_cputime(struct proc *targetp, struct timespec *ats) 275239347Sdavidxu{ 276239347Sdavidxu uint64_t runtime; 277239347Sdavidxu struct rusage ru; 278239347Sdavidxu 279239347Sdavidxu PROC_SLOCK(targetp); 280239347Sdavidxu rufetch(targetp, &ru); 281239347Sdavidxu runtime = targetp->p_rux.rux_runtime; 282239347Sdavidxu PROC_SUNLOCK(targetp); 283239347Sdavidxu cputick2timespec(runtime, ats); 284239347Sdavidxu} 285239347Sdavidxu 286239347Sdavidxustatic int 287239347Sdavidxuget_cputime(struct thread *td, clockid_t clock_id, struct timespec *ats) 288239347Sdavidxu{ 289239347Sdavidxu struct proc *p, *p2; 290239347Sdavidxu struct thread *td2; 291239347Sdavidxu lwpid_t tid; 292239347Sdavidxu pid_t pid; 293239347Sdavidxu int error; 294239347Sdavidxu 295239347Sdavidxu p = td->td_proc; 296239347Sdavidxu if ((clock_id & CPUCLOCK_PROCESS_BIT) == 0) { 297239347Sdavidxu tid = clock_id & CPUCLOCK_ID_MASK; 298239347Sdavidxu td2 = tdfind(tid, p->p_pid); 299239347Sdavidxu if (td2 == NULL) 300239347Sdavidxu return (EINVAL); 301239347Sdavidxu get_thread_cputime(td2, ats); 302239347Sdavidxu PROC_UNLOCK(td2->td_proc); 303239347Sdavidxu } else { 304239347Sdavidxu pid = clock_id & CPUCLOCK_ID_MASK; 305253325Skib error = pget(pid, PGET_CANSEE, &p2); 306253325Skib if (error != 0) 307239347Sdavidxu return (EINVAL); 308239347Sdavidxu get_process_cputime(p2, ats); 309239347Sdavidxu PROC_UNLOCK(p2); 310239347Sdavidxu } 311239347Sdavidxu return (0); 312239347Sdavidxu} 313239347Sdavidxu 314151357Spsint 315151357Spskern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats) 316151357Sps{ 317130884Skbyanc struct timeval sys, user; 318136152Sjhb struct proc *p; 31925583Speter 320136152Sjhb p = td->td_proc; 321151357Sps switch (clock_id) { 322152844Srwatson case CLOCK_REALTIME: /* Default to precise. */ 323152844Srwatson case CLOCK_REALTIME_PRECISE: 324151357Sps nanotime(ats); 325130654Skbyanc break; 326152844Srwatson case CLOCK_REALTIME_FAST: 327152844Srwatson getnanotime(ats); 328152844Srwatson break; 329130654Skbyanc case CLOCK_VIRTUAL: 330136152Sjhb PROC_LOCK(p); 331170472Sattilio PROC_SLOCK(p); 332136152Sjhb calcru(p, &user, &sys); 333170472Sattilio PROC_SUNLOCK(p); 334136152Sjhb PROC_UNLOCK(p); 335151357Sps TIMEVAL_TO_TIMESPEC(&user, ats); 336130654Skbyanc break; 337130654Skbyanc case CLOCK_PROF: 338136152Sjhb PROC_LOCK(p); 339170472Sattilio PROC_SLOCK(p); 340136152Sjhb calcru(p, &user, &sys); 341170472Sattilio PROC_SUNLOCK(p); 342136152Sjhb PROC_UNLOCK(p); 343130884Skbyanc timevaladd(&user, &sys); 344151357Sps TIMEVAL_TO_TIMESPEC(&user, ats); 345130654Skbyanc break; 346152844Srwatson case CLOCK_MONOTONIC: /* Default to precise. */ 347152844Srwatson case CLOCK_MONOTONIC_PRECISE: 348152585Sandre case CLOCK_UPTIME: 349152844Srwatson case CLOCK_UPTIME_PRECISE: 350151357Sps nanouptime(ats); 351130884Skbyanc break; 352152844Srwatson case CLOCK_UPTIME_FAST: 353152844Srwatson case CLOCK_MONOTONIC_FAST: 354152844Srwatson getnanouptime(ats); 355152844Srwatson break; 356152844Srwatson case CLOCK_SECOND: 357152844Srwatson ats->tv_sec = time_second; 358152844Srwatson ats->tv_nsec = 0; 359152844Srwatson break; 360175429Sdavidxu case CLOCK_THREAD_CPUTIME_ID: 361239347Sdavidxu get_thread_cputime(NULL, ats); 362175429Sdavidxu break; 363239347Sdavidxu case CLOCK_PROCESS_CPUTIME_ID: 364239347Sdavidxu PROC_LOCK(p); 365239347Sdavidxu get_process_cputime(p, ats); 366239347Sdavidxu PROC_UNLOCK(p); 367239347Sdavidxu break; 368130654Skbyanc default: 369239347Sdavidxu if ((int)clock_id >= 0) 370239347Sdavidxu return (EINVAL); 371239347Sdavidxu return (get_cputime(td, clock_id, ats)); 372130654Skbyanc } 373151357Sps return (0); 37425583Speter} 37525583Speter 37625583Speter#ifndef _SYS_SYSPROTO_H_ 37725583Speterstruct clock_settime_args { 37825583Speter clockid_t clock_id; 37925583Speter const struct timespec *tp; 38025583Speter}; 38125583Speter#endif 38225583Speter/* ARGSUSED */ 38325583Speterint 384225617Skmacysys_clock_settime(struct thread *td, struct clock_settime_args *uap) 38525583Speter{ 38625583Speter struct timespec ats; 38725583Speter int error; 38825583Speter 389151357Sps if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0) 390151357Sps return (error); 391151357Sps return (kern_clock_settime(td, uap->clock_id, &ats)); 392151357Sps} 393151357Sps 394151357Spsint 395151357Spskern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats) 396151357Sps{ 397151357Sps struct timeval atv; 398151357Sps int error; 399151357Sps 400164033Srwatson if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) 40194343Sjhb return (error); 402151357Sps if (clock_id != CLOCK_REALTIME) 40394343Sjhb return (EINVAL); 404151357Sps if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000) 40594343Sjhb return (EINVAL); 40634901Sphk /* XXX Don't convert nsec->usec and back */ 407151357Sps TIMESPEC_TO_TIMEVAL(&atv, ats); 40894343Sjhb error = settime(td, &atv); 40982746Sdillon return (error); 41025583Speter} 41125583Speter 41225583Speter#ifndef _SYS_SYSPROTO_H_ 41325583Speterstruct clock_getres_args { 41425583Speter clockid_t clock_id; 41525583Speter struct timespec *tp; 41625583Speter}; 41725583Speter#endif 41825583Speterint 419225617Skmacysys_clock_getres(struct thread *td, struct clock_getres_args *uap) 42025583Speter{ 42125583Speter struct timespec ts; 422151357Sps int error; 42325583Speter 424151357Sps if (uap->tp == NULL) 425151357Sps return (0); 426151357Sps 427151357Sps error = kern_clock_getres(td, uap->clock_id, &ts); 428151357Sps if (error == 0) 429151357Sps error = copyout(&ts, uap->tp, sizeof(ts)); 430151357Sps return (error); 431151357Sps} 432151357Sps 433151357Spsint 434151357Spskern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts) 435151357Sps{ 436151357Sps 437151357Sps ts->tv_sec = 0; 438151357Sps switch (clock_id) { 439130654Skbyanc case CLOCK_REALTIME: 440152844Srwatson case CLOCK_REALTIME_FAST: 441152844Srwatson case CLOCK_REALTIME_PRECISE: 442130654Skbyanc case CLOCK_MONOTONIC: 443152844Srwatson case CLOCK_MONOTONIC_FAST: 444152844Srwatson case CLOCK_MONOTONIC_PRECISE: 445152585Sandre case CLOCK_UPTIME: 446152844Srwatson case CLOCK_UPTIME_FAST: 447152844Srwatson case CLOCK_UPTIME_PRECISE: 448103964Sbde /* 449103964Sbde * Round up the result of the division cheaply by adding 1. 450103964Sbde * Rounding up is especially important if rounding down 451103964Sbde * would give 0. Perfect rounding is unimportant. 452103964Sbde */ 453151357Sps ts->tv_nsec = 1000000000 / tc_getfrequency() + 1; 454130654Skbyanc break; 455130654Skbyanc case CLOCK_VIRTUAL: 456130654Skbyanc case CLOCK_PROF: 457130654Skbyanc /* Accurately round up here because we can do so cheaply. */ 458151357Sps ts->tv_nsec = (1000000000 + hz - 1) / hz; 459130654Skbyanc break; 460152844Srwatson case CLOCK_SECOND: 461152844Srwatson ts->tv_sec = 1; 462152844Srwatson ts->tv_nsec = 0; 463152844Srwatson break; 464175429Sdavidxu case CLOCK_THREAD_CPUTIME_ID: 465239347Sdavidxu case CLOCK_PROCESS_CPUTIME_ID: 466239347Sdavidxu cputime: 467175429Sdavidxu /* sync with cputick2usec */ 468175429Sdavidxu ts->tv_nsec = 1000000 / cpu_tickrate(); 469175429Sdavidxu if (ts->tv_nsec == 0) 470175429Sdavidxu ts->tv_nsec = 1000; 471175429Sdavidxu break; 472130654Skbyanc default: 473239347Sdavidxu if ((int)clock_id < 0) 474239347Sdavidxu goto cputime; 475130654Skbyanc return (EINVAL); 476130654Skbyanc } 477151357Sps return (0); 47825583Speter} 47925583Speter 480248186Smavstatic uint8_t nanowait[MAXCPU]; 48125656Speter 482140481Spsint 483140481Spskern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) 48425583Speter{ 485247797Sdavide struct timespec ts; 486247797Sdavide sbintime_t sbt, sbtt, prec, tmp; 487247898Smav time_t over; 48835042Sphk int error; 48925583Speter 49028773Sbde if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) 49125656Speter return (EINVAL); 49243301Sdillon if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) 49328773Sbde return (0); 494247898Smav ts = *rqt; 495247898Smav if (ts.tv_sec > INT32_MAX / 2) { 496247898Smav over = ts.tv_sec - INT32_MAX / 2; 497247898Smav ts.tv_sec -= over; 498247898Smav } else 499247898Smav over = 0; 500247898Smav tmp = tstosbt(ts); 501247797Sdavide prec = tmp; 502247797Sdavide prec >>= tc_precexp; 503247797Sdavide if (TIMESEL(&sbt, tmp)) 504247797Sdavide sbt += tc_tick_sbt; 505247797Sdavide sbt += tmp; 506248186Smav error = tsleep_sbt(&nanowait[curcpu], PWAIT | PCATCH, "nanslp", 507248186Smav sbt, prec, C_ABSOLUTE); 508247797Sdavide if (error != EWOULDBLOCK) { 509247797Sdavide if (error == ERESTART) 510247797Sdavide error = EINTR; 511247797Sdavide TIMESEL(&sbtt, tmp); 512247797Sdavide if (rmt != NULL) { 513247797Sdavide ts = sbttots(sbt - sbtt); 514247898Smav ts.tv_sec += over; 515247797Sdavide if (ts.tv_sec < 0) 516247797Sdavide timespecclear(&ts); 517247797Sdavide *rmt = ts; 51835042Sphk } 519247797Sdavide if (sbtt >= sbt) 52035042Sphk return (0); 521247797Sdavide return (error); 52226335Speter } 523247797Sdavide return (0); 52426335Speter} 52525583Speter 52626335Speter#ifndef _SYS_SYSPROTO_H_ 52726335Speterstruct nanosleep_args { 52826335Speter struct timespec *rqtp; 52926335Speter struct timespec *rmtp; 53026335Speter}; 53126335Speter#endif 53226335Speter/* ARGSUSED */ 53326335Speterint 534225617Skmacysys_nanosleep(struct thread *td, struct nanosleep_args *uap) 53526335Speter{ 53626335Speter struct timespec rmt, rqt; 53782746Sdillon int error; 53826335Speter 539107849Salfred error = copyin(uap->rqtp, &rqt, sizeof(rqt)); 54026335Speter if (error) 54126335Speter return (error); 54282746Sdillon 543109521Salfred if (uap->rmtp && 544109521Salfred !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 545109521Salfred return (EFAULT); 546140481Sps error = kern_nanosleep(td, &rqt, &rmt); 547107849Salfred if (error && uap->rmtp) { 54882746Sdillon int error2; 54982746Sdillon 550107849Salfred error2 = copyout(&rmt, uap->rmtp, sizeof(rmt)); 551109521Salfred if (error2) 55282746Sdillon error = error2; 55325583Speter } 55425656Speter return (error); 55525583Speter} 55625583Speter 55726335Speter#ifndef _SYS_SYSPROTO_H_ 5581541Srgrimesstruct gettimeofday_args { 5591541Srgrimes struct timeval *tp; 5601541Srgrimes struct timezone *tzp; 5611541Srgrimes}; 56212221Sbde#endif 5631541Srgrimes/* ARGSUSED */ 5641549Srgrimesint 565225617Skmacysys_gettimeofday(struct thread *td, struct gettimeofday_args *uap) 5661541Srgrimes{ 5671541Srgrimes struct timeval atv; 568110286Stjr struct timezone rtz; 5691541Srgrimes int error = 0; 5701541Srgrimes 5711541Srgrimes if (uap->tp) { 5721541Srgrimes microtime(&atv); 57399012Salfred error = copyout(&atv, uap->tp, sizeof (atv)); 5741541Srgrimes } 57590836Sphk if (error == 0 && uap->tzp != NULL) { 576110299Sphk rtz.tz_minuteswest = tz_minuteswest; 577110299Sphk rtz.tz_dsttime = tz_dsttime; 578110286Stjr error = copyout(&rtz, uap->tzp, sizeof (rtz)); 57982746Sdillon } 5801541Srgrimes return (error); 5811541Srgrimes} 5821541Srgrimes 58312221Sbde#ifndef _SYS_SYSPROTO_H_ 5841541Srgrimesstruct settimeofday_args { 5851541Srgrimes struct timeval *tv; 5861541Srgrimes struct timezone *tzp; 5871541Srgrimes}; 58812221Sbde#endif 5891541Srgrimes/* ARGSUSED */ 5901549Srgrimesint 591225617Skmacysys_settimeofday(struct thread *td, struct settimeofday_args *uap) 5921541Srgrimes{ 593144445Sjhb struct timeval atv, *tvp; 594144445Sjhb struct timezone atz, *tzp; 595144445Sjhb int error; 5961541Srgrimes 597144445Sjhb if (uap->tv) { 598144445Sjhb error = copyin(uap->tv, &atv, sizeof(atv)); 599144445Sjhb if (error) 600144445Sjhb return (error); 601144445Sjhb tvp = &atv; 602144445Sjhb } else 603144445Sjhb tvp = NULL; 604144445Sjhb if (uap->tzp) { 605144445Sjhb error = copyin(uap->tzp, &atz, sizeof(atz)); 606144445Sjhb if (error) 607144445Sjhb return (error); 608144445Sjhb tzp = &atz; 609144445Sjhb } else 610144445Sjhb tzp = NULL; 611144445Sjhb return (kern_settimeofday(td, tvp, tzp)); 612144445Sjhb} 613144445Sjhb 614144445Sjhbint 615144445Sjhbkern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp) 616144445Sjhb{ 617144445Sjhb int error; 618144445Sjhb 619164033Srwatson error = priv_check(td, PRIV_SETTIMEOFDAY); 620144445Sjhb if (error) 62194343Sjhb return (error); 6221541Srgrimes /* Verify all parameters before changing time. */ 623144445Sjhb if (tv) { 624144445Sjhb if (tv->tv_usec < 0 || tv->tv_usec >= 1000000) 62594343Sjhb return (EINVAL); 626144445Sjhb error = settime(td, tv); 62725656Speter } 628144445Sjhb if (tzp && error == 0) { 629144445Sjhb tz_minuteswest = tzp->tz_minuteswest; 630144445Sjhb tz_dsttime = tzp->tz_dsttime; 63182746Sdillon } 63282746Sdillon return (error); 6331541Srgrimes} 634144445Sjhb 63582746Sdillon/* 636167232Srwatson * Get value of an interval timer. The process virtual and profiling virtual 637167232Srwatson * time timers are kept in the p_stats area, since they can be swapped out. 638167232Srwatson * These are kept internally in the way they are specified externally: in 639167232Srwatson * time until they expire. 6401541Srgrimes * 641167232Srwatson * The real time interval timer is kept in the process table slot for the 642167232Srwatson * process, and its value (it_value) is kept as an absolute time rather than 643167232Srwatson * as a delta, so that it is easy to keep periodic real-time signals from 644167232Srwatson * drifting. 6451541Srgrimes * 6461541Srgrimes * Virtual time timers are processed in the hardclock() routine of 647167232Srwatson * kern_clock.c. The real time timer is processed by a timeout routine, 648167232Srwatson * called from the softclock() routine. Since a callout may be delayed in 649167232Srwatson * real time due to interrupt processing in the system, it is possible for 650167232Srwatson * the real time timeout routine (realitexpire, given below), to be delayed 651167232Srwatson * in real time past when it is supposed to occur. It does not suffice, 652167232Srwatson * therefore, to reload the real timer .it_value from the real time timers 653167232Srwatson * .it_interval. Rather, we compute the next time in absolute time the timer 654167232Srwatson * should go off. 6551541Srgrimes */ 65612221Sbde#ifndef _SYS_SYSPROTO_H_ 6571541Srgrimesstruct getitimer_args { 6581541Srgrimes u_int which; 6591541Srgrimes struct itimerval *itv; 6601541Srgrimes}; 66112221Sbde#endif 6621549Srgrimesint 663225617Skmacysys_getitimer(struct thread *td, struct getitimer_args *uap) 6641541Srgrimes{ 665141470Sjhb struct itimerval aitv; 666140832Ssobomax int error; 667140832Ssobomax 668140832Ssobomax error = kern_getitimer(td, uap->which, &aitv); 669140832Ssobomax if (error != 0) 670140832Ssobomax return (error); 671140832Ssobomax return (copyout(&aitv, uap->itv, sizeof (struct itimerval))); 672140832Ssobomax} 673140832Ssobomax 674140832Ssobomaxint 675140832Ssobomaxkern_getitimer(struct thread *td, u_int which, struct itimerval *aitv) 676140832Ssobomax{ 67783366Sjulian struct proc *p = td->td_proc; 67834961Sphk struct timeval ctv; 6791541Srgrimes 680140832Ssobomax if (which > ITIMER_PROF) 6811541Srgrimes return (EINVAL); 68282746Sdillon 683140832Ssobomax if (which == ITIMER_REAL) { 6841541Srgrimes /* 68536128Sbde * Convert from absolute to relative time in .it_value 6861541Srgrimes * part of real time timer. If time for real time timer 6871541Srgrimes * has passed return 0, else return difference between 6881541Srgrimes * current time and time for the timer to go off. 6891541Srgrimes */ 690111034Stjr PROC_LOCK(p); 691140832Ssobomax *aitv = p->p_realtimer; 692111034Stjr PROC_UNLOCK(p); 693140832Ssobomax if (timevalisset(&aitv->it_value)) { 694247903Smav microuptime(&ctv); 695140832Ssobomax if (timevalcmp(&aitv->it_value, &ctv, <)) 696140832Ssobomax timevalclear(&aitv->it_value); 6971541Srgrimes else 698140832Ssobomax timevalsub(&aitv->it_value, &ctv); 69934961Sphk } 70082746Sdillon } else { 701170307Sjeff PROC_SLOCK(p); 702140832Ssobomax *aitv = p->p_stats->p_timer[which]; 703170307Sjeff PROC_SUNLOCK(p); 70482746Sdillon } 705140832Ssobomax return (0); 7061541Srgrimes} 7071541Srgrimes 70812221Sbde#ifndef _SYS_SYSPROTO_H_ 7091541Srgrimesstruct setitimer_args { 7101541Srgrimes u_int which; 7111541Srgrimes struct itimerval *itv, *oitv; 7121541Srgrimes}; 71312221Sbde#endif 7141549Srgrimesint 715225617Skmacysys_setitimer(struct thread *td, struct setitimer_args *uap) 7161541Srgrimes{ 717141470Sjhb struct itimerval aitv, oitv; 718140832Ssobomax int error; 7191541Srgrimes 720111034Stjr if (uap->itv == NULL) { 721111034Stjr uap->itv = uap->oitv; 722225617Skmacy return (sys_getitimer(td, (struct getitimer_args *)uap)); 723111034Stjr } 724111034Stjr 725111034Stjr if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval)))) 7261541Srgrimes return (error); 727140832Ssobomax error = kern_setitimer(td, uap->which, &aitv, &oitv); 728140832Ssobomax if (error != 0 || uap->oitv == NULL) 729140832Ssobomax return (error); 730140832Ssobomax return (copyout(&oitv, uap->oitv, sizeof(struct itimerval))); 731140832Ssobomax} 732140832Ssobomax 733140832Ssobomaxint 734141470Sjhbkern_setitimer(struct thread *td, u_int which, struct itimerval *aitv, 735141470Sjhb struct itimerval *oitv) 736140832Ssobomax{ 737140832Ssobomax struct proc *p = td->td_proc; 738140832Ssobomax struct timeval ctv; 739247903Smav sbintime_t sbt, pr; 740140832Ssobomax 741141483Sjhb if (aitv == NULL) 742141483Sjhb return (kern_getitimer(td, which, oitv)); 743141483Sjhb 744140832Ssobomax if (which > ITIMER_PROF) 745111034Stjr return (EINVAL); 746247903Smav if (itimerfix(&aitv->it_value) || 747247903Smav aitv->it_value.tv_sec > INT32_MAX / 2) 748111034Stjr return (EINVAL); 749140832Ssobomax if (!timevalisset(&aitv->it_value)) 750140832Ssobomax timevalclear(&aitv->it_interval); 751247903Smav else if (itimerfix(&aitv->it_interval) || 752247903Smav aitv->it_interval.tv_sec > INT32_MAX / 2) 753140832Ssobomax return (EINVAL); 75482746Sdillon 755140832Ssobomax if (which == ITIMER_REAL) { 756111034Stjr PROC_LOCK(p); 75735058Sphk if (timevalisset(&p->p_realtimer.it_value)) 75869286Sjake callout_stop(&p->p_itcallout); 759247903Smav microuptime(&ctv); 760140832Ssobomax if (timevalisset(&aitv->it_value)) { 761247903Smav pr = tvtosbt(aitv->it_value) >> tc_precexp; 762140832Ssobomax timevaladd(&aitv->it_value, &ctv); 763247903Smav sbt = tvtosbt(aitv->it_value); 764247903Smav callout_reset_sbt(&p->p_itcallout, sbt, pr, 765247903Smav realitexpire, p, C_ABSOLUTE); 766114980Sjhb } 767140832Ssobomax *oitv = p->p_realtimer; 768140832Ssobomax p->p_realtimer = *aitv; 769111034Stjr PROC_UNLOCK(p); 770140832Ssobomax if (timevalisset(&oitv->it_value)) { 771140832Ssobomax if (timevalcmp(&oitv->it_value, &ctv, <)) 772140832Ssobomax timevalclear(&oitv->it_value); 773111034Stjr else 774140832Ssobomax timevalsub(&oitv->it_value, &ctv); 775111034Stjr } 77682746Sdillon } else { 777264821Smav if (aitv->it_interval.tv_sec == 0 && 778264821Smav aitv->it_interval.tv_usec != 0 && 779264821Smav aitv->it_interval.tv_usec < tick) 780264821Smav aitv->it_interval.tv_usec = tick; 781264821Smav if (aitv->it_value.tv_sec == 0 && 782264821Smav aitv->it_value.tv_usec != 0 && 783264821Smav aitv->it_value.tv_usec < tick) 784264821Smav aitv->it_value.tv_usec = tick; 785170307Sjeff PROC_SLOCK(p); 786140832Ssobomax *oitv = p->p_stats->p_timer[which]; 787140832Ssobomax p->p_stats->p_timer[which] = *aitv; 788170307Sjeff PROC_SUNLOCK(p); 78982746Sdillon } 790140832Ssobomax return (0); 7911541Srgrimes} 7921541Srgrimes 7931541Srgrimes/* 7941541Srgrimes * Real interval timer expired: 7951541Srgrimes * send process whose timer expired an alarm signal. 7961541Srgrimes * If time is not set up to reload, then just return. 7971541Srgrimes * Else compute next time timer should go off which is > current time. 7981541Srgrimes * This is where delay in processing this timeout causes multiple 7991541Srgrimes * SIGALRM calls to be compressed into one. 80036127Sbde * tvtohz() always adds 1 to allow for the time until the next clock 8019327Sbde * interrupt being strictly less than 1 clock tick, but we don't want 8029327Sbde * that here since we want to appear to be in sync with the clock 8039327Sbde * interrupt even when we're delayed. 8041541Srgrimes */ 8051541Srgrimesvoid 806102074Sphkrealitexpire(void *arg) 8071541Srgrimes{ 808102074Sphk struct proc *p; 809247903Smav struct timeval ctv; 810247903Smav sbintime_t isbt; 8111541Srgrimes 8121541Srgrimes p = (struct proc *)arg; 813225617Skmacy kern_psignal(p, SIGALRM); 81435058Sphk if (!timevalisset(&p->p_realtimer.it_interval)) { 81535058Sphk timevalclear(&p->p_realtimer.it_value); 816116123Sjhb if (p->p_flag & P_WEXIT) 817116123Sjhb wakeup(&p->p_itcallout); 8181541Srgrimes return; 8191541Srgrimes } 820247903Smav isbt = tvtosbt(p->p_realtimer.it_interval); 821247903Smav if (isbt >= sbt_timethreshold) 822247903Smav getmicrouptime(&ctv); 823247903Smav else 824247903Smav microuptime(&ctv); 825247903Smav do { 8261541Srgrimes timevaladd(&p->p_realtimer.it_value, 8271541Srgrimes &p->p_realtimer.it_interval); 828247903Smav } while (timevalcmp(&p->p_realtimer.it_value, &ctv, <=)); 829247903Smav callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value), 830247903Smav isbt >> tc_precexp, realitexpire, p, C_ABSOLUTE); 8311541Srgrimes} 8321541Srgrimes 8331541Srgrimes/* 8341541Srgrimes * Check that a proposed value to load into the .it_value or 8351541Srgrimes * .it_interval part of an interval timer is acceptable, and 8361541Srgrimes * fix it to have at least minimal value (i.e. if it is less 8371541Srgrimes * than the resolution of the clock, round it up.) 8381541Srgrimes */ 8391549Srgrimesint 840102074Sphkitimerfix(struct timeval *tv) 8411541Srgrimes{ 8421541Srgrimes 843151576Sdavidxu if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) 8441541Srgrimes return (EINVAL); 845247903Smav if (tv->tv_sec == 0 && tv->tv_usec != 0 && 846247903Smav tv->tv_usec < (u_int)tick / 16) 847247903Smav tv->tv_usec = (u_int)tick / 16; 8481541Srgrimes return (0); 8491541Srgrimes} 8501541Srgrimes 8511541Srgrimes/* 8521541Srgrimes * Decrement an interval timer by a specified number 8531541Srgrimes * of microseconds, which must be less than a second, 8541541Srgrimes * i.e. < 1000000. If the timer expires, then reload 8551541Srgrimes * it. In this case, carry over (usec - old value) to 8561541Srgrimes * reduce the value reloaded into the timer so that 8571541Srgrimes * the timer does not drift. This routine assumes 8581541Srgrimes * that it is called in a context where the timers 8591541Srgrimes * on which it is operating cannot change in value. 8601541Srgrimes */ 8611549Srgrimesint 862102074Sphkitimerdecr(struct itimerval *itp, int usec) 8631541Srgrimes{ 8641541Srgrimes 8651541Srgrimes if (itp->it_value.tv_usec < usec) { 8661541Srgrimes if (itp->it_value.tv_sec == 0) { 8671541Srgrimes /* expired, and already in next interval */ 8681541Srgrimes usec -= itp->it_value.tv_usec; 8691541Srgrimes goto expire; 8701541Srgrimes } 8711541Srgrimes itp->it_value.tv_usec += 1000000; 8721541Srgrimes itp->it_value.tv_sec--; 8731541Srgrimes } 8741541Srgrimes itp->it_value.tv_usec -= usec; 8751541Srgrimes usec = 0; 87635058Sphk if (timevalisset(&itp->it_value)) 8771541Srgrimes return (1); 8781541Srgrimes /* expired, exactly at end of interval */ 8791541Srgrimesexpire: 88035058Sphk if (timevalisset(&itp->it_interval)) { 8811541Srgrimes itp->it_value = itp->it_interval; 8821541Srgrimes itp->it_value.tv_usec -= usec; 8831541Srgrimes if (itp->it_value.tv_usec < 0) { 8841541Srgrimes itp->it_value.tv_usec += 1000000; 8851541Srgrimes itp->it_value.tv_sec--; 8861541Srgrimes } 8871541Srgrimes } else 8881541Srgrimes itp->it_value.tv_usec = 0; /* sec is already 0 */ 8891541Srgrimes return (0); 8901541Srgrimes} 8911541Srgrimes 8921541Srgrimes/* 8931541Srgrimes * Add and subtract routines for timevals. 8941541Srgrimes * N.B.: subtract routine doesn't deal with 8951541Srgrimes * results which are before the beginning, 8961541Srgrimes * it just gets very confused in this case. 8971541Srgrimes * Caveat emptor. 8981541Srgrimes */ 8991549Srgrimesvoid 900121523Salfredtimevaladd(struct timeval *t1, const struct timeval *t2) 9011541Srgrimes{ 9021541Srgrimes 9031541Srgrimes t1->tv_sec += t2->tv_sec; 9041541Srgrimes t1->tv_usec += t2->tv_usec; 9051541Srgrimes timevalfix(t1); 9061541Srgrimes} 9071541Srgrimes 9081549Srgrimesvoid 909121523Salfredtimevalsub(struct timeval *t1, const struct timeval *t2) 9101541Srgrimes{ 9111541Srgrimes 9121541Srgrimes t1->tv_sec -= t2->tv_sec; 9131541Srgrimes t1->tv_usec -= t2->tv_usec; 9141541Srgrimes timevalfix(t1); 9151541Srgrimes} 9161541Srgrimes 91712819Sphkstatic void 918102074Sphktimevalfix(struct timeval *t1) 9191541Srgrimes{ 9201541Srgrimes 9211541Srgrimes if (t1->tv_usec < 0) { 9221541Srgrimes t1->tv_sec--; 9231541Srgrimes t1->tv_usec += 1000000; 9241541Srgrimes } 9251541Srgrimes if (t1->tv_usec >= 1000000) { 9261541Srgrimes t1->tv_sec++; 9271541Srgrimes t1->tv_usec -= 1000000; 9281541Srgrimes } 9291541Srgrimes} 930108142Ssam 931108142Ssam/* 932108511Ssam * ratecheck(): simple time-based rate-limit checking. 933108142Ssam */ 934108142Ssamint 935108142Ssamratecheck(struct timeval *lasttime, const struct timeval *mininterval) 936108142Ssam{ 937108142Ssam struct timeval tv, delta; 938108142Ssam int rv = 0; 939108142Ssam 940108511Ssam getmicrouptime(&tv); /* NB: 10ms precision */ 941108511Ssam delta = tv; 942108511Ssam timevalsub(&delta, lasttime); 943108142Ssam 944108142Ssam /* 945108142Ssam * check for 0,0 is so that the message will be seen at least once, 946108142Ssam * even if interval is huge. 947108142Ssam */ 948108142Ssam if (timevalcmp(&delta, mininterval, >=) || 949108142Ssam (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 950108142Ssam *lasttime = tv; 951108142Ssam rv = 1; 952108142Ssam } 953108142Ssam 954108142Ssam return (rv); 955108142Ssam} 956108142Ssam 957108142Ssam/* 958108142Ssam * ppsratecheck(): packets (or events) per second limitation. 959108511Ssam * 960108511Ssam * Return 0 if the limit is to be enforced (e.g. the caller 961108511Ssam * should drop a packet because of the rate limitation). 962108511Ssam * 963111558Ssam * maxpps of 0 always causes zero to be returned. maxpps of -1 964111558Ssam * always causes 1 to be returned; this effectively defeats rate 965111558Ssam * limiting. 966111558Ssam * 967108511Ssam * Note that we maintain the struct timeval for compatibility 968108511Ssam * with other bsd systems. We reuse the storage and just monitor 969108511Ssam * clock ticks for minimal overhead. 970108142Ssam */ 971108142Ssamint 972108142Ssamppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 973108142Ssam{ 974108511Ssam int now; 975108142Ssam 976108142Ssam /* 977108511Ssam * Reset the last time and counter if this is the first call 978108511Ssam * or more than a second has passed since the last update of 979108511Ssam * lasttime. 980108142Ssam */ 981108511Ssam now = ticks; 982108511Ssam if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { 983108511Ssam lasttime->tv_sec = now; 984108511Ssam *curpps = 1; 985111558Ssam return (maxpps != 0); 986108511Ssam } else { 987108511Ssam (*curpps)++; /* NB: ignore potential overflow */ 988108511Ssam return (maxpps < 0 || *curpps < maxpps); 989108511Ssam } 990108142Ssam} 991151576Sdavidxu 992151576Sdavidxustatic void 993151576Sdavidxuitimer_start(void) 994151576Sdavidxu{ 995151576Sdavidxu struct kclock rt_clock = { 996151576Sdavidxu .timer_create = realtimer_create, 997151576Sdavidxu .timer_delete = realtimer_delete, 998151576Sdavidxu .timer_settime = realtimer_settime, 999151576Sdavidxu .timer_gettime = realtimer_gettime, 1000164713Sdavidxu .event_hook = NULL 1001151576Sdavidxu }; 1002151576Sdavidxu 1003151576Sdavidxu itimer_zone = uma_zcreate("itimer", sizeof(struct itimer), 1004151576Sdavidxu NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0); 1005151576Sdavidxu register_posix_clock(CLOCK_REALTIME, &rt_clock); 1006151576Sdavidxu register_posix_clock(CLOCK_MONOTONIC, &rt_clock); 1007152983Sdavidxu p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L); 1008152983Sdavidxu p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX); 1009152983Sdavidxu p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX); 1010161302Snetchild EVENTHANDLER_REGISTER(process_exit, itimers_event_hook_exit, 1011153259Sdavidxu (void *)ITIMER_EV_EXIT, EVENTHANDLER_PRI_ANY); 1012161302Snetchild EVENTHANDLER_REGISTER(process_exec, itimers_event_hook_exec, 1013153259Sdavidxu (void *)ITIMER_EV_EXEC, EVENTHANDLER_PRI_ANY); 1014151576Sdavidxu} 1015151576Sdavidxu 1016151576Sdavidxuint 1017151576Sdavidxuregister_posix_clock(int clockid, struct kclock *clk) 1018151576Sdavidxu{ 1019151576Sdavidxu if ((unsigned)clockid >= MAX_CLOCKS) { 1020151576Sdavidxu printf("%s: invalid clockid\n", __func__); 1021151576Sdavidxu return (0); 1022151576Sdavidxu } 1023151576Sdavidxu posix_clocks[clockid] = *clk; 1024151576Sdavidxu return (1); 1025151576Sdavidxu} 1026151576Sdavidxu 1027151576Sdavidxustatic int 1028151576Sdavidxuitimer_init(void *mem, int size, int flags) 1029151576Sdavidxu{ 1030151576Sdavidxu struct itimer *it; 1031151576Sdavidxu 1032151576Sdavidxu it = (struct itimer *)mem; 1033151576Sdavidxu mtx_init(&it->it_mtx, "itimer lock", NULL, MTX_DEF); 1034151576Sdavidxu return (0); 1035151576Sdavidxu} 1036151576Sdavidxu 1037151576Sdavidxustatic void 1038151576Sdavidxuitimer_fini(void *mem, int size) 1039151576Sdavidxu{ 1040151576Sdavidxu struct itimer *it; 1041151576Sdavidxu 1042151576Sdavidxu it = (struct itimer *)mem; 1043151576Sdavidxu mtx_destroy(&it->it_mtx); 1044151576Sdavidxu} 1045151576Sdavidxu 1046151576Sdavidxustatic void 1047151576Sdavidxuitimer_enter(struct itimer *it) 1048151576Sdavidxu{ 1049151576Sdavidxu 1050151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1051151576Sdavidxu it->it_usecount++; 1052151576Sdavidxu} 1053151576Sdavidxu 1054151576Sdavidxustatic void 1055151576Sdavidxuitimer_leave(struct itimer *it) 1056151576Sdavidxu{ 1057151576Sdavidxu 1058151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1059151576Sdavidxu KASSERT(it->it_usecount > 0, ("invalid it_usecount")); 1060151576Sdavidxu 1061151576Sdavidxu if (--it->it_usecount == 0 && (it->it_flags & ITF_WANTED) != 0) 1062151576Sdavidxu wakeup(it); 1063151576Sdavidxu} 1064151576Sdavidxu 1065151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1066156134Sdavidxustruct ktimer_create_args { 1067151576Sdavidxu clockid_t clock_id; 1068151576Sdavidxu struct sigevent * evp; 1069156134Sdavidxu int * timerid; 1070151576Sdavidxu}; 1071151576Sdavidxu#endif 1072151576Sdavidxuint 1073225617Skmacysys_ktimer_create(struct thread *td, struct ktimer_create_args *uap) 1074151576Sdavidxu{ 1075253530Skib struct sigevent *evp, ev; 1076156134Sdavidxu int id; 1077151576Sdavidxu int error; 1078151576Sdavidxu 1079253530Skib if (uap->evp == NULL) { 1080253530Skib evp = NULL; 1081253530Skib } else { 1082151576Sdavidxu error = copyin(uap->evp, &ev, sizeof(ev)); 1083151576Sdavidxu if (error != 0) 1084151576Sdavidxu return (error); 1085253530Skib evp = &ev; 1086253530Skib } 1087253530Skib error = kern_ktimer_create(td, uap->clock_id, evp, &id, -1); 1088151576Sdavidxu if (error == 0) { 1089156134Sdavidxu error = copyout(&id, uap->timerid, sizeof(int)); 1090151576Sdavidxu if (error != 0) 1091253530Skib kern_ktimer_delete(td, id); 1092151576Sdavidxu } 1093151576Sdavidxu return (error); 1094151576Sdavidxu} 1095151576Sdavidxu 1096253530Skibint 1097253530Skibkern_ktimer_create(struct thread *td, clockid_t clock_id, struct sigevent *evp, 1098253530Skib int *timerid, int preset_id) 1099151576Sdavidxu{ 1100151576Sdavidxu struct proc *p = td->td_proc; 1101151576Sdavidxu struct itimer *it; 1102151576Sdavidxu int id; 1103151576Sdavidxu int error; 1104151576Sdavidxu 1105151576Sdavidxu if (clock_id < 0 || clock_id >= MAX_CLOCKS) 1106151576Sdavidxu return (EINVAL); 1107151576Sdavidxu 1108151576Sdavidxu if (posix_clocks[clock_id].timer_create == NULL) 1109151576Sdavidxu return (EINVAL); 1110151576Sdavidxu 1111151576Sdavidxu if (evp != NULL) { 1112151576Sdavidxu if (evp->sigev_notify != SIGEV_NONE && 1113151869Sdavidxu evp->sigev_notify != SIGEV_SIGNAL && 1114151869Sdavidxu evp->sigev_notify != SIGEV_THREAD_ID) 1115151576Sdavidxu return (EINVAL); 1116151869Sdavidxu if ((evp->sigev_notify == SIGEV_SIGNAL || 1117151869Sdavidxu evp->sigev_notify == SIGEV_THREAD_ID) && 1118151576Sdavidxu !_SIG_VALID(evp->sigev_signo)) 1119151576Sdavidxu return (EINVAL); 1120151576Sdavidxu } 1121151576Sdavidxu 1122151585Sdavidxu if (p->p_itimers == NULL) 1123151576Sdavidxu itimers_alloc(p); 1124151576Sdavidxu 1125151576Sdavidxu it = uma_zalloc(itimer_zone, M_WAITOK); 1126151576Sdavidxu it->it_flags = 0; 1127151576Sdavidxu it->it_usecount = 0; 1128151576Sdavidxu it->it_active = 0; 1129151869Sdavidxu timespecclear(&it->it_time.it_value); 1130151869Sdavidxu timespecclear(&it->it_time.it_interval); 1131151576Sdavidxu it->it_overrun = 0; 1132151576Sdavidxu it->it_overrun_last = 0; 1133151576Sdavidxu it->it_clockid = clock_id; 1134151576Sdavidxu it->it_timerid = -1; 1135151576Sdavidxu it->it_proc = p; 1136151576Sdavidxu ksiginfo_init(&it->it_ksi); 1137151576Sdavidxu it->it_ksi.ksi_flags |= KSI_INS | KSI_EXT; 1138151576Sdavidxu error = CLOCK_CALL(clock_id, timer_create, (it)); 1139151576Sdavidxu if (error != 0) 1140151576Sdavidxu goto out; 1141151576Sdavidxu 1142151576Sdavidxu PROC_LOCK(p); 1143151576Sdavidxu if (preset_id != -1) { 1144151576Sdavidxu KASSERT(preset_id >= 0 && preset_id < 3, ("invalid preset_id")); 1145151576Sdavidxu id = preset_id; 1146151585Sdavidxu if (p->p_itimers->its_timers[id] != NULL) { 1147151576Sdavidxu PROC_UNLOCK(p); 1148151576Sdavidxu error = 0; 1149151576Sdavidxu goto out; 1150151576Sdavidxu } 1151151576Sdavidxu } else { 1152151576Sdavidxu /* 1153151576Sdavidxu * Find a free timer slot, skipping those reserved 1154151576Sdavidxu * for setitimer(). 1155151576Sdavidxu */ 1156151576Sdavidxu for (id = 3; id < TIMER_MAX; id++) 1157151585Sdavidxu if (p->p_itimers->its_timers[id] == NULL) 1158151576Sdavidxu break; 1159151576Sdavidxu if (id == TIMER_MAX) { 1160151576Sdavidxu PROC_UNLOCK(p); 1161151576Sdavidxu error = EAGAIN; 1162151576Sdavidxu goto out; 1163151576Sdavidxu } 1164151576Sdavidxu } 1165151576Sdavidxu it->it_timerid = id; 1166151585Sdavidxu p->p_itimers->its_timers[id] = it; 1167151576Sdavidxu if (evp != NULL) 1168151576Sdavidxu it->it_sigev = *evp; 1169151576Sdavidxu else { 1170151576Sdavidxu it->it_sigev.sigev_notify = SIGEV_SIGNAL; 1171151576Sdavidxu switch (clock_id) { 1172151576Sdavidxu default: 1173151576Sdavidxu case CLOCK_REALTIME: 1174151576Sdavidxu it->it_sigev.sigev_signo = SIGALRM; 1175151576Sdavidxu break; 1176151576Sdavidxu case CLOCK_VIRTUAL: 1177151576Sdavidxu it->it_sigev.sigev_signo = SIGVTALRM; 1178151576Sdavidxu break; 1179151576Sdavidxu case CLOCK_PROF: 1180151576Sdavidxu it->it_sigev.sigev_signo = SIGPROF; 1181151576Sdavidxu break; 1182151576Sdavidxu } 1183152029Sdavidxu it->it_sigev.sigev_value.sival_int = id; 1184151576Sdavidxu } 1185151576Sdavidxu 1186151869Sdavidxu if (it->it_sigev.sigev_notify == SIGEV_SIGNAL || 1187151869Sdavidxu it->it_sigev.sigev_notify == SIGEV_THREAD_ID) { 1188151576Sdavidxu it->it_ksi.ksi_signo = it->it_sigev.sigev_signo; 1189151576Sdavidxu it->it_ksi.ksi_code = SI_TIMER; 1190151576Sdavidxu it->it_ksi.ksi_value = it->it_sigev.sigev_value; 1191151576Sdavidxu it->it_ksi.ksi_timerid = id; 1192151576Sdavidxu } 1193151576Sdavidxu PROC_UNLOCK(p); 1194151576Sdavidxu *timerid = id; 1195151576Sdavidxu return (0); 1196151576Sdavidxu 1197151576Sdavidxuout: 1198151576Sdavidxu ITIMER_LOCK(it); 1199151576Sdavidxu CLOCK_CALL(it->it_clockid, timer_delete, (it)); 1200151576Sdavidxu ITIMER_UNLOCK(it); 1201151576Sdavidxu uma_zfree(itimer_zone, it); 1202151576Sdavidxu return (error); 1203151576Sdavidxu} 1204151576Sdavidxu 1205151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1206156134Sdavidxustruct ktimer_delete_args { 1207156134Sdavidxu int timerid; 1208151576Sdavidxu}; 1209151576Sdavidxu#endif 1210151576Sdavidxuint 1211225617Skmacysys_ktimer_delete(struct thread *td, struct ktimer_delete_args *uap) 1212151576Sdavidxu{ 1213253530Skib 1214253530Skib return (kern_ktimer_delete(td, uap->timerid)); 1215151576Sdavidxu} 1216151576Sdavidxu 1217151576Sdavidxustatic struct itimer * 1218164713Sdavidxuitimer_find(struct proc *p, int timerid) 1219151576Sdavidxu{ 1220151576Sdavidxu struct itimer *it; 1221151576Sdavidxu 1222151576Sdavidxu PROC_LOCK_ASSERT(p, MA_OWNED); 1223190301Scperciva if ((p->p_itimers == NULL) || 1224190301Scperciva (timerid < 0) || (timerid >= TIMER_MAX) || 1225151585Sdavidxu (it = p->p_itimers->its_timers[timerid]) == NULL) { 1226151576Sdavidxu return (NULL); 1227151576Sdavidxu } 1228151576Sdavidxu ITIMER_LOCK(it); 1229164713Sdavidxu if ((it->it_flags & ITF_DELETING) != 0) { 1230151576Sdavidxu ITIMER_UNLOCK(it); 1231151576Sdavidxu it = NULL; 1232151576Sdavidxu } 1233151576Sdavidxu return (it); 1234151576Sdavidxu} 1235151576Sdavidxu 1236253530Skibint 1237253530Skibkern_ktimer_delete(struct thread *td, int timerid) 1238151576Sdavidxu{ 1239151576Sdavidxu struct proc *p = td->td_proc; 1240151576Sdavidxu struct itimer *it; 1241151576Sdavidxu 1242151576Sdavidxu PROC_LOCK(p); 1243164713Sdavidxu it = itimer_find(p, timerid); 1244151576Sdavidxu if (it == NULL) { 1245151576Sdavidxu PROC_UNLOCK(p); 1246151576Sdavidxu return (EINVAL); 1247151576Sdavidxu } 1248151576Sdavidxu PROC_UNLOCK(p); 1249151576Sdavidxu 1250151576Sdavidxu it->it_flags |= ITF_DELETING; 1251151576Sdavidxu while (it->it_usecount > 0) { 1252151576Sdavidxu it->it_flags |= ITF_WANTED; 1253151576Sdavidxu msleep(it, &it->it_mtx, PPAUSE, "itimer", 0); 1254151576Sdavidxu } 1255151576Sdavidxu it->it_flags &= ~ITF_WANTED; 1256151576Sdavidxu CLOCK_CALL(it->it_clockid, timer_delete, (it)); 1257151576Sdavidxu ITIMER_UNLOCK(it); 1258151576Sdavidxu 1259151576Sdavidxu PROC_LOCK(p); 1260151576Sdavidxu if (KSI_ONQ(&it->it_ksi)) 1261151576Sdavidxu sigqueue_take(&it->it_ksi); 1262151585Sdavidxu p->p_itimers->its_timers[timerid] = NULL; 1263151576Sdavidxu PROC_UNLOCK(p); 1264151576Sdavidxu uma_zfree(itimer_zone, it); 1265151576Sdavidxu return (0); 1266151576Sdavidxu} 1267151576Sdavidxu 1268151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1269156134Sdavidxustruct ktimer_settime_args { 1270156134Sdavidxu int timerid; 1271151576Sdavidxu int flags; 1272151576Sdavidxu const struct itimerspec * value; 1273151576Sdavidxu struct itimerspec * ovalue; 1274151576Sdavidxu}; 1275151576Sdavidxu#endif 1276151576Sdavidxuint 1277225617Skmacysys_ktimer_settime(struct thread *td, struct ktimer_settime_args *uap) 1278151576Sdavidxu{ 1279151576Sdavidxu struct itimerspec val, oval, *ovalp; 1280151576Sdavidxu int error; 1281151576Sdavidxu 1282151576Sdavidxu error = copyin(uap->value, &val, sizeof(val)); 1283151576Sdavidxu if (error != 0) 1284151576Sdavidxu return (error); 1285253530Skib ovalp = uap->ovalue != NULL ? &oval : NULL; 1286253530Skib error = kern_ktimer_settime(td, uap->timerid, uap->flags, &val, ovalp); 1287253530Skib if (error == 0 && uap->ovalue != NULL) 1288253530Skib error = copyout(ovalp, uap->ovalue, sizeof(*ovalp)); 1289253530Skib return (error); 1290253530Skib} 1291151576Sdavidxu 1292253530Skibint 1293253530Skibkern_ktimer_settime(struct thread *td, int timer_id, int flags, 1294253530Skib struct itimerspec *val, struct itimerspec *oval) 1295253530Skib{ 1296253530Skib struct proc *p; 1297253530Skib struct itimer *it; 1298253530Skib int error; 1299253530Skib 1300253530Skib p = td->td_proc; 1301151576Sdavidxu PROC_LOCK(p); 1302253530Skib if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) { 1303151576Sdavidxu PROC_UNLOCK(p); 1304151576Sdavidxu error = EINVAL; 1305151576Sdavidxu } else { 1306151576Sdavidxu PROC_UNLOCK(p); 1307151576Sdavidxu itimer_enter(it); 1308253530Skib error = CLOCK_CALL(it->it_clockid, timer_settime, (it, 1309253530Skib flags, val, oval)); 1310151576Sdavidxu itimer_leave(it); 1311151576Sdavidxu ITIMER_UNLOCK(it); 1312151576Sdavidxu } 1313151576Sdavidxu return (error); 1314151576Sdavidxu} 1315151576Sdavidxu 1316151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1317156134Sdavidxustruct ktimer_gettime_args { 1318156134Sdavidxu int timerid; 1319151576Sdavidxu struct itimerspec * value; 1320151576Sdavidxu}; 1321151576Sdavidxu#endif 1322151576Sdavidxuint 1323225617Skmacysys_ktimer_gettime(struct thread *td, struct ktimer_gettime_args *uap) 1324151576Sdavidxu{ 1325151576Sdavidxu struct itimerspec val; 1326151576Sdavidxu int error; 1327151576Sdavidxu 1328253530Skib error = kern_ktimer_gettime(td, uap->timerid, &val); 1329253530Skib if (error == 0) 1330253530Skib error = copyout(&val, uap->value, sizeof(val)); 1331253530Skib return (error); 1332253530Skib} 1333253530Skib 1334253530Skibint 1335253530Skibkern_ktimer_gettime(struct thread *td, int timer_id, struct itimerspec *val) 1336253530Skib{ 1337253530Skib struct proc *p; 1338253530Skib struct itimer *it; 1339253530Skib int error; 1340253530Skib 1341253530Skib p = td->td_proc; 1342151576Sdavidxu PROC_LOCK(p); 1343253530Skib if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) { 1344151576Sdavidxu PROC_UNLOCK(p); 1345151576Sdavidxu error = EINVAL; 1346151576Sdavidxu } else { 1347151576Sdavidxu PROC_UNLOCK(p); 1348151576Sdavidxu itimer_enter(it); 1349253530Skib error = CLOCK_CALL(it->it_clockid, timer_gettime, (it, val)); 1350151576Sdavidxu itimer_leave(it); 1351151576Sdavidxu ITIMER_UNLOCK(it); 1352151576Sdavidxu } 1353151576Sdavidxu return (error); 1354151576Sdavidxu} 1355151576Sdavidxu 1356151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1357151576Sdavidxustruct timer_getoverrun_args { 1358156134Sdavidxu int timerid; 1359151576Sdavidxu}; 1360151576Sdavidxu#endif 1361151576Sdavidxuint 1362225617Skmacysys_ktimer_getoverrun(struct thread *td, struct ktimer_getoverrun_args *uap) 1363151576Sdavidxu{ 1364270042Sbz 1365270042Sbz return (kern_ktimer_getoverrun(td, uap->timerid)); 1366270042Sbz} 1367270042Sbz 1368270042Sbzint 1369270042Sbzkern_ktimer_getoverrun(struct thread *td, int timer_id) 1370270042Sbz{ 1371151576Sdavidxu struct proc *p = td->td_proc; 1372151576Sdavidxu struct itimer *it; 1373151576Sdavidxu int error ; 1374151576Sdavidxu 1375151576Sdavidxu PROC_LOCK(p); 1376270042Sbz if (timer_id < 3 || 1377270042Sbz (it = itimer_find(p, timer_id)) == NULL) { 1378151576Sdavidxu PROC_UNLOCK(p); 1379151576Sdavidxu error = EINVAL; 1380151576Sdavidxu } else { 1381151576Sdavidxu td->td_retval[0] = it->it_overrun_last; 1382151576Sdavidxu ITIMER_UNLOCK(it); 1383151869Sdavidxu PROC_UNLOCK(p); 1384151576Sdavidxu error = 0; 1385151576Sdavidxu } 1386151576Sdavidxu return (error); 1387151576Sdavidxu} 1388151576Sdavidxu 1389151576Sdavidxustatic int 1390151576Sdavidxurealtimer_create(struct itimer *it) 1391151576Sdavidxu{ 1392151576Sdavidxu callout_init_mtx(&it->it_callout, &it->it_mtx, 0); 1393151576Sdavidxu return (0); 1394151576Sdavidxu} 1395151576Sdavidxu 1396151576Sdavidxustatic int 1397151576Sdavidxurealtimer_delete(struct itimer *it) 1398151576Sdavidxu{ 1399151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1400164713Sdavidxu 1401184067Sdavidxu /* 1402184067Sdavidxu * clear timer's value and interval to tell realtimer_expire 1403184067Sdavidxu * to not rearm the timer. 1404184067Sdavidxu */ 1405184067Sdavidxu timespecclear(&it->it_time.it_value); 1406184067Sdavidxu timespecclear(&it->it_time.it_interval); 1407164713Sdavidxu ITIMER_UNLOCK(it); 1408164713Sdavidxu callout_drain(&it->it_callout); 1409164713Sdavidxu ITIMER_LOCK(it); 1410151576Sdavidxu return (0); 1411151576Sdavidxu} 1412151576Sdavidxu 1413151576Sdavidxustatic int 1414151576Sdavidxurealtimer_gettime(struct itimer *it, struct itimerspec *ovalue) 1415151576Sdavidxu{ 1416151869Sdavidxu struct timespec cts; 1417151576Sdavidxu 1418151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1419151576Sdavidxu 1420151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1421151869Sdavidxu *ovalue = it->it_time; 1422151576Sdavidxu if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) { 1423151869Sdavidxu timespecsub(&ovalue->it_value, &cts); 1424151576Sdavidxu if (ovalue->it_value.tv_sec < 0 || 1425151576Sdavidxu (ovalue->it_value.tv_sec == 0 && 1426151576Sdavidxu ovalue->it_value.tv_nsec == 0)) { 1427151576Sdavidxu ovalue->it_value.tv_sec = 0; 1428151576Sdavidxu ovalue->it_value.tv_nsec = 1; 1429151576Sdavidxu } 1430151576Sdavidxu } 1431151576Sdavidxu return (0); 1432151576Sdavidxu} 1433151576Sdavidxu 1434151576Sdavidxustatic int 1435151576Sdavidxurealtimer_settime(struct itimer *it, int flags, 1436151576Sdavidxu struct itimerspec *value, struct itimerspec *ovalue) 1437151576Sdavidxu{ 1438151869Sdavidxu struct timespec cts, ts; 1439151869Sdavidxu struct timeval tv; 1440151869Sdavidxu struct itimerspec val; 1441151576Sdavidxu 1442151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1443151576Sdavidxu 1444151869Sdavidxu val = *value; 1445151869Sdavidxu if (itimespecfix(&val.it_value)) 1446151576Sdavidxu return (EINVAL); 1447151576Sdavidxu 1448151869Sdavidxu if (timespecisset(&val.it_value)) { 1449151869Sdavidxu if (itimespecfix(&val.it_interval)) 1450151576Sdavidxu return (EINVAL); 1451151576Sdavidxu } else { 1452151869Sdavidxu timespecclear(&val.it_interval); 1453151576Sdavidxu } 1454151576Sdavidxu 1455151576Sdavidxu if (ovalue != NULL) 1456151576Sdavidxu realtimer_gettime(it, ovalue); 1457151576Sdavidxu 1458151576Sdavidxu it->it_time = val; 1459151869Sdavidxu if (timespecisset(&val.it_value)) { 1460151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1461151869Sdavidxu ts = val.it_value; 1462151576Sdavidxu if ((flags & TIMER_ABSTIME) == 0) { 1463151576Sdavidxu /* Convert to absolute time. */ 1464151869Sdavidxu timespecadd(&it->it_time.it_value, &cts); 1465151576Sdavidxu } else { 1466151869Sdavidxu timespecsub(&ts, &cts); 1467151576Sdavidxu /* 1468151869Sdavidxu * We don't care if ts is negative, tztohz will 1469151576Sdavidxu * fix it. 1470151576Sdavidxu */ 1471151576Sdavidxu } 1472151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1473151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), 1474151576Sdavidxu realtimer_expire, it); 1475151576Sdavidxu } else { 1476151576Sdavidxu callout_stop(&it->it_callout); 1477151576Sdavidxu } 1478151576Sdavidxu 1479151576Sdavidxu return (0); 1480151576Sdavidxu} 1481151576Sdavidxu 1482151576Sdavidxustatic void 1483151869Sdavidxurealtimer_clocktime(clockid_t id, struct timespec *ts) 1484151576Sdavidxu{ 1485151576Sdavidxu if (id == CLOCK_REALTIME) 1486151869Sdavidxu getnanotime(ts); 1487151576Sdavidxu else /* CLOCK_MONOTONIC */ 1488151869Sdavidxu getnanouptime(ts); 1489151576Sdavidxu} 1490151576Sdavidxu 1491151869Sdavidxuint 1492156134Sdavidxuitimer_accept(struct proc *p, int timerid, ksiginfo_t *ksi) 1493151869Sdavidxu{ 1494151869Sdavidxu struct itimer *it; 1495151869Sdavidxu 1496151869Sdavidxu PROC_LOCK_ASSERT(p, MA_OWNED); 1497164713Sdavidxu it = itimer_find(p, timerid); 1498151869Sdavidxu if (it != NULL) { 1499151869Sdavidxu ksi->ksi_overrun = it->it_overrun; 1500151869Sdavidxu it->it_overrun_last = it->it_overrun; 1501151869Sdavidxu it->it_overrun = 0; 1502151869Sdavidxu ITIMER_UNLOCK(it); 1503151869Sdavidxu return (0); 1504151869Sdavidxu } 1505151869Sdavidxu return (EINVAL); 1506151869Sdavidxu} 1507151869Sdavidxu 1508151869Sdavidxuint 1509151869Sdavidxuitimespecfix(struct timespec *ts) 1510151869Sdavidxu{ 1511151869Sdavidxu 1512151869Sdavidxu if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) 1513151869Sdavidxu return (EINVAL); 1514151869Sdavidxu if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000) 1515151869Sdavidxu ts->tv_nsec = tick * 1000; 1516151869Sdavidxu return (0); 1517151869Sdavidxu} 1518151869Sdavidxu 1519151576Sdavidxu/* Timeout callback for realtime timer */ 1520151576Sdavidxustatic void 1521151576Sdavidxurealtimer_expire(void *arg) 1522151576Sdavidxu{ 1523151869Sdavidxu struct timespec cts, ts; 1524151869Sdavidxu struct timeval tv; 1525151576Sdavidxu struct itimer *it; 1526151576Sdavidxu 1527151576Sdavidxu it = (struct itimer *)arg; 1528151576Sdavidxu 1529151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1530151576Sdavidxu /* Only fire if time is reached. */ 1531151869Sdavidxu if (timespeccmp(&cts, &it->it_time.it_value, >=)) { 1532151869Sdavidxu if (timespecisset(&it->it_time.it_interval)) { 1533151869Sdavidxu timespecadd(&it->it_time.it_value, 1534151869Sdavidxu &it->it_time.it_interval); 1535151869Sdavidxu while (timespeccmp(&cts, &it->it_time.it_value, >=)) { 1536152983Sdavidxu if (it->it_overrun < INT_MAX) 1537152983Sdavidxu it->it_overrun++; 1538152983Sdavidxu else 1539152983Sdavidxu it->it_ksi.ksi_errno = ERANGE; 1540151869Sdavidxu timespecadd(&it->it_time.it_value, 1541151869Sdavidxu &it->it_time.it_interval); 1542151576Sdavidxu } 1543151576Sdavidxu } else { 1544151576Sdavidxu /* single shot timer ? */ 1545151869Sdavidxu timespecclear(&it->it_time.it_value); 1546151576Sdavidxu } 1547151869Sdavidxu if (timespecisset(&it->it_time.it_value)) { 1548151869Sdavidxu ts = it->it_time.it_value; 1549151869Sdavidxu timespecsub(&ts, &cts); 1550151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1551151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), 1552151576Sdavidxu realtimer_expire, it); 1553151576Sdavidxu } 1554184067Sdavidxu itimer_enter(it); 1555151576Sdavidxu ITIMER_UNLOCK(it); 1556151576Sdavidxu itimer_fire(it); 1557151576Sdavidxu ITIMER_LOCK(it); 1558184067Sdavidxu itimer_leave(it); 1559151869Sdavidxu } else if (timespecisset(&it->it_time.it_value)) { 1560151869Sdavidxu ts = it->it_time.it_value; 1561151869Sdavidxu timespecsub(&ts, &cts); 1562151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1563151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire, 1564151576Sdavidxu it); 1565151576Sdavidxu } 1566151576Sdavidxu} 1567151576Sdavidxu 1568151576Sdavidxuvoid 1569151576Sdavidxuitimer_fire(struct itimer *it) 1570151576Sdavidxu{ 1571151576Sdavidxu struct proc *p = it->it_proc; 1572213642Sdavidxu struct thread *td; 1573151576Sdavidxu 1574151869Sdavidxu if (it->it_sigev.sigev_notify == SIGEV_SIGNAL || 1575151869Sdavidxu it->it_sigev.sigev_notify == SIGEV_THREAD_ID) { 1576213642Sdavidxu if (sigev_findtd(p, &it->it_sigev, &td) != 0) { 1577213642Sdavidxu ITIMER_LOCK(it); 1578213642Sdavidxu timespecclear(&it->it_time.it_value); 1579213642Sdavidxu timespecclear(&it->it_time.it_interval); 1580213642Sdavidxu callout_stop(&it->it_callout); 1581213642Sdavidxu ITIMER_UNLOCK(it); 1582213642Sdavidxu return; 1583213642Sdavidxu } 1584151993Sdavidxu if (!KSI_ONQ(&it->it_ksi)) { 1585152983Sdavidxu it->it_ksi.ksi_errno = 0; 1586213642Sdavidxu ksiginfo_set_sigev(&it->it_ksi, &it->it_sigev); 1587213642Sdavidxu tdsendsignal(p, td, it->it_ksi.ksi_signo, &it->it_ksi); 1588151993Sdavidxu } else { 1589152983Sdavidxu if (it->it_overrun < INT_MAX) 1590152983Sdavidxu it->it_overrun++; 1591152983Sdavidxu else 1592152983Sdavidxu it->it_ksi.ksi_errno = ERANGE; 1593151576Sdavidxu } 1594151576Sdavidxu PROC_UNLOCK(p); 1595151576Sdavidxu } 1596151576Sdavidxu} 1597151576Sdavidxu 1598151576Sdavidxustatic void 1599151576Sdavidxuitimers_alloc(struct proc *p) 1600151576Sdavidxu{ 1601151585Sdavidxu struct itimers *its; 1602151585Sdavidxu int i; 1603151576Sdavidxu 1604151585Sdavidxu its = malloc(sizeof (struct itimers), M_SUBPROC, M_WAITOK | M_ZERO); 1605151585Sdavidxu LIST_INIT(&its->its_virtual); 1606151585Sdavidxu LIST_INIT(&its->its_prof); 1607151585Sdavidxu TAILQ_INIT(&its->its_worklist); 1608151585Sdavidxu for (i = 0; i < TIMER_MAX; i++) 1609151585Sdavidxu its->its_timers[i] = NULL; 1610151576Sdavidxu PROC_LOCK(p); 1611151585Sdavidxu if (p->p_itimers == NULL) { 1612151585Sdavidxu p->p_itimers = its; 1613151576Sdavidxu PROC_UNLOCK(p); 1614151585Sdavidxu } 1615151585Sdavidxu else { 1616151576Sdavidxu PROC_UNLOCK(p); 1617151585Sdavidxu free(its, M_SUBPROC); 1618151576Sdavidxu } 1619151576Sdavidxu} 1620151576Sdavidxu 1621161302Snetchildstatic void 1622161302Snetchilditimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp __unused) 1623161302Snetchild{ 1624164713Sdavidxu itimers_event_hook_exit(arg, p); 1625161302Snetchild} 1626161302Snetchild 1627151576Sdavidxu/* Clean up timers when some process events are being triggered. */ 1628153259Sdavidxustatic void 1629161302Snetchilditimers_event_hook_exit(void *arg, struct proc *p) 1630151576Sdavidxu{ 1631151576Sdavidxu struct itimers *its; 1632151576Sdavidxu struct itimer *it; 1633153267Sdavidxu int event = (int)(intptr_t)arg; 1634151576Sdavidxu int i; 1635151576Sdavidxu 1636151585Sdavidxu if (p->p_itimers != NULL) { 1637151585Sdavidxu its = p->p_itimers; 1638151576Sdavidxu for (i = 0; i < MAX_CLOCKS; ++i) { 1639151576Sdavidxu if (posix_clocks[i].event_hook != NULL) 1640151576Sdavidxu CLOCK_CALL(i, event_hook, (p, i, event)); 1641151576Sdavidxu } 1642151576Sdavidxu /* 1643151576Sdavidxu * According to susv3, XSI interval timers should be inherited 1644151576Sdavidxu * by new image. 1645151576Sdavidxu */ 1646151576Sdavidxu if (event == ITIMER_EV_EXEC) 1647151576Sdavidxu i = 3; 1648151576Sdavidxu else if (event == ITIMER_EV_EXIT) 1649151576Sdavidxu i = 0; 1650151576Sdavidxu else 1651151576Sdavidxu panic("unhandled event"); 1652151576Sdavidxu for (; i < TIMER_MAX; ++i) { 1653164713Sdavidxu if ((it = its->its_timers[i]) != NULL) 1654253530Skib kern_ktimer_delete(curthread, i); 1655151576Sdavidxu } 1656151576Sdavidxu if (its->its_timers[0] == NULL && 1657151576Sdavidxu its->its_timers[1] == NULL && 1658151576Sdavidxu its->its_timers[2] == NULL) { 1659151585Sdavidxu free(its, M_SUBPROC); 1660151585Sdavidxu p->p_itimers = NULL; 1661151576Sdavidxu } 1662151576Sdavidxu } 1663151576Sdavidxu} 1664