kern_time.c revision 239347
1139804Simp/*- 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 4. Neither the name of the University nor the names of its contributors 141541Srgrimes * may be used to endorse or promote products derived from this software 151541Srgrimes * without specific prior written permission. 161541Srgrimes * 171541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271541Srgrimes * SUCH DAMAGE. 281541Srgrimes * 291541Srgrimes * @(#)kern_time.c 8.1 (Berkeley) 6/10/93 301541Srgrimes */ 311541Srgrimes 32116182Sobrien#include <sys/cdefs.h> 33116182Sobrien__FBSDID("$FreeBSD: head/sys/kern/kern_time.c 239347 2012-08-17 02:26:31Z davidxu $"); 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> 46140483Sps#include <sys/syscallsubr.h> 47152983Sdavidxu#include <sys/sysctl.h> 4825583Speter#include <sys/sysent.h> 49164033Srwatson#include <sys/priv.h> 501541Srgrimes#include <sys/proc.h> 51164184Strhodes#include <sys/posix4.h> 5225656Speter#include <sys/time.h> 53151576Sdavidxu#include <sys/timers.h> 5458377Sphk#include <sys/timetc.h> 551541Srgrimes#include <sys/vnode.h> 5676166Smarkm 5726335Speter#include <vm/vm.h> 5826335Speter#include <vm/vm_extern.h> 591541Srgrimes 60151576Sdavidxu#define MAX_CLOCKS (CLOCK_MONOTONIC+1) 61239347Sdavidxu#define CPUCLOCK_BIT 0x80000000 62239347Sdavidxu#define CPUCLOCK_PROCESS_BIT 0x40000000 63239347Sdavidxu#define CPUCLOCK_ID_MASK (~(CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT)) 64239347Sdavidxu#define MAKE_THREAD_CPUCLOCK(tid) (CPUCLOCK_BIT|(tid)) 65239347Sdavidxu#define MAKE_PROCESS_CPUCLOCK(pid) \ 66239347Sdavidxu (CPUCLOCK_BIT|CPUCLOCK_PROCESS_BIT|(pid)) 67151576Sdavidxu 68151576Sdavidxustatic struct kclock posix_clocks[MAX_CLOCKS]; 69151576Sdavidxustatic uma_zone_t itimer_zone = NULL; 70151576Sdavidxu 718876Srgrimes/* 721541Srgrimes * Time of day and interval timer support. 731541Srgrimes * 741541Srgrimes * These routines provide the kernel entry points to get and set 751541Srgrimes * the time-of-day and per-process interval timers. Subroutines 761541Srgrimes * here provide support for adding and subtracting timeval structures 771541Srgrimes * and decrementing interval timers, optionally reloading the interval 781541Srgrimes * timers when they expire. 791541Srgrimes */ 801541Srgrimes 8194343Sjhbstatic int settime(struct thread *, struct timeval *); 8292723Salfredstatic void timevalfix(struct timeval *); 8313016Sbde 84151576Sdavidxustatic void itimer_start(void); 85151576Sdavidxustatic int itimer_init(void *, int, int); 86151576Sdavidxustatic void itimer_fini(void *, int); 87151576Sdavidxustatic void itimer_enter(struct itimer *); 88151576Sdavidxustatic void itimer_leave(struct itimer *); 89164713Sdavidxustatic struct itimer *itimer_find(struct proc *, int); 90151576Sdavidxustatic void itimers_alloc(struct proc *); 91161302Snetchildstatic void itimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp); 92161302Snetchildstatic void itimers_event_hook_exit(void *arg, struct proc *p); 93151576Sdavidxustatic int realtimer_create(struct itimer *); 94151576Sdavidxustatic int realtimer_gettime(struct itimer *, struct itimerspec *); 95151576Sdavidxustatic int realtimer_settime(struct itimer *, int, 96151576Sdavidxu struct itimerspec *, struct itimerspec *); 97151576Sdavidxustatic int realtimer_delete(struct itimer *); 98151869Sdavidxustatic void realtimer_clocktime(clockid_t, struct timespec *); 99151576Sdavidxustatic void realtimer_expire(void *); 100151576Sdavidxustatic int kern_timer_create(struct thread *, clockid_t, 101156134Sdavidxu struct sigevent *, int *, int); 102156134Sdavidxustatic int kern_timer_delete(struct thread *, int); 103151576Sdavidxu 104151576Sdavidxuint register_posix_clock(int, struct kclock *); 105151576Sdavidxuvoid itimer_fire(struct itimer *it); 106151869Sdavidxuint itimespecfix(struct timespec *ts); 107151576Sdavidxu 108151576Sdavidxu#define CLOCK_CALL(clock, call, arglist) \ 109151576Sdavidxu ((*posix_clocks[clock].call) arglist) 110151576Sdavidxu 111151576SdavidxuSYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL); 112151576Sdavidxu 113151576Sdavidxu 11425583Speterstatic int 115102074Sphksettime(struct thread *td, struct timeval *tv) 11625583Speter{ 11745433Snsayer struct timeval delta, tv1, tv2; 11845438Snsayer static struct timeval maxtime, laststep; 11933690Sphk struct timespec ts; 12025583Speter int s; 12125583Speter 12225656Speter s = splclock(); 12333818Sbde microtime(&tv1); 12435029Sphk delta = *tv; 12535029Sphk timevalsub(&delta, &tv1); 12625583Speter 12725583Speter /* 12833818Sbde * If the system is secure, we do not allow the time to be 12945433Snsayer * set to a value earlier than 1 second less than the highest 13045433Snsayer * time we have yet seen. The worst a miscreant can do in 13145433Snsayer * this circumstance is "freeze" time. He couldn't go 13245433Snsayer * back to the past. 13345438Snsayer * 13445438Snsayer * We similarly do not allow the clock to be stepped more 13545438Snsayer * than one second, nor more than once per second. This allows 13645438Snsayer * a miscreant to make the clock march double-time, but no worse. 13725583Speter */ 13894343Sjhb if (securelevel_gt(td->td_ucred, 1) != 0) { 13945433Snsayer if (delta.tv_sec < 0 || delta.tv_usec < 0) { 14045437Smjacob /* 14145438Snsayer * Update maxtime to latest time we've seen. 14245437Smjacob */ 14345437Smjacob if (tv1.tv_sec > maxtime.tv_sec) 14445437Smjacob maxtime = tv1; 14545437Smjacob tv2 = *tv; 14645437Smjacob timevalsub(&tv2, &maxtime); 14745437Smjacob if (tv2.tv_sec < -1) { 14845437Smjacob tv->tv_sec = maxtime.tv_sec - 1; 14945433Snsayer printf("Time adjustment clamped to -1 second\n"); 15045433Snsayer } 15145437Smjacob } else { 15245438Snsayer if (tv1.tv_sec == laststep.tv_sec) { 15345438Snsayer splx(s); 15445438Snsayer return (EPERM); 15545438Snsayer } 15645438Snsayer if (delta.tv_sec > 1) { 15745438Snsayer tv->tv_sec = tv1.tv_sec + 1; 15845438Snsayer printf("Time adjustment clamped to +1 second\n"); 15945438Snsayer } 16045438Snsayer laststep = *tv; 16145433Snsayer } 16233818Sbde } 16333818Sbde 16433690Sphk ts.tv_sec = tv->tv_sec; 16533690Sphk ts.tv_nsec = tv->tv_usec * 1000; 16694343Sjhb mtx_lock(&Giant); 16758377Sphk tc_setclock(&ts); 16825583Speter resettodr(); 16994343Sjhb mtx_unlock(&Giant); 17025583Speter return (0); 17125583Speter} 17225583Speter 17312221Sbde#ifndef _SYS_SYSPROTO_H_ 174239347Sdavidxustruct clock_getcpuclockid2_args { 175239347Sdavidxu id_t id; 176239347Sdavidxu int which, 177239347Sdavidxu clockid_t *clock_id; 178239347Sdavidxu}; 179239347Sdavidxu#endif 180239347Sdavidxu/* ARGSUSED */ 181239347Sdavidxuint 182239347Sdavidxusys_clock_getcpuclockid2(struct thread *td, struct clock_getcpuclockid2_args *uap) 183239347Sdavidxu{ 184239347Sdavidxu clockid_t clk_id; 185239347Sdavidxu struct proc *p; 186239347Sdavidxu pid_t pid; 187239347Sdavidxu lwpid_t tid; 188239347Sdavidxu int error; 189239347Sdavidxu 190239347Sdavidxu switch(uap->which) { 191239347Sdavidxu case CPUCLOCK_WHICH_PID: 192239347Sdavidxu if (uap->id != 0) { 193239347Sdavidxu p = pfind(uap->id); 194239347Sdavidxu if (p == NULL) 195239347Sdavidxu return (ESRCH); 196239347Sdavidxu error = p_cansee(td, p); 197239347Sdavidxu PROC_UNLOCK(p); 198239347Sdavidxu if (error) 199239347Sdavidxu return (error); 200239347Sdavidxu pid = uap->id; 201239347Sdavidxu } else { 202239347Sdavidxu pid = td->td_proc->p_pid; 203239347Sdavidxu } 204239347Sdavidxu clk_id = MAKE_PROCESS_CPUCLOCK(pid); 205239347Sdavidxu break; 206239347Sdavidxu case CPUCLOCK_WHICH_TID: 207239347Sdavidxu if (uap->id == 0) 208239347Sdavidxu tid = td->td_tid; 209239347Sdavidxu else 210239347Sdavidxu tid = uap->id; 211239347Sdavidxu clk_id = MAKE_THREAD_CPUCLOCK(tid); 212239347Sdavidxu break; 213239347Sdavidxu default: 214239347Sdavidxu return (EINVAL); 215239347Sdavidxu } 216239347Sdavidxu return (copyout(&clk_id, uap->clock_id, sizeof(clockid_t))); 217239347Sdavidxu} 218239347Sdavidxu 219239347Sdavidxu#ifndef _SYS_SYSPROTO_H_ 22025583Speterstruct clock_gettime_args { 22125583Speter clockid_t clock_id; 22225583Speter struct timespec *tp; 22325583Speter}; 22425583Speter#endif 22525583Speter/* ARGSUSED */ 22625583Speterint 227225617Skmacysys_clock_gettime(struct thread *td, struct clock_gettime_args *uap) 22825583Speter{ 22925583Speter struct timespec ats; 230151357Sps int error; 231151357Sps 232151357Sps error = kern_clock_gettime(td, uap->clock_id, &ats); 233151357Sps if (error == 0) 234151357Sps error = copyout(&ats, uap->tp, sizeof(ats)); 235151357Sps 236151357Sps return (error); 237151357Sps} 238151357Sps 239239347Sdavidxustatic inline void 240239347Sdavidxucputick2timespec(uint64_t runtime, struct timespec *ats) 241239347Sdavidxu{ 242239347Sdavidxu runtime = cputick2usec(runtime); 243239347Sdavidxu ats->tv_sec = runtime / 1000000; 244239347Sdavidxu ats->tv_nsec = runtime % 1000000 * 1000; 245239347Sdavidxu} 246239347Sdavidxu 247239347Sdavidxustatic void 248239347Sdavidxuget_thread_cputime(struct thread *targettd, struct timespec *ats) 249239347Sdavidxu{ 250239347Sdavidxu uint64_t runtime, curtime, switchtime; 251239347Sdavidxu 252239347Sdavidxu if (targettd == NULL) { /* current thread */ 253239347Sdavidxu critical_enter(); 254239347Sdavidxu switchtime = PCPU_GET(switchtime); 255239347Sdavidxu curtime = cpu_ticks(); 256239347Sdavidxu runtime = curthread->td_runtime; 257239347Sdavidxu critical_exit(); 258239347Sdavidxu runtime += curtime - switchtime; 259239347Sdavidxu } else { 260239347Sdavidxu thread_lock(targettd); 261239347Sdavidxu runtime = targettd->td_runtime; 262239347Sdavidxu thread_unlock(targettd); 263239347Sdavidxu } 264239347Sdavidxu cputick2timespec(runtime, ats); 265239347Sdavidxu} 266239347Sdavidxu 267239347Sdavidxustatic void 268239347Sdavidxuget_process_cputime(struct proc *targetp, struct timespec *ats) 269239347Sdavidxu{ 270239347Sdavidxu uint64_t runtime; 271239347Sdavidxu struct rusage ru; 272239347Sdavidxu 273239347Sdavidxu PROC_SLOCK(targetp); 274239347Sdavidxu rufetch(targetp, &ru); 275239347Sdavidxu runtime = targetp->p_rux.rux_runtime; 276239347Sdavidxu PROC_SUNLOCK(targetp); 277239347Sdavidxu cputick2timespec(runtime, ats); 278239347Sdavidxu} 279239347Sdavidxu 280239347Sdavidxustatic int 281239347Sdavidxuget_cputime(struct thread *td, clockid_t clock_id, struct timespec *ats) 282239347Sdavidxu{ 283239347Sdavidxu struct proc *p, *p2; 284239347Sdavidxu struct thread *td2; 285239347Sdavidxu lwpid_t tid; 286239347Sdavidxu pid_t pid; 287239347Sdavidxu int error; 288239347Sdavidxu 289239347Sdavidxu p = td->td_proc; 290239347Sdavidxu if ((clock_id & CPUCLOCK_PROCESS_BIT) == 0) { 291239347Sdavidxu tid = clock_id & CPUCLOCK_ID_MASK; 292239347Sdavidxu td2 = tdfind(tid, p->p_pid); 293239347Sdavidxu if (td2 == NULL) 294239347Sdavidxu return (EINVAL); 295239347Sdavidxu get_thread_cputime(td2, ats); 296239347Sdavidxu PROC_UNLOCK(td2->td_proc); 297239347Sdavidxu } else { 298239347Sdavidxu pid = clock_id & CPUCLOCK_ID_MASK; 299239347Sdavidxu p2 = pfind(pid); 300239347Sdavidxu if (p2 == NULL) 301239347Sdavidxu return (EINVAL); 302239347Sdavidxu error = p_cansee(td, p2); 303239347Sdavidxu if (error) { 304239347Sdavidxu PROC_UNLOCK(p2); 305239347Sdavidxu return (EINVAL); 306239347Sdavidxu } 307239347Sdavidxu get_process_cputime(p2, ats); 308239347Sdavidxu PROC_UNLOCK(p2); 309239347Sdavidxu } 310239347Sdavidxu return (0); 311239347Sdavidxu} 312239347Sdavidxu 313151357Spsint 314151357Spskern_clock_gettime(struct thread *td, clockid_t clock_id, struct timespec *ats) 315151357Sps{ 316130884Skbyanc struct timeval sys, user; 317136152Sjhb struct proc *p; 31825583Speter 319136152Sjhb p = td->td_proc; 320151357Sps switch (clock_id) { 321152844Srwatson case CLOCK_REALTIME: /* Default to precise. */ 322152844Srwatson case CLOCK_REALTIME_PRECISE: 323151357Sps nanotime(ats); 324130654Skbyanc break; 325152844Srwatson case CLOCK_REALTIME_FAST: 326152844Srwatson getnanotime(ats); 327152844Srwatson break; 328130654Skbyanc case CLOCK_VIRTUAL: 329136152Sjhb PROC_LOCK(p); 330170472Sattilio PROC_SLOCK(p); 331136152Sjhb calcru(p, &user, &sys); 332170472Sattilio PROC_SUNLOCK(p); 333136152Sjhb PROC_UNLOCK(p); 334151357Sps TIMEVAL_TO_TIMESPEC(&user, ats); 335130654Skbyanc break; 336130654Skbyanc case CLOCK_PROF: 337136152Sjhb PROC_LOCK(p); 338170472Sattilio PROC_SLOCK(p); 339136152Sjhb calcru(p, &user, &sys); 340170472Sattilio PROC_SUNLOCK(p); 341136152Sjhb PROC_UNLOCK(p); 342130884Skbyanc timevaladd(&user, &sys); 343151357Sps TIMEVAL_TO_TIMESPEC(&user, ats); 344130654Skbyanc break; 345152844Srwatson case CLOCK_MONOTONIC: /* Default to precise. */ 346152844Srwatson case CLOCK_MONOTONIC_PRECISE: 347152585Sandre case CLOCK_UPTIME: 348152844Srwatson case CLOCK_UPTIME_PRECISE: 349151357Sps nanouptime(ats); 350130884Skbyanc break; 351152844Srwatson case CLOCK_UPTIME_FAST: 352152844Srwatson case CLOCK_MONOTONIC_FAST: 353152844Srwatson getnanouptime(ats); 354152844Srwatson break; 355152844Srwatson case CLOCK_SECOND: 356152844Srwatson ats->tv_sec = time_second; 357152844Srwatson ats->tv_nsec = 0; 358152844Srwatson break; 359175429Sdavidxu case CLOCK_THREAD_CPUTIME_ID: 360239347Sdavidxu get_thread_cputime(NULL, ats); 361175429Sdavidxu break; 362239347Sdavidxu case CLOCK_PROCESS_CPUTIME_ID: 363239347Sdavidxu PROC_LOCK(p); 364239347Sdavidxu get_process_cputime(p, ats); 365239347Sdavidxu PROC_UNLOCK(p); 366239347Sdavidxu break; 367130654Skbyanc default: 368239347Sdavidxu if ((int)clock_id >= 0) 369239347Sdavidxu return (EINVAL); 370239347Sdavidxu return (get_cputime(td, clock_id, ats)); 371130654Skbyanc } 372151357Sps return (0); 37325583Speter} 37425583Speter 37525583Speter#ifndef _SYS_SYSPROTO_H_ 37625583Speterstruct clock_settime_args { 37725583Speter clockid_t clock_id; 37825583Speter const struct timespec *tp; 37925583Speter}; 38025583Speter#endif 38125583Speter/* ARGSUSED */ 38225583Speterint 383225617Skmacysys_clock_settime(struct thread *td, struct clock_settime_args *uap) 38425583Speter{ 38525583Speter struct timespec ats; 38625583Speter int error; 38725583Speter 388151357Sps if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0) 389151357Sps return (error); 390151357Sps return (kern_clock_settime(td, uap->clock_id, &ats)); 391151357Sps} 392151357Sps 393151357Spsint 394151357Spskern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats) 395151357Sps{ 396151357Sps struct timeval atv; 397151357Sps int error; 398151357Sps 399164033Srwatson if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) 40094343Sjhb return (error); 401151357Sps if (clock_id != CLOCK_REALTIME) 40294343Sjhb return (EINVAL); 403151357Sps if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000) 40494343Sjhb return (EINVAL); 40534901Sphk /* XXX Don't convert nsec->usec and back */ 406151357Sps TIMESPEC_TO_TIMEVAL(&atv, ats); 40794343Sjhb error = settime(td, &atv); 40882746Sdillon return (error); 40925583Speter} 41025583Speter 41125583Speter#ifndef _SYS_SYSPROTO_H_ 41225583Speterstruct clock_getres_args { 41325583Speter clockid_t clock_id; 41425583Speter struct timespec *tp; 41525583Speter}; 41625583Speter#endif 41725583Speterint 418225617Skmacysys_clock_getres(struct thread *td, struct clock_getres_args *uap) 41925583Speter{ 42025583Speter struct timespec ts; 421151357Sps int error; 42225583Speter 423151357Sps if (uap->tp == NULL) 424151357Sps return (0); 425151357Sps 426151357Sps error = kern_clock_getres(td, uap->clock_id, &ts); 427151357Sps if (error == 0) 428151357Sps error = copyout(&ts, uap->tp, sizeof(ts)); 429151357Sps return (error); 430151357Sps} 431151357Sps 432151357Spsint 433151357Spskern_clock_getres(struct thread *td, clockid_t clock_id, struct timespec *ts) 434151357Sps{ 435151357Sps 436151357Sps ts->tv_sec = 0; 437151357Sps switch (clock_id) { 438130654Skbyanc case CLOCK_REALTIME: 439152844Srwatson case CLOCK_REALTIME_FAST: 440152844Srwatson case CLOCK_REALTIME_PRECISE: 441130654Skbyanc case CLOCK_MONOTONIC: 442152844Srwatson case CLOCK_MONOTONIC_FAST: 443152844Srwatson case CLOCK_MONOTONIC_PRECISE: 444152585Sandre case CLOCK_UPTIME: 445152844Srwatson case CLOCK_UPTIME_FAST: 446152844Srwatson case CLOCK_UPTIME_PRECISE: 447103964Sbde /* 448103964Sbde * Round up the result of the division cheaply by adding 1. 449103964Sbde * Rounding up is especially important if rounding down 450103964Sbde * would give 0. Perfect rounding is unimportant. 451103964Sbde */ 452151357Sps ts->tv_nsec = 1000000000 / tc_getfrequency() + 1; 453130654Skbyanc break; 454130654Skbyanc case CLOCK_VIRTUAL: 455130654Skbyanc case CLOCK_PROF: 456130654Skbyanc /* Accurately round up here because we can do so cheaply. */ 457151357Sps ts->tv_nsec = (1000000000 + hz - 1) / hz; 458130654Skbyanc break; 459152844Srwatson case CLOCK_SECOND: 460152844Srwatson ts->tv_sec = 1; 461152844Srwatson ts->tv_nsec = 0; 462152844Srwatson break; 463175429Sdavidxu case CLOCK_THREAD_CPUTIME_ID: 464239347Sdavidxu case CLOCK_PROCESS_CPUTIME_ID: 465239347Sdavidxu cputime: 466175429Sdavidxu /* sync with cputick2usec */ 467175429Sdavidxu ts->tv_nsec = 1000000 / cpu_tickrate(); 468175429Sdavidxu if (ts->tv_nsec == 0) 469175429Sdavidxu ts->tv_nsec = 1000; 470175429Sdavidxu break; 471130654Skbyanc default: 472239347Sdavidxu if ((int)clock_id < 0) 473239347Sdavidxu goto cputime; 474130654Skbyanc return (EINVAL); 475130654Skbyanc } 476151357Sps return (0); 47725583Speter} 47825583Speter 47926335Speterstatic int nanowait; 48025656Speter 481140481Spsint 482140481Spskern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) 48325583Speter{ 48435045Sphk struct timespec ts, ts2, ts3; 48535042Sphk struct timeval tv; 48635042Sphk int error; 48725583Speter 48828773Sbde if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) 48925656Speter return (EINVAL); 49043301Sdillon if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) 49128773Sbde return (0); 49236119Sphk getnanouptime(&ts); 49335029Sphk timespecadd(&ts, rqt); 49435042Sphk TIMESPEC_TO_TIMEVAL(&tv, rqt); 49535042Sphk for (;;) { 49635042Sphk error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", 49735042Sphk tvtohz(&tv)); 49836119Sphk getnanouptime(&ts2); 49935042Sphk if (error != EWOULDBLOCK) { 50035042Sphk if (error == ERESTART) 50135042Sphk error = EINTR; 50235042Sphk if (rmt != NULL) { 50335042Sphk timespecsub(&ts, &ts2); 50435042Sphk if (ts.tv_sec < 0) 50535042Sphk timespecclear(&ts); 50635042Sphk *rmt = ts; 50735042Sphk } 50835042Sphk return (error); 50935042Sphk } 51035029Sphk if (timespeccmp(&ts2, &ts, >=)) 51135042Sphk return (0); 51235045Sphk ts3 = ts; 51335045Sphk timespecsub(&ts3, &ts2); 51435045Sphk TIMESPEC_TO_TIMEVAL(&tv, &ts3); 51526335Speter } 51626335Speter} 51725583Speter 51826335Speter#ifndef _SYS_SYSPROTO_H_ 51926335Speterstruct nanosleep_args { 52026335Speter struct timespec *rqtp; 52126335Speter struct timespec *rmtp; 52226335Speter}; 52326335Speter#endif 52426335Speter/* ARGSUSED */ 52526335Speterint 526225617Skmacysys_nanosleep(struct thread *td, struct nanosleep_args *uap) 52726335Speter{ 52826335Speter struct timespec rmt, rqt; 52982746Sdillon int error; 53026335Speter 531107849Salfred error = copyin(uap->rqtp, &rqt, sizeof(rqt)); 53226335Speter if (error) 53326335Speter return (error); 53482746Sdillon 535109521Salfred if (uap->rmtp && 536109521Salfred !useracc((caddr_t)uap->rmtp, sizeof(rmt), VM_PROT_WRITE)) 537109521Salfred return (EFAULT); 538140481Sps error = kern_nanosleep(td, &rqt, &rmt); 539107849Salfred if (error && uap->rmtp) { 54082746Sdillon int error2; 54182746Sdillon 542107849Salfred error2 = copyout(&rmt, uap->rmtp, sizeof(rmt)); 543109521Salfred if (error2) 54482746Sdillon error = error2; 54525583Speter } 54625656Speter return (error); 54725583Speter} 54825583Speter 54926335Speter#ifndef _SYS_SYSPROTO_H_ 5501541Srgrimesstruct gettimeofday_args { 5511541Srgrimes struct timeval *tp; 5521541Srgrimes struct timezone *tzp; 5531541Srgrimes}; 55412221Sbde#endif 5551541Srgrimes/* ARGSUSED */ 5561549Srgrimesint 557225617Skmacysys_gettimeofday(struct thread *td, struct gettimeofday_args *uap) 5581541Srgrimes{ 5591541Srgrimes struct timeval atv; 560110286Stjr struct timezone rtz; 5611541Srgrimes int error = 0; 5621541Srgrimes 5631541Srgrimes if (uap->tp) { 5641541Srgrimes microtime(&atv); 56599012Salfred error = copyout(&atv, uap->tp, sizeof (atv)); 5661541Srgrimes } 56790836Sphk if (error == 0 && uap->tzp != NULL) { 568110299Sphk rtz.tz_minuteswest = tz_minuteswest; 569110299Sphk rtz.tz_dsttime = tz_dsttime; 570110286Stjr error = copyout(&rtz, uap->tzp, sizeof (rtz)); 57182746Sdillon } 5721541Srgrimes return (error); 5731541Srgrimes} 5741541Srgrimes 57512221Sbde#ifndef _SYS_SYSPROTO_H_ 5761541Srgrimesstruct settimeofday_args { 5771541Srgrimes struct timeval *tv; 5781541Srgrimes struct timezone *tzp; 5791541Srgrimes}; 58012221Sbde#endif 5811541Srgrimes/* ARGSUSED */ 5821549Srgrimesint 583225617Skmacysys_settimeofday(struct thread *td, struct settimeofday_args *uap) 5841541Srgrimes{ 585144445Sjhb struct timeval atv, *tvp; 586144445Sjhb struct timezone atz, *tzp; 587144445Sjhb int error; 5881541Srgrimes 589144445Sjhb if (uap->tv) { 590144445Sjhb error = copyin(uap->tv, &atv, sizeof(atv)); 591144445Sjhb if (error) 592144445Sjhb return (error); 593144445Sjhb tvp = &atv; 594144445Sjhb } else 595144445Sjhb tvp = NULL; 596144445Sjhb if (uap->tzp) { 597144445Sjhb error = copyin(uap->tzp, &atz, sizeof(atz)); 598144445Sjhb if (error) 599144445Sjhb return (error); 600144445Sjhb tzp = &atz; 601144445Sjhb } else 602144445Sjhb tzp = NULL; 603144445Sjhb return (kern_settimeofday(td, tvp, tzp)); 604144445Sjhb} 605144445Sjhb 606144445Sjhbint 607144445Sjhbkern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp) 608144445Sjhb{ 609144445Sjhb int error; 610144445Sjhb 611164033Srwatson error = priv_check(td, PRIV_SETTIMEOFDAY); 612144445Sjhb if (error) 61394343Sjhb return (error); 6141541Srgrimes /* Verify all parameters before changing time. */ 615144445Sjhb if (tv) { 616144445Sjhb if (tv->tv_usec < 0 || tv->tv_usec >= 1000000) 61794343Sjhb return (EINVAL); 618144445Sjhb error = settime(td, tv); 61925656Speter } 620144445Sjhb if (tzp && error == 0) { 621144445Sjhb tz_minuteswest = tzp->tz_minuteswest; 622144445Sjhb tz_dsttime = tzp->tz_dsttime; 62382746Sdillon } 62482746Sdillon return (error); 6251541Srgrimes} 626144445Sjhb 62782746Sdillon/* 628167232Srwatson * Get value of an interval timer. The process virtual and profiling virtual 629167232Srwatson * time timers are kept in the p_stats area, since they can be swapped out. 630167232Srwatson * These are kept internally in the way they are specified externally: in 631167232Srwatson * time until they expire. 6321541Srgrimes * 633167232Srwatson * The real time interval timer is kept in the process table slot for the 634167232Srwatson * process, and its value (it_value) is kept as an absolute time rather than 635167232Srwatson * as a delta, so that it is easy to keep periodic real-time signals from 636167232Srwatson * drifting. 6371541Srgrimes * 6381541Srgrimes * Virtual time timers are processed in the hardclock() routine of 639167232Srwatson * kern_clock.c. The real time timer is processed by a timeout routine, 640167232Srwatson * called from the softclock() routine. Since a callout may be delayed in 641167232Srwatson * real time due to interrupt processing in the system, it is possible for 642167232Srwatson * the real time timeout routine (realitexpire, given below), to be delayed 643167232Srwatson * in real time past when it is supposed to occur. It does not suffice, 644167232Srwatson * therefore, to reload the real timer .it_value from the real time timers 645167232Srwatson * .it_interval. Rather, we compute the next time in absolute time the timer 646167232Srwatson * should go off. 6471541Srgrimes */ 64812221Sbde#ifndef _SYS_SYSPROTO_H_ 6491541Srgrimesstruct getitimer_args { 6501541Srgrimes u_int which; 6511541Srgrimes struct itimerval *itv; 6521541Srgrimes}; 65312221Sbde#endif 6541549Srgrimesint 655225617Skmacysys_getitimer(struct thread *td, struct getitimer_args *uap) 6561541Srgrimes{ 657141470Sjhb struct itimerval aitv; 658140832Ssobomax int error; 659140832Ssobomax 660140832Ssobomax error = kern_getitimer(td, uap->which, &aitv); 661140832Ssobomax if (error != 0) 662140832Ssobomax return (error); 663140832Ssobomax return (copyout(&aitv, uap->itv, sizeof (struct itimerval))); 664140832Ssobomax} 665140832Ssobomax 666140832Ssobomaxint 667140832Ssobomaxkern_getitimer(struct thread *td, u_int which, struct itimerval *aitv) 668140832Ssobomax{ 66983366Sjulian struct proc *p = td->td_proc; 67034961Sphk struct timeval ctv; 6711541Srgrimes 672140832Ssobomax if (which > ITIMER_PROF) 6731541Srgrimes return (EINVAL); 67482746Sdillon 675140832Ssobomax if (which == ITIMER_REAL) { 6761541Srgrimes /* 67736128Sbde * Convert from absolute to relative time in .it_value 6781541Srgrimes * part of real time timer. If time for real time timer 6791541Srgrimes * has passed return 0, else return difference between 6801541Srgrimes * current time and time for the timer to go off. 6811541Srgrimes */ 682111034Stjr PROC_LOCK(p); 683140832Ssobomax *aitv = p->p_realtimer; 684111034Stjr PROC_UNLOCK(p); 685140832Ssobomax if (timevalisset(&aitv->it_value)) { 68636119Sphk getmicrouptime(&ctv); 687140832Ssobomax if (timevalcmp(&aitv->it_value, &ctv, <)) 688140832Ssobomax timevalclear(&aitv->it_value); 6891541Srgrimes else 690140832Ssobomax timevalsub(&aitv->it_value, &ctv); 69134961Sphk } 69282746Sdillon } else { 693170307Sjeff PROC_SLOCK(p); 694140832Ssobomax *aitv = p->p_stats->p_timer[which]; 695170307Sjeff PROC_SUNLOCK(p); 69682746Sdillon } 697140832Ssobomax return (0); 6981541Srgrimes} 6991541Srgrimes 70012221Sbde#ifndef _SYS_SYSPROTO_H_ 7011541Srgrimesstruct setitimer_args { 7021541Srgrimes u_int which; 7031541Srgrimes struct itimerval *itv, *oitv; 7041541Srgrimes}; 70512221Sbde#endif 7061549Srgrimesint 707225617Skmacysys_setitimer(struct thread *td, struct setitimer_args *uap) 7081541Srgrimes{ 709141470Sjhb struct itimerval aitv, oitv; 710140832Ssobomax int error; 7111541Srgrimes 712111034Stjr if (uap->itv == NULL) { 713111034Stjr uap->itv = uap->oitv; 714225617Skmacy return (sys_getitimer(td, (struct getitimer_args *)uap)); 715111034Stjr } 716111034Stjr 717111034Stjr if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval)))) 7181541Srgrimes return (error); 719140832Ssobomax error = kern_setitimer(td, uap->which, &aitv, &oitv); 720140832Ssobomax if (error != 0 || uap->oitv == NULL) 721140832Ssobomax return (error); 722140832Ssobomax return (copyout(&oitv, uap->oitv, sizeof(struct itimerval))); 723140832Ssobomax} 724140832Ssobomax 725140832Ssobomaxint 726141470Sjhbkern_setitimer(struct thread *td, u_int which, struct itimerval *aitv, 727141470Sjhb struct itimerval *oitv) 728140832Ssobomax{ 729140832Ssobomax struct proc *p = td->td_proc; 730140832Ssobomax struct timeval ctv; 731140832Ssobomax 732141483Sjhb if (aitv == NULL) 733141483Sjhb return (kern_getitimer(td, which, oitv)); 734141483Sjhb 735140832Ssobomax if (which > ITIMER_PROF) 736111034Stjr return (EINVAL); 737140832Ssobomax if (itimerfix(&aitv->it_value)) 738111034Stjr return (EINVAL); 739140832Ssobomax if (!timevalisset(&aitv->it_value)) 740140832Ssobomax timevalclear(&aitv->it_interval); 741140832Ssobomax else if (itimerfix(&aitv->it_interval)) 742140832Ssobomax return (EINVAL); 74382746Sdillon 744140832Ssobomax if (which == ITIMER_REAL) { 745111034Stjr PROC_LOCK(p); 74635058Sphk if (timevalisset(&p->p_realtimer.it_value)) 74769286Sjake callout_stop(&p->p_itcallout); 748114980Sjhb getmicrouptime(&ctv); 749140832Ssobomax if (timevalisset(&aitv->it_value)) { 750140832Ssobomax callout_reset(&p->p_itcallout, tvtohz(&aitv->it_value), 75169286Sjake realitexpire, p); 752140832Ssobomax timevaladd(&aitv->it_value, &ctv); 753114980Sjhb } 754140832Ssobomax *oitv = p->p_realtimer; 755140832Ssobomax p->p_realtimer = *aitv; 756111034Stjr PROC_UNLOCK(p); 757140832Ssobomax if (timevalisset(&oitv->it_value)) { 758140832Ssobomax if (timevalcmp(&oitv->it_value, &ctv, <)) 759140832Ssobomax timevalclear(&oitv->it_value); 760111034Stjr else 761140832Ssobomax timevalsub(&oitv->it_value, &ctv); 762111034Stjr } 76382746Sdillon } else { 764170307Sjeff PROC_SLOCK(p); 765140832Ssobomax *oitv = p->p_stats->p_timer[which]; 766140832Ssobomax p->p_stats->p_timer[which] = *aitv; 767170307Sjeff PROC_SUNLOCK(p); 76882746Sdillon } 769140832Ssobomax return (0); 7701541Srgrimes} 7711541Srgrimes 7721541Srgrimes/* 7731541Srgrimes * Real interval timer expired: 7741541Srgrimes * send process whose timer expired an alarm signal. 7751541Srgrimes * If time is not set up to reload, then just return. 7761541Srgrimes * Else compute next time timer should go off which is > current time. 7771541Srgrimes * This is where delay in processing this timeout causes multiple 7781541Srgrimes * SIGALRM calls to be compressed into one. 77936127Sbde * tvtohz() always adds 1 to allow for the time until the next clock 7809327Sbde * interrupt being strictly less than 1 clock tick, but we don't want 7819327Sbde * that here since we want to appear to be in sync with the clock 7829327Sbde * interrupt even when we're delayed. 7831541Srgrimes */ 7841541Srgrimesvoid 785102074Sphkrealitexpire(void *arg) 7861541Srgrimes{ 787102074Sphk struct proc *p; 78835044Sphk struct timeval ctv, ntv; 7891541Srgrimes 7901541Srgrimes p = (struct proc *)arg; 79173916Sjhb PROC_LOCK(p); 792225617Skmacy kern_psignal(p, SIGALRM); 79335058Sphk if (!timevalisset(&p->p_realtimer.it_interval)) { 79435058Sphk timevalclear(&p->p_realtimer.it_value); 795116123Sjhb if (p->p_flag & P_WEXIT) 796116123Sjhb wakeup(&p->p_itcallout); 79773916Sjhb PROC_UNLOCK(p); 7981541Srgrimes return; 7991541Srgrimes } 8001541Srgrimes for (;;) { 8011541Srgrimes timevaladd(&p->p_realtimer.it_value, 8021541Srgrimes &p->p_realtimer.it_interval); 80336119Sphk getmicrouptime(&ctv); 80435058Sphk if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) { 80535044Sphk ntv = p->p_realtimer.it_value; 80635044Sphk timevalsub(&ntv, &ctv); 80769286Sjake callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1, 80869286Sjake realitexpire, p); 80973916Sjhb PROC_UNLOCK(p); 8101541Srgrimes return; 8111541Srgrimes } 8121541Srgrimes } 81373916Sjhb /*NOTREACHED*/ 8141541Srgrimes} 8151541Srgrimes 8161541Srgrimes/* 8171541Srgrimes * Check that a proposed value to load into the .it_value or 8181541Srgrimes * .it_interval part of an interval timer is acceptable, and 8191541Srgrimes * fix it to have at least minimal value (i.e. if it is less 8201541Srgrimes * than the resolution of the clock, round it up.) 8211541Srgrimes */ 8221549Srgrimesint 823102074Sphkitimerfix(struct timeval *tv) 8241541Srgrimes{ 8251541Srgrimes 826151576Sdavidxu if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) 8271541Srgrimes return (EINVAL); 8281541Srgrimes if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 8291541Srgrimes tv->tv_usec = tick; 8301541Srgrimes return (0); 8311541Srgrimes} 8321541Srgrimes 8331541Srgrimes/* 8341541Srgrimes * Decrement an interval timer by a specified number 8351541Srgrimes * of microseconds, which must be less than a second, 8361541Srgrimes * i.e. < 1000000. If the timer expires, then reload 8371541Srgrimes * it. In this case, carry over (usec - old value) to 8381541Srgrimes * reduce the value reloaded into the timer so that 8391541Srgrimes * the timer does not drift. This routine assumes 8401541Srgrimes * that it is called in a context where the timers 8411541Srgrimes * on which it is operating cannot change in value. 8421541Srgrimes */ 8431549Srgrimesint 844102074Sphkitimerdecr(struct itimerval *itp, int usec) 8451541Srgrimes{ 8461541Srgrimes 8471541Srgrimes if (itp->it_value.tv_usec < usec) { 8481541Srgrimes if (itp->it_value.tv_sec == 0) { 8491541Srgrimes /* expired, and already in next interval */ 8501541Srgrimes usec -= itp->it_value.tv_usec; 8511541Srgrimes goto expire; 8521541Srgrimes } 8531541Srgrimes itp->it_value.tv_usec += 1000000; 8541541Srgrimes itp->it_value.tv_sec--; 8551541Srgrimes } 8561541Srgrimes itp->it_value.tv_usec -= usec; 8571541Srgrimes usec = 0; 85835058Sphk if (timevalisset(&itp->it_value)) 8591541Srgrimes return (1); 8601541Srgrimes /* expired, exactly at end of interval */ 8611541Srgrimesexpire: 86235058Sphk if (timevalisset(&itp->it_interval)) { 8631541Srgrimes itp->it_value = itp->it_interval; 8641541Srgrimes itp->it_value.tv_usec -= usec; 8651541Srgrimes if (itp->it_value.tv_usec < 0) { 8661541Srgrimes itp->it_value.tv_usec += 1000000; 8671541Srgrimes itp->it_value.tv_sec--; 8681541Srgrimes } 8691541Srgrimes } else 8701541Srgrimes itp->it_value.tv_usec = 0; /* sec is already 0 */ 8711541Srgrimes return (0); 8721541Srgrimes} 8731541Srgrimes 8741541Srgrimes/* 8751541Srgrimes * Add and subtract routines for timevals. 8761541Srgrimes * N.B.: subtract routine doesn't deal with 8771541Srgrimes * results which are before the beginning, 8781541Srgrimes * it just gets very confused in this case. 8791541Srgrimes * Caveat emptor. 8801541Srgrimes */ 8811549Srgrimesvoid 882121523Salfredtimevaladd(struct timeval *t1, const struct timeval *t2) 8831541Srgrimes{ 8841541Srgrimes 8851541Srgrimes t1->tv_sec += t2->tv_sec; 8861541Srgrimes t1->tv_usec += t2->tv_usec; 8871541Srgrimes timevalfix(t1); 8881541Srgrimes} 8891541Srgrimes 8901549Srgrimesvoid 891121523Salfredtimevalsub(struct timeval *t1, const struct timeval *t2) 8921541Srgrimes{ 8931541Srgrimes 8941541Srgrimes t1->tv_sec -= t2->tv_sec; 8951541Srgrimes t1->tv_usec -= t2->tv_usec; 8961541Srgrimes timevalfix(t1); 8971541Srgrimes} 8981541Srgrimes 89912819Sphkstatic void 900102074Sphktimevalfix(struct timeval *t1) 9011541Srgrimes{ 9021541Srgrimes 9031541Srgrimes if (t1->tv_usec < 0) { 9041541Srgrimes t1->tv_sec--; 9051541Srgrimes t1->tv_usec += 1000000; 9061541Srgrimes } 9071541Srgrimes if (t1->tv_usec >= 1000000) { 9081541Srgrimes t1->tv_sec++; 9091541Srgrimes t1->tv_usec -= 1000000; 9101541Srgrimes } 9111541Srgrimes} 912108142Ssam 913108142Ssam/* 914108511Ssam * ratecheck(): simple time-based rate-limit checking. 915108142Ssam */ 916108142Ssamint 917108142Ssamratecheck(struct timeval *lasttime, const struct timeval *mininterval) 918108142Ssam{ 919108142Ssam struct timeval tv, delta; 920108142Ssam int rv = 0; 921108142Ssam 922108511Ssam getmicrouptime(&tv); /* NB: 10ms precision */ 923108511Ssam delta = tv; 924108511Ssam timevalsub(&delta, lasttime); 925108142Ssam 926108142Ssam /* 927108142Ssam * check for 0,0 is so that the message will be seen at least once, 928108142Ssam * even if interval is huge. 929108142Ssam */ 930108142Ssam if (timevalcmp(&delta, mininterval, >=) || 931108142Ssam (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 932108142Ssam *lasttime = tv; 933108142Ssam rv = 1; 934108142Ssam } 935108142Ssam 936108142Ssam return (rv); 937108142Ssam} 938108142Ssam 939108142Ssam/* 940108142Ssam * ppsratecheck(): packets (or events) per second limitation. 941108511Ssam * 942108511Ssam * Return 0 if the limit is to be enforced (e.g. the caller 943108511Ssam * should drop a packet because of the rate limitation). 944108511Ssam * 945111558Ssam * maxpps of 0 always causes zero to be returned. maxpps of -1 946111558Ssam * always causes 1 to be returned; this effectively defeats rate 947111558Ssam * limiting. 948111558Ssam * 949108511Ssam * Note that we maintain the struct timeval for compatibility 950108511Ssam * with other bsd systems. We reuse the storage and just monitor 951108511Ssam * clock ticks for minimal overhead. 952108142Ssam */ 953108142Ssamint 954108142Ssamppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 955108142Ssam{ 956108511Ssam int now; 957108142Ssam 958108142Ssam /* 959108511Ssam * Reset the last time and counter if this is the first call 960108511Ssam * or more than a second has passed since the last update of 961108511Ssam * lasttime. 962108142Ssam */ 963108511Ssam now = ticks; 964108511Ssam if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) { 965108511Ssam lasttime->tv_sec = now; 966108511Ssam *curpps = 1; 967111558Ssam return (maxpps != 0); 968108511Ssam } else { 969108511Ssam (*curpps)++; /* NB: ignore potential overflow */ 970108511Ssam return (maxpps < 0 || *curpps < maxpps); 971108511Ssam } 972108142Ssam} 973151576Sdavidxu 974151576Sdavidxustatic void 975151576Sdavidxuitimer_start(void) 976151576Sdavidxu{ 977151576Sdavidxu struct kclock rt_clock = { 978151576Sdavidxu .timer_create = realtimer_create, 979151576Sdavidxu .timer_delete = realtimer_delete, 980151576Sdavidxu .timer_settime = realtimer_settime, 981151576Sdavidxu .timer_gettime = realtimer_gettime, 982164713Sdavidxu .event_hook = NULL 983151576Sdavidxu }; 984151576Sdavidxu 985151576Sdavidxu itimer_zone = uma_zcreate("itimer", sizeof(struct itimer), 986151576Sdavidxu NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0); 987151576Sdavidxu register_posix_clock(CLOCK_REALTIME, &rt_clock); 988151576Sdavidxu register_posix_clock(CLOCK_MONOTONIC, &rt_clock); 989152983Sdavidxu p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L); 990152983Sdavidxu p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX); 991152983Sdavidxu p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX); 992161302Snetchild EVENTHANDLER_REGISTER(process_exit, itimers_event_hook_exit, 993153259Sdavidxu (void *)ITIMER_EV_EXIT, EVENTHANDLER_PRI_ANY); 994161302Snetchild EVENTHANDLER_REGISTER(process_exec, itimers_event_hook_exec, 995153259Sdavidxu (void *)ITIMER_EV_EXEC, EVENTHANDLER_PRI_ANY); 996151576Sdavidxu} 997151576Sdavidxu 998151576Sdavidxuint 999151576Sdavidxuregister_posix_clock(int clockid, struct kclock *clk) 1000151576Sdavidxu{ 1001151576Sdavidxu if ((unsigned)clockid >= MAX_CLOCKS) { 1002151576Sdavidxu printf("%s: invalid clockid\n", __func__); 1003151576Sdavidxu return (0); 1004151576Sdavidxu } 1005151576Sdavidxu posix_clocks[clockid] = *clk; 1006151576Sdavidxu return (1); 1007151576Sdavidxu} 1008151576Sdavidxu 1009151576Sdavidxustatic int 1010151576Sdavidxuitimer_init(void *mem, int size, int flags) 1011151576Sdavidxu{ 1012151576Sdavidxu struct itimer *it; 1013151576Sdavidxu 1014151576Sdavidxu it = (struct itimer *)mem; 1015151576Sdavidxu mtx_init(&it->it_mtx, "itimer lock", NULL, MTX_DEF); 1016151576Sdavidxu return (0); 1017151576Sdavidxu} 1018151576Sdavidxu 1019151576Sdavidxustatic void 1020151576Sdavidxuitimer_fini(void *mem, int size) 1021151576Sdavidxu{ 1022151576Sdavidxu struct itimer *it; 1023151576Sdavidxu 1024151576Sdavidxu it = (struct itimer *)mem; 1025151576Sdavidxu mtx_destroy(&it->it_mtx); 1026151576Sdavidxu} 1027151576Sdavidxu 1028151576Sdavidxustatic void 1029151576Sdavidxuitimer_enter(struct itimer *it) 1030151576Sdavidxu{ 1031151576Sdavidxu 1032151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1033151576Sdavidxu it->it_usecount++; 1034151576Sdavidxu} 1035151576Sdavidxu 1036151576Sdavidxustatic void 1037151576Sdavidxuitimer_leave(struct itimer *it) 1038151576Sdavidxu{ 1039151576Sdavidxu 1040151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1041151576Sdavidxu KASSERT(it->it_usecount > 0, ("invalid it_usecount")); 1042151576Sdavidxu 1043151576Sdavidxu if (--it->it_usecount == 0 && (it->it_flags & ITF_WANTED) != 0) 1044151576Sdavidxu wakeup(it); 1045151576Sdavidxu} 1046151576Sdavidxu 1047151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1048156134Sdavidxustruct ktimer_create_args { 1049151576Sdavidxu clockid_t clock_id; 1050151576Sdavidxu struct sigevent * evp; 1051156134Sdavidxu int * timerid; 1052151576Sdavidxu}; 1053151576Sdavidxu#endif 1054151576Sdavidxuint 1055225617Skmacysys_ktimer_create(struct thread *td, struct ktimer_create_args *uap) 1056151576Sdavidxu{ 1057151576Sdavidxu struct sigevent *evp1, ev; 1058156134Sdavidxu int id; 1059151576Sdavidxu int error; 1060151576Sdavidxu 1061151576Sdavidxu if (uap->evp != NULL) { 1062151576Sdavidxu error = copyin(uap->evp, &ev, sizeof(ev)); 1063151576Sdavidxu if (error != 0) 1064151576Sdavidxu return (error); 1065151576Sdavidxu evp1 = &ev; 1066151576Sdavidxu } else 1067151576Sdavidxu evp1 = NULL; 1068151576Sdavidxu 1069151576Sdavidxu error = kern_timer_create(td, uap->clock_id, evp1, &id, -1); 1070151576Sdavidxu 1071151576Sdavidxu if (error == 0) { 1072156134Sdavidxu error = copyout(&id, uap->timerid, sizeof(int)); 1073151576Sdavidxu if (error != 0) 1074151576Sdavidxu kern_timer_delete(td, id); 1075151576Sdavidxu } 1076151576Sdavidxu return (error); 1077151576Sdavidxu} 1078151576Sdavidxu 1079151576Sdavidxustatic int 1080151576Sdavidxukern_timer_create(struct thread *td, clockid_t clock_id, 1081156134Sdavidxu struct sigevent *evp, int *timerid, int preset_id) 1082151576Sdavidxu{ 1083151576Sdavidxu struct proc *p = td->td_proc; 1084151576Sdavidxu struct itimer *it; 1085151576Sdavidxu int id; 1086151576Sdavidxu int error; 1087151576Sdavidxu 1088151576Sdavidxu if (clock_id < 0 || clock_id >= MAX_CLOCKS) 1089151576Sdavidxu return (EINVAL); 1090151576Sdavidxu 1091151576Sdavidxu if (posix_clocks[clock_id].timer_create == NULL) 1092151576Sdavidxu return (EINVAL); 1093151576Sdavidxu 1094151576Sdavidxu if (evp != NULL) { 1095151576Sdavidxu if (evp->sigev_notify != SIGEV_NONE && 1096151869Sdavidxu evp->sigev_notify != SIGEV_SIGNAL && 1097151869Sdavidxu evp->sigev_notify != SIGEV_THREAD_ID) 1098151576Sdavidxu return (EINVAL); 1099151869Sdavidxu if ((evp->sigev_notify == SIGEV_SIGNAL || 1100151869Sdavidxu evp->sigev_notify == SIGEV_THREAD_ID) && 1101151576Sdavidxu !_SIG_VALID(evp->sigev_signo)) 1102151576Sdavidxu return (EINVAL); 1103151576Sdavidxu } 1104151576Sdavidxu 1105151585Sdavidxu if (p->p_itimers == NULL) 1106151576Sdavidxu itimers_alloc(p); 1107151576Sdavidxu 1108151576Sdavidxu it = uma_zalloc(itimer_zone, M_WAITOK); 1109151576Sdavidxu it->it_flags = 0; 1110151576Sdavidxu it->it_usecount = 0; 1111151576Sdavidxu it->it_active = 0; 1112151869Sdavidxu timespecclear(&it->it_time.it_value); 1113151869Sdavidxu timespecclear(&it->it_time.it_interval); 1114151576Sdavidxu it->it_overrun = 0; 1115151576Sdavidxu it->it_overrun_last = 0; 1116151576Sdavidxu it->it_clockid = clock_id; 1117151576Sdavidxu it->it_timerid = -1; 1118151576Sdavidxu it->it_proc = p; 1119151576Sdavidxu ksiginfo_init(&it->it_ksi); 1120151576Sdavidxu it->it_ksi.ksi_flags |= KSI_INS | KSI_EXT; 1121151576Sdavidxu error = CLOCK_CALL(clock_id, timer_create, (it)); 1122151576Sdavidxu if (error != 0) 1123151576Sdavidxu goto out; 1124151576Sdavidxu 1125151576Sdavidxu PROC_LOCK(p); 1126151576Sdavidxu if (preset_id != -1) { 1127151576Sdavidxu KASSERT(preset_id >= 0 && preset_id < 3, ("invalid preset_id")); 1128151576Sdavidxu id = preset_id; 1129151585Sdavidxu if (p->p_itimers->its_timers[id] != NULL) { 1130151576Sdavidxu PROC_UNLOCK(p); 1131151576Sdavidxu error = 0; 1132151576Sdavidxu goto out; 1133151576Sdavidxu } 1134151576Sdavidxu } else { 1135151576Sdavidxu /* 1136151576Sdavidxu * Find a free timer slot, skipping those reserved 1137151576Sdavidxu * for setitimer(). 1138151576Sdavidxu */ 1139151576Sdavidxu for (id = 3; id < TIMER_MAX; id++) 1140151585Sdavidxu if (p->p_itimers->its_timers[id] == NULL) 1141151576Sdavidxu break; 1142151576Sdavidxu if (id == TIMER_MAX) { 1143151576Sdavidxu PROC_UNLOCK(p); 1144151576Sdavidxu error = EAGAIN; 1145151576Sdavidxu goto out; 1146151576Sdavidxu } 1147151576Sdavidxu } 1148151576Sdavidxu it->it_timerid = id; 1149151585Sdavidxu p->p_itimers->its_timers[id] = it; 1150151576Sdavidxu if (evp != NULL) 1151151576Sdavidxu it->it_sigev = *evp; 1152151576Sdavidxu else { 1153151576Sdavidxu it->it_sigev.sigev_notify = SIGEV_SIGNAL; 1154151576Sdavidxu switch (clock_id) { 1155151576Sdavidxu default: 1156151576Sdavidxu case CLOCK_REALTIME: 1157151576Sdavidxu it->it_sigev.sigev_signo = SIGALRM; 1158151576Sdavidxu break; 1159151576Sdavidxu case CLOCK_VIRTUAL: 1160151576Sdavidxu it->it_sigev.sigev_signo = SIGVTALRM; 1161151576Sdavidxu break; 1162151576Sdavidxu case CLOCK_PROF: 1163151576Sdavidxu it->it_sigev.sigev_signo = SIGPROF; 1164151576Sdavidxu break; 1165151576Sdavidxu } 1166152029Sdavidxu it->it_sigev.sigev_value.sival_int = id; 1167151576Sdavidxu } 1168151576Sdavidxu 1169151869Sdavidxu if (it->it_sigev.sigev_notify == SIGEV_SIGNAL || 1170151869Sdavidxu it->it_sigev.sigev_notify == SIGEV_THREAD_ID) { 1171151576Sdavidxu it->it_ksi.ksi_signo = it->it_sigev.sigev_signo; 1172151576Sdavidxu it->it_ksi.ksi_code = SI_TIMER; 1173151576Sdavidxu it->it_ksi.ksi_value = it->it_sigev.sigev_value; 1174151576Sdavidxu it->it_ksi.ksi_timerid = id; 1175151576Sdavidxu } 1176151576Sdavidxu PROC_UNLOCK(p); 1177151576Sdavidxu *timerid = id; 1178151576Sdavidxu return (0); 1179151576Sdavidxu 1180151576Sdavidxuout: 1181151576Sdavidxu ITIMER_LOCK(it); 1182151576Sdavidxu CLOCK_CALL(it->it_clockid, timer_delete, (it)); 1183151576Sdavidxu ITIMER_UNLOCK(it); 1184151576Sdavidxu uma_zfree(itimer_zone, it); 1185151576Sdavidxu return (error); 1186151576Sdavidxu} 1187151576Sdavidxu 1188151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1189156134Sdavidxustruct ktimer_delete_args { 1190156134Sdavidxu int timerid; 1191151576Sdavidxu}; 1192151576Sdavidxu#endif 1193151576Sdavidxuint 1194225617Skmacysys_ktimer_delete(struct thread *td, struct ktimer_delete_args *uap) 1195151576Sdavidxu{ 1196151576Sdavidxu return (kern_timer_delete(td, uap->timerid)); 1197151576Sdavidxu} 1198151576Sdavidxu 1199151576Sdavidxustatic struct itimer * 1200164713Sdavidxuitimer_find(struct proc *p, int timerid) 1201151576Sdavidxu{ 1202151576Sdavidxu struct itimer *it; 1203151576Sdavidxu 1204151576Sdavidxu PROC_LOCK_ASSERT(p, MA_OWNED); 1205190301Scperciva if ((p->p_itimers == NULL) || 1206190301Scperciva (timerid < 0) || (timerid >= TIMER_MAX) || 1207151585Sdavidxu (it = p->p_itimers->its_timers[timerid]) == NULL) { 1208151576Sdavidxu return (NULL); 1209151576Sdavidxu } 1210151576Sdavidxu ITIMER_LOCK(it); 1211164713Sdavidxu if ((it->it_flags & ITF_DELETING) != 0) { 1212151576Sdavidxu ITIMER_UNLOCK(it); 1213151576Sdavidxu it = NULL; 1214151576Sdavidxu } 1215151576Sdavidxu return (it); 1216151576Sdavidxu} 1217151576Sdavidxu 1218151576Sdavidxustatic int 1219156134Sdavidxukern_timer_delete(struct thread *td, int timerid) 1220151576Sdavidxu{ 1221151576Sdavidxu struct proc *p = td->td_proc; 1222151576Sdavidxu struct itimer *it; 1223151576Sdavidxu 1224151576Sdavidxu PROC_LOCK(p); 1225164713Sdavidxu it = itimer_find(p, timerid); 1226151576Sdavidxu if (it == NULL) { 1227151576Sdavidxu PROC_UNLOCK(p); 1228151576Sdavidxu return (EINVAL); 1229151576Sdavidxu } 1230151576Sdavidxu PROC_UNLOCK(p); 1231151576Sdavidxu 1232151576Sdavidxu it->it_flags |= ITF_DELETING; 1233151576Sdavidxu while (it->it_usecount > 0) { 1234151576Sdavidxu it->it_flags |= ITF_WANTED; 1235151576Sdavidxu msleep(it, &it->it_mtx, PPAUSE, "itimer", 0); 1236151576Sdavidxu } 1237151576Sdavidxu it->it_flags &= ~ITF_WANTED; 1238151576Sdavidxu CLOCK_CALL(it->it_clockid, timer_delete, (it)); 1239151576Sdavidxu ITIMER_UNLOCK(it); 1240151576Sdavidxu 1241151576Sdavidxu PROC_LOCK(p); 1242151576Sdavidxu if (KSI_ONQ(&it->it_ksi)) 1243151576Sdavidxu sigqueue_take(&it->it_ksi); 1244151585Sdavidxu p->p_itimers->its_timers[timerid] = NULL; 1245151576Sdavidxu PROC_UNLOCK(p); 1246151576Sdavidxu uma_zfree(itimer_zone, it); 1247151576Sdavidxu return (0); 1248151576Sdavidxu} 1249151576Sdavidxu 1250151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1251156134Sdavidxustruct ktimer_settime_args { 1252156134Sdavidxu int timerid; 1253151576Sdavidxu int flags; 1254151576Sdavidxu const struct itimerspec * value; 1255151576Sdavidxu struct itimerspec * ovalue; 1256151576Sdavidxu}; 1257151576Sdavidxu#endif 1258151576Sdavidxuint 1259225617Skmacysys_ktimer_settime(struct thread *td, struct ktimer_settime_args *uap) 1260151576Sdavidxu{ 1261151576Sdavidxu struct proc *p = td->td_proc; 1262151576Sdavidxu struct itimer *it; 1263151576Sdavidxu struct itimerspec val, oval, *ovalp; 1264151576Sdavidxu int error; 1265151576Sdavidxu 1266151576Sdavidxu error = copyin(uap->value, &val, sizeof(val)); 1267151576Sdavidxu if (error != 0) 1268151576Sdavidxu return (error); 1269151576Sdavidxu 1270151576Sdavidxu if (uap->ovalue != NULL) 1271151576Sdavidxu ovalp = &oval; 1272151576Sdavidxu else 1273151576Sdavidxu ovalp = NULL; 1274151576Sdavidxu 1275151576Sdavidxu PROC_LOCK(p); 1276151576Sdavidxu if (uap->timerid < 3 || 1277164713Sdavidxu (it = itimer_find(p, uap->timerid)) == NULL) { 1278151576Sdavidxu PROC_UNLOCK(p); 1279151576Sdavidxu error = EINVAL; 1280151576Sdavidxu } else { 1281151576Sdavidxu PROC_UNLOCK(p); 1282151576Sdavidxu itimer_enter(it); 1283151576Sdavidxu error = CLOCK_CALL(it->it_clockid, timer_settime, 1284151576Sdavidxu (it, uap->flags, &val, ovalp)); 1285151576Sdavidxu itimer_leave(it); 1286151576Sdavidxu ITIMER_UNLOCK(it); 1287151576Sdavidxu } 1288151576Sdavidxu if (error == 0 && uap->ovalue != NULL) 1289151576Sdavidxu error = copyout(ovalp, uap->ovalue, sizeof(*ovalp)); 1290151576Sdavidxu return (error); 1291151576Sdavidxu} 1292151576Sdavidxu 1293151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1294156134Sdavidxustruct ktimer_gettime_args { 1295156134Sdavidxu int timerid; 1296151576Sdavidxu struct itimerspec * value; 1297151576Sdavidxu}; 1298151576Sdavidxu#endif 1299151576Sdavidxuint 1300225617Skmacysys_ktimer_gettime(struct thread *td, struct ktimer_gettime_args *uap) 1301151576Sdavidxu{ 1302151576Sdavidxu struct proc *p = td->td_proc; 1303151576Sdavidxu struct itimer *it; 1304151576Sdavidxu struct itimerspec val; 1305151576Sdavidxu int error; 1306151576Sdavidxu 1307151576Sdavidxu PROC_LOCK(p); 1308151576Sdavidxu if (uap->timerid < 3 || 1309164713Sdavidxu (it = itimer_find(p, uap->timerid)) == NULL) { 1310151576Sdavidxu PROC_UNLOCK(p); 1311151576Sdavidxu error = EINVAL; 1312151576Sdavidxu } else { 1313151576Sdavidxu PROC_UNLOCK(p); 1314151576Sdavidxu itimer_enter(it); 1315151576Sdavidxu error = CLOCK_CALL(it->it_clockid, timer_gettime, 1316151576Sdavidxu (it, &val)); 1317151576Sdavidxu itimer_leave(it); 1318151576Sdavidxu ITIMER_UNLOCK(it); 1319151576Sdavidxu } 1320151576Sdavidxu if (error == 0) 1321151576Sdavidxu error = copyout(&val, uap->value, sizeof(val)); 1322151576Sdavidxu return (error); 1323151576Sdavidxu} 1324151576Sdavidxu 1325151576Sdavidxu#ifndef _SYS_SYSPROTO_H_ 1326151576Sdavidxustruct timer_getoverrun_args { 1327156134Sdavidxu int timerid; 1328151576Sdavidxu}; 1329151576Sdavidxu#endif 1330151576Sdavidxuint 1331225617Skmacysys_ktimer_getoverrun(struct thread *td, struct ktimer_getoverrun_args *uap) 1332151576Sdavidxu{ 1333151576Sdavidxu struct proc *p = td->td_proc; 1334151576Sdavidxu struct itimer *it; 1335151576Sdavidxu int error ; 1336151576Sdavidxu 1337151576Sdavidxu PROC_LOCK(p); 1338151576Sdavidxu if (uap->timerid < 3 || 1339164713Sdavidxu (it = itimer_find(p, uap->timerid)) == NULL) { 1340151576Sdavidxu PROC_UNLOCK(p); 1341151576Sdavidxu error = EINVAL; 1342151576Sdavidxu } else { 1343151576Sdavidxu td->td_retval[0] = it->it_overrun_last; 1344151576Sdavidxu ITIMER_UNLOCK(it); 1345151869Sdavidxu PROC_UNLOCK(p); 1346151576Sdavidxu error = 0; 1347151576Sdavidxu } 1348151576Sdavidxu return (error); 1349151576Sdavidxu} 1350151576Sdavidxu 1351151576Sdavidxustatic int 1352151576Sdavidxurealtimer_create(struct itimer *it) 1353151576Sdavidxu{ 1354151576Sdavidxu callout_init_mtx(&it->it_callout, &it->it_mtx, 0); 1355151576Sdavidxu return (0); 1356151576Sdavidxu} 1357151576Sdavidxu 1358151576Sdavidxustatic int 1359151576Sdavidxurealtimer_delete(struct itimer *it) 1360151576Sdavidxu{ 1361151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1362164713Sdavidxu 1363184067Sdavidxu /* 1364184067Sdavidxu * clear timer's value and interval to tell realtimer_expire 1365184067Sdavidxu * to not rearm the timer. 1366184067Sdavidxu */ 1367184067Sdavidxu timespecclear(&it->it_time.it_value); 1368184067Sdavidxu timespecclear(&it->it_time.it_interval); 1369164713Sdavidxu ITIMER_UNLOCK(it); 1370164713Sdavidxu callout_drain(&it->it_callout); 1371164713Sdavidxu ITIMER_LOCK(it); 1372151576Sdavidxu return (0); 1373151576Sdavidxu} 1374151576Sdavidxu 1375151576Sdavidxustatic int 1376151576Sdavidxurealtimer_gettime(struct itimer *it, struct itimerspec *ovalue) 1377151576Sdavidxu{ 1378151869Sdavidxu struct timespec cts; 1379151576Sdavidxu 1380151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1381151576Sdavidxu 1382151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1383151869Sdavidxu *ovalue = it->it_time; 1384151576Sdavidxu if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) { 1385151869Sdavidxu timespecsub(&ovalue->it_value, &cts); 1386151576Sdavidxu if (ovalue->it_value.tv_sec < 0 || 1387151576Sdavidxu (ovalue->it_value.tv_sec == 0 && 1388151576Sdavidxu ovalue->it_value.tv_nsec == 0)) { 1389151576Sdavidxu ovalue->it_value.tv_sec = 0; 1390151576Sdavidxu ovalue->it_value.tv_nsec = 1; 1391151576Sdavidxu } 1392151576Sdavidxu } 1393151576Sdavidxu return (0); 1394151576Sdavidxu} 1395151576Sdavidxu 1396151576Sdavidxustatic int 1397151576Sdavidxurealtimer_settime(struct itimer *it, int flags, 1398151576Sdavidxu struct itimerspec *value, struct itimerspec *ovalue) 1399151576Sdavidxu{ 1400151869Sdavidxu struct timespec cts, ts; 1401151869Sdavidxu struct timeval tv; 1402151869Sdavidxu struct itimerspec val; 1403151576Sdavidxu 1404151576Sdavidxu mtx_assert(&it->it_mtx, MA_OWNED); 1405151576Sdavidxu 1406151869Sdavidxu val = *value; 1407151869Sdavidxu if (itimespecfix(&val.it_value)) 1408151576Sdavidxu return (EINVAL); 1409151576Sdavidxu 1410151869Sdavidxu if (timespecisset(&val.it_value)) { 1411151869Sdavidxu if (itimespecfix(&val.it_interval)) 1412151576Sdavidxu return (EINVAL); 1413151576Sdavidxu } else { 1414151869Sdavidxu timespecclear(&val.it_interval); 1415151576Sdavidxu } 1416151576Sdavidxu 1417151576Sdavidxu if (ovalue != NULL) 1418151576Sdavidxu realtimer_gettime(it, ovalue); 1419151576Sdavidxu 1420151576Sdavidxu it->it_time = val; 1421151869Sdavidxu if (timespecisset(&val.it_value)) { 1422151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1423151869Sdavidxu ts = val.it_value; 1424151576Sdavidxu if ((flags & TIMER_ABSTIME) == 0) { 1425151576Sdavidxu /* Convert to absolute time. */ 1426151869Sdavidxu timespecadd(&it->it_time.it_value, &cts); 1427151576Sdavidxu } else { 1428151869Sdavidxu timespecsub(&ts, &cts); 1429151576Sdavidxu /* 1430151869Sdavidxu * We don't care if ts is negative, tztohz will 1431151576Sdavidxu * fix it. 1432151576Sdavidxu */ 1433151576Sdavidxu } 1434151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1435151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), 1436151576Sdavidxu realtimer_expire, it); 1437151576Sdavidxu } else { 1438151576Sdavidxu callout_stop(&it->it_callout); 1439151576Sdavidxu } 1440151576Sdavidxu 1441151576Sdavidxu return (0); 1442151576Sdavidxu} 1443151576Sdavidxu 1444151576Sdavidxustatic void 1445151869Sdavidxurealtimer_clocktime(clockid_t id, struct timespec *ts) 1446151576Sdavidxu{ 1447151576Sdavidxu if (id == CLOCK_REALTIME) 1448151869Sdavidxu getnanotime(ts); 1449151576Sdavidxu else /* CLOCK_MONOTONIC */ 1450151869Sdavidxu getnanouptime(ts); 1451151576Sdavidxu} 1452151576Sdavidxu 1453151869Sdavidxuint 1454156134Sdavidxuitimer_accept(struct proc *p, int timerid, ksiginfo_t *ksi) 1455151869Sdavidxu{ 1456151869Sdavidxu struct itimer *it; 1457151869Sdavidxu 1458151869Sdavidxu PROC_LOCK_ASSERT(p, MA_OWNED); 1459164713Sdavidxu it = itimer_find(p, timerid); 1460151869Sdavidxu if (it != NULL) { 1461151869Sdavidxu ksi->ksi_overrun = it->it_overrun; 1462151869Sdavidxu it->it_overrun_last = it->it_overrun; 1463151869Sdavidxu it->it_overrun = 0; 1464151869Sdavidxu ITIMER_UNLOCK(it); 1465151869Sdavidxu return (0); 1466151869Sdavidxu } 1467151869Sdavidxu return (EINVAL); 1468151869Sdavidxu} 1469151869Sdavidxu 1470151869Sdavidxuint 1471151869Sdavidxuitimespecfix(struct timespec *ts) 1472151869Sdavidxu{ 1473151869Sdavidxu 1474151869Sdavidxu if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) 1475151869Sdavidxu return (EINVAL); 1476151869Sdavidxu if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000) 1477151869Sdavidxu ts->tv_nsec = tick * 1000; 1478151869Sdavidxu return (0); 1479151869Sdavidxu} 1480151869Sdavidxu 1481151576Sdavidxu/* Timeout callback for realtime timer */ 1482151576Sdavidxustatic void 1483151576Sdavidxurealtimer_expire(void *arg) 1484151576Sdavidxu{ 1485151869Sdavidxu struct timespec cts, ts; 1486151869Sdavidxu struct timeval tv; 1487151576Sdavidxu struct itimer *it; 1488151576Sdavidxu 1489151576Sdavidxu it = (struct itimer *)arg; 1490151576Sdavidxu 1491151869Sdavidxu realtimer_clocktime(it->it_clockid, &cts); 1492151576Sdavidxu /* Only fire if time is reached. */ 1493151869Sdavidxu if (timespeccmp(&cts, &it->it_time.it_value, >=)) { 1494151869Sdavidxu if (timespecisset(&it->it_time.it_interval)) { 1495151869Sdavidxu timespecadd(&it->it_time.it_value, 1496151869Sdavidxu &it->it_time.it_interval); 1497151869Sdavidxu while (timespeccmp(&cts, &it->it_time.it_value, >=)) { 1498152983Sdavidxu if (it->it_overrun < INT_MAX) 1499152983Sdavidxu it->it_overrun++; 1500152983Sdavidxu else 1501152983Sdavidxu it->it_ksi.ksi_errno = ERANGE; 1502151869Sdavidxu timespecadd(&it->it_time.it_value, 1503151869Sdavidxu &it->it_time.it_interval); 1504151576Sdavidxu } 1505151576Sdavidxu } else { 1506151576Sdavidxu /* single shot timer ? */ 1507151869Sdavidxu timespecclear(&it->it_time.it_value); 1508151576Sdavidxu } 1509151869Sdavidxu if (timespecisset(&it->it_time.it_value)) { 1510151869Sdavidxu ts = it->it_time.it_value; 1511151869Sdavidxu timespecsub(&ts, &cts); 1512151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1513151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), 1514151576Sdavidxu realtimer_expire, it); 1515151576Sdavidxu } 1516184067Sdavidxu itimer_enter(it); 1517151576Sdavidxu ITIMER_UNLOCK(it); 1518151576Sdavidxu itimer_fire(it); 1519151576Sdavidxu ITIMER_LOCK(it); 1520184067Sdavidxu itimer_leave(it); 1521151869Sdavidxu } else if (timespecisset(&it->it_time.it_value)) { 1522151869Sdavidxu ts = it->it_time.it_value; 1523151869Sdavidxu timespecsub(&ts, &cts); 1524151869Sdavidxu TIMESPEC_TO_TIMEVAL(&tv, &ts); 1525151869Sdavidxu callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire, 1526151576Sdavidxu it); 1527151576Sdavidxu } 1528151576Sdavidxu} 1529151576Sdavidxu 1530151576Sdavidxuvoid 1531151576Sdavidxuitimer_fire(struct itimer *it) 1532151576Sdavidxu{ 1533151576Sdavidxu struct proc *p = it->it_proc; 1534213642Sdavidxu struct thread *td; 1535151576Sdavidxu 1536151869Sdavidxu if (it->it_sigev.sigev_notify == SIGEV_SIGNAL || 1537151869Sdavidxu it->it_sigev.sigev_notify == SIGEV_THREAD_ID) { 1538213642Sdavidxu if (sigev_findtd(p, &it->it_sigev, &td) != 0) { 1539213642Sdavidxu ITIMER_LOCK(it); 1540213642Sdavidxu timespecclear(&it->it_time.it_value); 1541213642Sdavidxu timespecclear(&it->it_time.it_interval); 1542213642Sdavidxu callout_stop(&it->it_callout); 1543213642Sdavidxu ITIMER_UNLOCK(it); 1544213642Sdavidxu return; 1545213642Sdavidxu } 1546151993Sdavidxu if (!KSI_ONQ(&it->it_ksi)) { 1547152983Sdavidxu it->it_ksi.ksi_errno = 0; 1548213642Sdavidxu ksiginfo_set_sigev(&it->it_ksi, &it->it_sigev); 1549213642Sdavidxu tdsendsignal(p, td, it->it_ksi.ksi_signo, &it->it_ksi); 1550151993Sdavidxu } else { 1551152983Sdavidxu if (it->it_overrun < INT_MAX) 1552152983Sdavidxu it->it_overrun++; 1553152983Sdavidxu else 1554152983Sdavidxu it->it_ksi.ksi_errno = ERANGE; 1555151576Sdavidxu } 1556151576Sdavidxu PROC_UNLOCK(p); 1557151576Sdavidxu } 1558151576Sdavidxu} 1559151576Sdavidxu 1560151576Sdavidxustatic void 1561151576Sdavidxuitimers_alloc(struct proc *p) 1562151576Sdavidxu{ 1563151585Sdavidxu struct itimers *its; 1564151585Sdavidxu int i; 1565151576Sdavidxu 1566151585Sdavidxu its = malloc(sizeof (struct itimers), M_SUBPROC, M_WAITOK | M_ZERO); 1567151585Sdavidxu LIST_INIT(&its->its_virtual); 1568151585Sdavidxu LIST_INIT(&its->its_prof); 1569151585Sdavidxu TAILQ_INIT(&its->its_worklist); 1570151585Sdavidxu for (i = 0; i < TIMER_MAX; i++) 1571151585Sdavidxu its->its_timers[i] = NULL; 1572151576Sdavidxu PROC_LOCK(p); 1573151585Sdavidxu if (p->p_itimers == NULL) { 1574151585Sdavidxu p->p_itimers = its; 1575151576Sdavidxu PROC_UNLOCK(p); 1576151585Sdavidxu } 1577151585Sdavidxu else { 1578151576Sdavidxu PROC_UNLOCK(p); 1579151585Sdavidxu free(its, M_SUBPROC); 1580151576Sdavidxu } 1581151576Sdavidxu} 1582151576Sdavidxu 1583161302Snetchildstatic void 1584161302Snetchilditimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp __unused) 1585161302Snetchild{ 1586164713Sdavidxu itimers_event_hook_exit(arg, p); 1587161302Snetchild} 1588161302Snetchild 1589151576Sdavidxu/* Clean up timers when some process events are being triggered. */ 1590153259Sdavidxustatic void 1591161302Snetchilditimers_event_hook_exit(void *arg, struct proc *p) 1592151576Sdavidxu{ 1593151576Sdavidxu struct itimers *its; 1594151576Sdavidxu struct itimer *it; 1595153267Sdavidxu int event = (int)(intptr_t)arg; 1596151576Sdavidxu int i; 1597151576Sdavidxu 1598151585Sdavidxu if (p->p_itimers != NULL) { 1599151585Sdavidxu its = p->p_itimers; 1600151576Sdavidxu for (i = 0; i < MAX_CLOCKS; ++i) { 1601151576Sdavidxu if (posix_clocks[i].event_hook != NULL) 1602151576Sdavidxu CLOCK_CALL(i, event_hook, (p, i, event)); 1603151576Sdavidxu } 1604151576Sdavidxu /* 1605151576Sdavidxu * According to susv3, XSI interval timers should be inherited 1606151576Sdavidxu * by new image. 1607151576Sdavidxu */ 1608151576Sdavidxu if (event == ITIMER_EV_EXEC) 1609151576Sdavidxu i = 3; 1610151576Sdavidxu else if (event == ITIMER_EV_EXIT) 1611151576Sdavidxu i = 0; 1612151576Sdavidxu else 1613151576Sdavidxu panic("unhandled event"); 1614151576Sdavidxu for (; i < TIMER_MAX; ++i) { 1615164713Sdavidxu if ((it = its->its_timers[i]) != NULL) 1616164713Sdavidxu kern_timer_delete(curthread, i); 1617151576Sdavidxu } 1618151576Sdavidxu if (its->its_timers[0] == NULL && 1619151576Sdavidxu its->its_timers[1] == NULL && 1620151576Sdavidxu its->its_timers[2] == NULL) { 1621151585Sdavidxu free(its, M_SUBPROC); 1622151585Sdavidxu p->p_itimers = NULL; 1623151576Sdavidxu } 1624151576Sdavidxu } 1625151576Sdavidxu} 1626