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