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 {
777170307Sjeff		PROC_SLOCK(p);
778140832Ssobomax		*oitv = p->p_stats->p_timer[which];
779140832Ssobomax		p->p_stats->p_timer[which] = *aitv;
780170307Sjeff		PROC_SUNLOCK(p);
78182746Sdillon	}
782140832Ssobomax	return (0);
7831541Srgrimes}
7841541Srgrimes
7851541Srgrimes/*
7861541Srgrimes * Real interval timer expired:
7871541Srgrimes * send process whose timer expired an alarm signal.
7881541Srgrimes * If time is not set up to reload, then just return.
7891541Srgrimes * Else compute next time timer should go off which is > current time.
7901541Srgrimes * This is where delay in processing this timeout causes multiple
7911541Srgrimes * SIGALRM calls to be compressed into one.
79236127Sbde * tvtohz() always adds 1 to allow for the time until the next clock
7939327Sbde * interrupt being strictly less than 1 clock tick, but we don't want
7949327Sbde * that here since we want to appear to be in sync with the clock
7959327Sbde * interrupt even when we're delayed.
7961541Srgrimes */
7971541Srgrimesvoid
798102074Sphkrealitexpire(void *arg)
7991541Srgrimes{
800102074Sphk	struct proc *p;
801247903Smav	struct timeval ctv;
802247903Smav	sbintime_t isbt;
8031541Srgrimes
8041541Srgrimes	p = (struct proc *)arg;
805225617Skmacy	kern_psignal(p, SIGALRM);
80635058Sphk	if (!timevalisset(&p->p_realtimer.it_interval)) {
80735058Sphk		timevalclear(&p->p_realtimer.it_value);
808116123Sjhb		if (p->p_flag & P_WEXIT)
809116123Sjhb			wakeup(&p->p_itcallout);
8101541Srgrimes		return;
8111541Srgrimes	}
812247903Smav	isbt = tvtosbt(p->p_realtimer.it_interval);
813247903Smav	if (isbt >= sbt_timethreshold)
814247903Smav		getmicrouptime(&ctv);
815247903Smav	else
816247903Smav		microuptime(&ctv);
817247903Smav	do {
8181541Srgrimes		timevaladd(&p->p_realtimer.it_value,
8191541Srgrimes		    &p->p_realtimer.it_interval);
820247903Smav	} while (timevalcmp(&p->p_realtimer.it_value, &ctv, <=));
821247903Smav	callout_reset_sbt(&p->p_itcallout, tvtosbt(p->p_realtimer.it_value),
822247903Smav	    isbt >> tc_precexp, realitexpire, p, C_ABSOLUTE);
8231541Srgrimes}
8241541Srgrimes
8251541Srgrimes/*
8261541Srgrimes * Check that a proposed value to load into the .it_value or
8271541Srgrimes * .it_interval part of an interval timer is acceptable, and
8281541Srgrimes * fix it to have at least minimal value (i.e. if it is less
8291541Srgrimes * than the resolution of the clock, round it up.)
8301541Srgrimes */
8311549Srgrimesint
832102074Sphkitimerfix(struct timeval *tv)
8331541Srgrimes{
8341541Srgrimes
835151576Sdavidxu	if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000)
8361541Srgrimes		return (EINVAL);
837247903Smav	if (tv->tv_sec == 0 && tv->tv_usec != 0 &&
838247903Smav	    tv->tv_usec < (u_int)tick / 16)
839247903Smav		tv->tv_usec = (u_int)tick / 16;
8401541Srgrimes	return (0);
8411541Srgrimes}
8421541Srgrimes
8431541Srgrimes/*
8441541Srgrimes * Decrement an interval timer by a specified number
8451541Srgrimes * of microseconds, which must be less than a second,
8461541Srgrimes * i.e. < 1000000.  If the timer expires, then reload
8471541Srgrimes * it.  In this case, carry over (usec - old value) to
8481541Srgrimes * reduce the value reloaded into the timer so that
8491541Srgrimes * the timer does not drift.  This routine assumes
8501541Srgrimes * that it is called in a context where the timers
8511541Srgrimes * on which it is operating cannot change in value.
8521541Srgrimes */
8531549Srgrimesint
854102074Sphkitimerdecr(struct itimerval *itp, int usec)
8551541Srgrimes{
8561541Srgrimes
8571541Srgrimes	if (itp->it_value.tv_usec < usec) {
8581541Srgrimes		if (itp->it_value.tv_sec == 0) {
8591541Srgrimes			/* expired, and already in next interval */
8601541Srgrimes			usec -= itp->it_value.tv_usec;
8611541Srgrimes			goto expire;
8621541Srgrimes		}
8631541Srgrimes		itp->it_value.tv_usec += 1000000;
8641541Srgrimes		itp->it_value.tv_sec--;
8651541Srgrimes	}
8661541Srgrimes	itp->it_value.tv_usec -= usec;
8671541Srgrimes	usec = 0;
86835058Sphk	if (timevalisset(&itp->it_value))
8691541Srgrimes		return (1);
8701541Srgrimes	/* expired, exactly at end of interval */
8711541Srgrimesexpire:
87235058Sphk	if (timevalisset(&itp->it_interval)) {
8731541Srgrimes		itp->it_value = itp->it_interval;
8741541Srgrimes		itp->it_value.tv_usec -= usec;
8751541Srgrimes		if (itp->it_value.tv_usec < 0) {
8761541Srgrimes			itp->it_value.tv_usec += 1000000;
8771541Srgrimes			itp->it_value.tv_sec--;
8781541Srgrimes		}
8791541Srgrimes	} else
8801541Srgrimes		itp->it_value.tv_usec = 0;		/* sec is already 0 */
8811541Srgrimes	return (0);
8821541Srgrimes}
8831541Srgrimes
8841541Srgrimes/*
8851541Srgrimes * Add and subtract routines for timevals.
8861541Srgrimes * N.B.: subtract routine doesn't deal with
8871541Srgrimes * results which are before the beginning,
8881541Srgrimes * it just gets very confused in this case.
8891541Srgrimes * Caveat emptor.
8901541Srgrimes */
8911549Srgrimesvoid
892121523Salfredtimevaladd(struct timeval *t1, const struct timeval *t2)
8931541Srgrimes{
8941541Srgrimes
8951541Srgrimes	t1->tv_sec += t2->tv_sec;
8961541Srgrimes	t1->tv_usec += t2->tv_usec;
8971541Srgrimes	timevalfix(t1);
8981541Srgrimes}
8991541Srgrimes
9001549Srgrimesvoid
901121523Salfredtimevalsub(struct timeval *t1, const struct timeval *t2)
9021541Srgrimes{
9031541Srgrimes
9041541Srgrimes	t1->tv_sec -= t2->tv_sec;
9051541Srgrimes	t1->tv_usec -= t2->tv_usec;
9061541Srgrimes	timevalfix(t1);
9071541Srgrimes}
9081541Srgrimes
90912819Sphkstatic void
910102074Sphktimevalfix(struct timeval *t1)
9111541Srgrimes{
9121541Srgrimes
9131541Srgrimes	if (t1->tv_usec < 0) {
9141541Srgrimes		t1->tv_sec--;
9151541Srgrimes		t1->tv_usec += 1000000;
9161541Srgrimes	}
9171541Srgrimes	if (t1->tv_usec >= 1000000) {
9181541Srgrimes		t1->tv_sec++;
9191541Srgrimes		t1->tv_usec -= 1000000;
9201541Srgrimes	}
9211541Srgrimes}
922108142Ssam
923108142Ssam/*
924108511Ssam * ratecheck(): simple time-based rate-limit checking.
925108142Ssam */
926108142Ssamint
927108142Ssamratecheck(struct timeval *lasttime, const struct timeval *mininterval)
928108142Ssam{
929108142Ssam	struct timeval tv, delta;
930108142Ssam	int rv = 0;
931108142Ssam
932108511Ssam	getmicrouptime(&tv);		/* NB: 10ms precision */
933108511Ssam	delta = tv;
934108511Ssam	timevalsub(&delta, lasttime);
935108142Ssam
936108142Ssam	/*
937108142Ssam	 * check for 0,0 is so that the message will be seen at least once,
938108142Ssam	 * even if interval is huge.
939108142Ssam	 */
940108142Ssam	if (timevalcmp(&delta, mininterval, >=) ||
941108142Ssam	    (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) {
942108142Ssam		*lasttime = tv;
943108142Ssam		rv = 1;
944108142Ssam	}
945108142Ssam
946108142Ssam	return (rv);
947108142Ssam}
948108142Ssam
949108142Ssam/*
950108142Ssam * ppsratecheck(): packets (or events) per second limitation.
951108511Ssam *
952108511Ssam * Return 0 if the limit is to be enforced (e.g. the caller
953108511Ssam * should drop a packet because of the rate limitation).
954108511Ssam *
955111558Ssam * maxpps of 0 always causes zero to be returned.  maxpps of -1
956111558Ssam * always causes 1 to be returned; this effectively defeats rate
957111558Ssam * limiting.
958111558Ssam *
959108511Ssam * Note that we maintain the struct timeval for compatibility
960108511Ssam * with other bsd systems.  We reuse the storage and just monitor
961108511Ssam * clock ticks for minimal overhead.
962108142Ssam */
963108142Ssamint
964108142Ssamppsratecheck(struct timeval *lasttime, int *curpps, int maxpps)
965108142Ssam{
966108511Ssam	int now;
967108142Ssam
968108142Ssam	/*
969108511Ssam	 * Reset the last time and counter if this is the first call
970108511Ssam	 * or more than a second has passed since the last update of
971108511Ssam	 * lasttime.
972108142Ssam	 */
973108511Ssam	now = ticks;
974108511Ssam	if (lasttime->tv_sec == 0 || (u_int)(now - lasttime->tv_sec) >= hz) {
975108511Ssam		lasttime->tv_sec = now;
976108511Ssam		*curpps = 1;
977111558Ssam		return (maxpps != 0);
978108511Ssam	} else {
979108511Ssam		(*curpps)++;		/* NB: ignore potential overflow */
980108511Ssam		return (maxpps < 0 || *curpps < maxpps);
981108511Ssam	}
982108142Ssam}
983151576Sdavidxu
984151576Sdavidxustatic void
985151576Sdavidxuitimer_start(void)
986151576Sdavidxu{
987151576Sdavidxu	struct kclock rt_clock = {
988151576Sdavidxu		.timer_create  = realtimer_create,
989151576Sdavidxu		.timer_delete  = realtimer_delete,
990151576Sdavidxu		.timer_settime = realtimer_settime,
991151576Sdavidxu		.timer_gettime = realtimer_gettime,
992164713Sdavidxu		.event_hook    = NULL
993151576Sdavidxu	};
994151576Sdavidxu
995151576Sdavidxu	itimer_zone = uma_zcreate("itimer", sizeof(struct itimer),
996151576Sdavidxu		NULL, NULL, itimer_init, itimer_fini, UMA_ALIGN_PTR, 0);
997151576Sdavidxu	register_posix_clock(CLOCK_REALTIME,  &rt_clock);
998151576Sdavidxu	register_posix_clock(CLOCK_MONOTONIC, &rt_clock);
999152983Sdavidxu	p31b_setcfg(CTL_P1003_1B_TIMERS, 200112L);
1000152983Sdavidxu	p31b_setcfg(CTL_P1003_1B_DELAYTIMER_MAX, INT_MAX);
1001152983Sdavidxu	p31b_setcfg(CTL_P1003_1B_TIMER_MAX, TIMER_MAX);
1002161302Snetchild	EVENTHANDLER_REGISTER(process_exit, itimers_event_hook_exit,
1003153259Sdavidxu		(void *)ITIMER_EV_EXIT, EVENTHANDLER_PRI_ANY);
1004161302Snetchild	EVENTHANDLER_REGISTER(process_exec, itimers_event_hook_exec,
1005153259Sdavidxu		(void *)ITIMER_EV_EXEC, EVENTHANDLER_PRI_ANY);
1006151576Sdavidxu}
1007151576Sdavidxu
1008151576Sdavidxuint
1009151576Sdavidxuregister_posix_clock(int clockid, struct kclock *clk)
1010151576Sdavidxu{
1011151576Sdavidxu	if ((unsigned)clockid >= MAX_CLOCKS) {
1012151576Sdavidxu		printf("%s: invalid clockid\n", __func__);
1013151576Sdavidxu		return (0);
1014151576Sdavidxu	}
1015151576Sdavidxu	posix_clocks[clockid] = *clk;
1016151576Sdavidxu	return (1);
1017151576Sdavidxu}
1018151576Sdavidxu
1019151576Sdavidxustatic int
1020151576Sdavidxuitimer_init(void *mem, int size, int flags)
1021151576Sdavidxu{
1022151576Sdavidxu	struct itimer *it;
1023151576Sdavidxu
1024151576Sdavidxu	it = (struct itimer *)mem;
1025151576Sdavidxu	mtx_init(&it->it_mtx, "itimer lock", NULL, MTX_DEF);
1026151576Sdavidxu	return (0);
1027151576Sdavidxu}
1028151576Sdavidxu
1029151576Sdavidxustatic void
1030151576Sdavidxuitimer_fini(void *mem, int size)
1031151576Sdavidxu{
1032151576Sdavidxu	struct itimer *it;
1033151576Sdavidxu
1034151576Sdavidxu	it = (struct itimer *)mem;
1035151576Sdavidxu	mtx_destroy(&it->it_mtx);
1036151576Sdavidxu}
1037151576Sdavidxu
1038151576Sdavidxustatic void
1039151576Sdavidxuitimer_enter(struct itimer *it)
1040151576Sdavidxu{
1041151576Sdavidxu
1042151576Sdavidxu	mtx_assert(&it->it_mtx, MA_OWNED);
1043151576Sdavidxu	it->it_usecount++;
1044151576Sdavidxu}
1045151576Sdavidxu
1046151576Sdavidxustatic void
1047151576Sdavidxuitimer_leave(struct itimer *it)
1048151576Sdavidxu{
1049151576Sdavidxu
1050151576Sdavidxu	mtx_assert(&it->it_mtx, MA_OWNED);
1051151576Sdavidxu	KASSERT(it->it_usecount > 0, ("invalid it_usecount"));
1052151576Sdavidxu
1053151576Sdavidxu	if (--it->it_usecount == 0 && (it->it_flags & ITF_WANTED) != 0)
1054151576Sdavidxu		wakeup(it);
1055151576Sdavidxu}
1056151576Sdavidxu
1057151576Sdavidxu#ifndef _SYS_SYSPROTO_H_
1058156134Sdavidxustruct ktimer_create_args {
1059151576Sdavidxu	clockid_t clock_id;
1060151576Sdavidxu	struct sigevent * evp;
1061156134Sdavidxu	int * timerid;
1062151576Sdavidxu};
1063151576Sdavidxu#endif
1064151576Sdavidxuint
1065225617Skmacysys_ktimer_create(struct thread *td, struct ktimer_create_args *uap)
1066151576Sdavidxu{
1067253530Skib	struct sigevent *evp, ev;
1068156134Sdavidxu	int id;
1069151576Sdavidxu	int error;
1070151576Sdavidxu
1071253530Skib	if (uap->evp == NULL) {
1072253530Skib		evp = NULL;
1073253530Skib	} else {
1074151576Sdavidxu		error = copyin(uap->evp, &ev, sizeof(ev));
1075151576Sdavidxu		if (error != 0)
1076151576Sdavidxu			return (error);
1077253530Skib		evp = &ev;
1078253530Skib	}
1079253530Skib	error = kern_ktimer_create(td, uap->clock_id, evp, &id, -1);
1080151576Sdavidxu	if (error == 0) {
1081156134Sdavidxu		error = copyout(&id, uap->timerid, sizeof(int));
1082151576Sdavidxu		if (error != 0)
1083253530Skib			kern_ktimer_delete(td, id);
1084151576Sdavidxu	}
1085151576Sdavidxu	return (error);
1086151576Sdavidxu}
1087151576Sdavidxu
1088253530Skibint
1089253530Skibkern_ktimer_create(struct thread *td, clockid_t clock_id, struct sigevent *evp,
1090253530Skib    int *timerid, int preset_id)
1091151576Sdavidxu{
1092151576Sdavidxu	struct proc *p = td->td_proc;
1093151576Sdavidxu	struct itimer *it;
1094151576Sdavidxu	int id;
1095151576Sdavidxu	int error;
1096151576Sdavidxu
1097151576Sdavidxu	if (clock_id < 0 || clock_id >= MAX_CLOCKS)
1098151576Sdavidxu		return (EINVAL);
1099151576Sdavidxu
1100151576Sdavidxu	if (posix_clocks[clock_id].timer_create == NULL)
1101151576Sdavidxu		return (EINVAL);
1102151576Sdavidxu
1103151576Sdavidxu	if (evp != NULL) {
1104151576Sdavidxu		if (evp->sigev_notify != SIGEV_NONE &&
1105151869Sdavidxu		    evp->sigev_notify != SIGEV_SIGNAL &&
1106151869Sdavidxu		    evp->sigev_notify != SIGEV_THREAD_ID)
1107151576Sdavidxu			return (EINVAL);
1108151869Sdavidxu		if ((evp->sigev_notify == SIGEV_SIGNAL ||
1109151869Sdavidxu		     evp->sigev_notify == SIGEV_THREAD_ID) &&
1110151576Sdavidxu			!_SIG_VALID(evp->sigev_signo))
1111151576Sdavidxu			return (EINVAL);
1112151576Sdavidxu	}
1113151576Sdavidxu
1114151585Sdavidxu	if (p->p_itimers == NULL)
1115151576Sdavidxu		itimers_alloc(p);
1116151576Sdavidxu
1117151576Sdavidxu	it = uma_zalloc(itimer_zone, M_WAITOK);
1118151576Sdavidxu	it->it_flags = 0;
1119151576Sdavidxu	it->it_usecount = 0;
1120151576Sdavidxu	it->it_active = 0;
1121151869Sdavidxu	timespecclear(&it->it_time.it_value);
1122151869Sdavidxu	timespecclear(&it->it_time.it_interval);
1123151576Sdavidxu	it->it_overrun = 0;
1124151576Sdavidxu	it->it_overrun_last = 0;
1125151576Sdavidxu	it->it_clockid = clock_id;
1126151576Sdavidxu	it->it_timerid = -1;
1127151576Sdavidxu	it->it_proc = p;
1128151576Sdavidxu	ksiginfo_init(&it->it_ksi);
1129151576Sdavidxu	it->it_ksi.ksi_flags |= KSI_INS | KSI_EXT;
1130151576Sdavidxu	error = CLOCK_CALL(clock_id, timer_create, (it));
1131151576Sdavidxu	if (error != 0)
1132151576Sdavidxu		goto out;
1133151576Sdavidxu
1134151576Sdavidxu	PROC_LOCK(p);
1135151576Sdavidxu	if (preset_id != -1) {
1136151576Sdavidxu		KASSERT(preset_id >= 0 && preset_id < 3, ("invalid preset_id"));
1137151576Sdavidxu		id = preset_id;
1138151585Sdavidxu		if (p->p_itimers->its_timers[id] != NULL) {
1139151576Sdavidxu			PROC_UNLOCK(p);
1140151576Sdavidxu			error = 0;
1141151576Sdavidxu			goto out;
1142151576Sdavidxu		}
1143151576Sdavidxu	} else {
1144151576Sdavidxu		/*
1145151576Sdavidxu		 * Find a free timer slot, skipping those reserved
1146151576Sdavidxu		 * for setitimer().
1147151576Sdavidxu		 */
1148151576Sdavidxu		for (id = 3; id < TIMER_MAX; id++)
1149151585Sdavidxu			if (p->p_itimers->its_timers[id] == NULL)
1150151576Sdavidxu				break;
1151151576Sdavidxu		if (id == TIMER_MAX) {
1152151576Sdavidxu			PROC_UNLOCK(p);
1153151576Sdavidxu			error = EAGAIN;
1154151576Sdavidxu			goto out;
1155151576Sdavidxu		}
1156151576Sdavidxu	}
1157151576Sdavidxu	it->it_timerid = id;
1158151585Sdavidxu	p->p_itimers->its_timers[id] = it;
1159151576Sdavidxu	if (evp != NULL)
1160151576Sdavidxu		it->it_sigev = *evp;
1161151576Sdavidxu	else {
1162151576Sdavidxu		it->it_sigev.sigev_notify = SIGEV_SIGNAL;
1163151576Sdavidxu		switch (clock_id) {
1164151576Sdavidxu		default:
1165151576Sdavidxu		case CLOCK_REALTIME:
1166151576Sdavidxu			it->it_sigev.sigev_signo = SIGALRM;
1167151576Sdavidxu			break;
1168151576Sdavidxu		case CLOCK_VIRTUAL:
1169151576Sdavidxu 			it->it_sigev.sigev_signo = SIGVTALRM;
1170151576Sdavidxu			break;
1171151576Sdavidxu		case CLOCK_PROF:
1172151576Sdavidxu			it->it_sigev.sigev_signo = SIGPROF;
1173151576Sdavidxu			break;
1174151576Sdavidxu		}
1175152029Sdavidxu		it->it_sigev.sigev_value.sival_int = id;
1176151576Sdavidxu	}
1177151576Sdavidxu
1178151869Sdavidxu	if (it->it_sigev.sigev_notify == SIGEV_SIGNAL ||
1179151869Sdavidxu	    it->it_sigev.sigev_notify == SIGEV_THREAD_ID) {
1180151576Sdavidxu		it->it_ksi.ksi_signo = it->it_sigev.sigev_signo;
1181151576Sdavidxu		it->it_ksi.ksi_code = SI_TIMER;
1182151576Sdavidxu		it->it_ksi.ksi_value = it->it_sigev.sigev_value;
1183151576Sdavidxu		it->it_ksi.ksi_timerid = id;
1184151576Sdavidxu	}
1185151576Sdavidxu	PROC_UNLOCK(p);
1186151576Sdavidxu	*timerid = id;
1187151576Sdavidxu	return (0);
1188151576Sdavidxu
1189151576Sdavidxuout:
1190151576Sdavidxu	ITIMER_LOCK(it);
1191151576Sdavidxu	CLOCK_CALL(it->it_clockid, timer_delete, (it));
1192151576Sdavidxu	ITIMER_UNLOCK(it);
1193151576Sdavidxu	uma_zfree(itimer_zone, it);
1194151576Sdavidxu	return (error);
1195151576Sdavidxu}
1196151576Sdavidxu
1197151576Sdavidxu#ifndef _SYS_SYSPROTO_H_
1198156134Sdavidxustruct ktimer_delete_args {
1199156134Sdavidxu	int timerid;
1200151576Sdavidxu};
1201151576Sdavidxu#endif
1202151576Sdavidxuint
1203225617Skmacysys_ktimer_delete(struct thread *td, struct ktimer_delete_args *uap)
1204151576Sdavidxu{
1205253530Skib
1206253530Skib	return (kern_ktimer_delete(td, uap->timerid));
1207151576Sdavidxu}
1208151576Sdavidxu
1209151576Sdavidxustatic struct itimer *
1210164713Sdavidxuitimer_find(struct proc *p, int timerid)
1211151576Sdavidxu{
1212151576Sdavidxu	struct itimer *it;
1213151576Sdavidxu
1214151576Sdavidxu	PROC_LOCK_ASSERT(p, MA_OWNED);
1215190301Scperciva	if ((p->p_itimers == NULL) ||
1216190301Scperciva	    (timerid < 0) || (timerid >= TIMER_MAX) ||
1217151585Sdavidxu	    (it = p->p_itimers->its_timers[timerid]) == NULL) {
1218151576Sdavidxu		return (NULL);
1219151576Sdavidxu	}
1220151576Sdavidxu	ITIMER_LOCK(it);
1221164713Sdavidxu	if ((it->it_flags & ITF_DELETING) != 0) {
1222151576Sdavidxu		ITIMER_UNLOCK(it);
1223151576Sdavidxu		it = NULL;
1224151576Sdavidxu	}
1225151576Sdavidxu	return (it);
1226151576Sdavidxu}
1227151576Sdavidxu
1228253530Skibint
1229253530Skibkern_ktimer_delete(struct thread *td, int timerid)
1230151576Sdavidxu{
1231151576Sdavidxu	struct proc *p = td->td_proc;
1232151576Sdavidxu	struct itimer *it;
1233151576Sdavidxu
1234151576Sdavidxu	PROC_LOCK(p);
1235164713Sdavidxu	it = itimer_find(p, timerid);
1236151576Sdavidxu	if (it == NULL) {
1237151576Sdavidxu		PROC_UNLOCK(p);
1238151576Sdavidxu		return (EINVAL);
1239151576Sdavidxu	}
1240151576Sdavidxu	PROC_UNLOCK(p);
1241151576Sdavidxu
1242151576Sdavidxu	it->it_flags |= ITF_DELETING;
1243151576Sdavidxu	while (it->it_usecount > 0) {
1244151576Sdavidxu		it->it_flags |= ITF_WANTED;
1245151576Sdavidxu		msleep(it, &it->it_mtx, PPAUSE, "itimer", 0);
1246151576Sdavidxu	}
1247151576Sdavidxu	it->it_flags &= ~ITF_WANTED;
1248151576Sdavidxu	CLOCK_CALL(it->it_clockid, timer_delete, (it));
1249151576Sdavidxu	ITIMER_UNLOCK(it);
1250151576Sdavidxu
1251151576Sdavidxu	PROC_LOCK(p);
1252151576Sdavidxu	if (KSI_ONQ(&it->it_ksi))
1253151576Sdavidxu		sigqueue_take(&it->it_ksi);
1254151585Sdavidxu	p->p_itimers->its_timers[timerid] = NULL;
1255151576Sdavidxu	PROC_UNLOCK(p);
1256151576Sdavidxu	uma_zfree(itimer_zone, it);
1257151576Sdavidxu	return (0);
1258151576Sdavidxu}
1259151576Sdavidxu
1260151576Sdavidxu#ifndef _SYS_SYSPROTO_H_
1261156134Sdavidxustruct ktimer_settime_args {
1262156134Sdavidxu	int timerid;
1263151576Sdavidxu	int flags;
1264151576Sdavidxu	const struct itimerspec * value;
1265151576Sdavidxu	struct itimerspec * ovalue;
1266151576Sdavidxu};
1267151576Sdavidxu#endif
1268151576Sdavidxuint
1269225617Skmacysys_ktimer_settime(struct thread *td, struct ktimer_settime_args *uap)
1270151576Sdavidxu{
1271151576Sdavidxu	struct itimerspec val, oval, *ovalp;
1272151576Sdavidxu	int error;
1273151576Sdavidxu
1274151576Sdavidxu	error = copyin(uap->value, &val, sizeof(val));
1275151576Sdavidxu	if (error != 0)
1276151576Sdavidxu		return (error);
1277253530Skib	ovalp = uap->ovalue != NULL ? &oval : NULL;
1278253530Skib	error = kern_ktimer_settime(td, uap->timerid, uap->flags, &val, ovalp);
1279253530Skib	if (error == 0 && uap->ovalue != NULL)
1280253530Skib		error = copyout(ovalp, uap->ovalue, sizeof(*ovalp));
1281253530Skib	return (error);
1282253530Skib}
1283151576Sdavidxu
1284253530Skibint
1285253530Skibkern_ktimer_settime(struct thread *td, int timer_id, int flags,
1286253530Skib    struct itimerspec *val, struct itimerspec *oval)
1287253530Skib{
1288253530Skib	struct proc *p;
1289253530Skib	struct itimer *it;
1290253530Skib	int error;
1291253530Skib
1292253530Skib	p = td->td_proc;
1293151576Sdavidxu	PROC_LOCK(p);
1294253530Skib	if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) {
1295151576Sdavidxu		PROC_UNLOCK(p);
1296151576Sdavidxu		error = EINVAL;
1297151576Sdavidxu	} else {
1298151576Sdavidxu		PROC_UNLOCK(p);
1299151576Sdavidxu		itimer_enter(it);
1300253530Skib		error = CLOCK_CALL(it->it_clockid, timer_settime, (it,
1301253530Skib		    flags, val, oval));
1302151576Sdavidxu		itimer_leave(it);
1303151576Sdavidxu		ITIMER_UNLOCK(it);
1304151576Sdavidxu	}
1305151576Sdavidxu	return (error);
1306151576Sdavidxu}
1307151576Sdavidxu
1308151576Sdavidxu#ifndef _SYS_SYSPROTO_H_
1309156134Sdavidxustruct ktimer_gettime_args {
1310156134Sdavidxu	int timerid;
1311151576Sdavidxu	struct itimerspec * value;
1312151576Sdavidxu};
1313151576Sdavidxu#endif
1314151576Sdavidxuint
1315225617Skmacysys_ktimer_gettime(struct thread *td, struct ktimer_gettime_args *uap)
1316151576Sdavidxu{
1317151576Sdavidxu	struct itimerspec val;
1318151576Sdavidxu	int error;
1319151576Sdavidxu
1320253530Skib	error = kern_ktimer_gettime(td, uap->timerid, &val);
1321253530Skib	if (error == 0)
1322253530Skib		error = copyout(&val, uap->value, sizeof(val));
1323253530Skib	return (error);
1324253530Skib}
1325253530Skib
1326253530Skibint
1327253530Skibkern_ktimer_gettime(struct thread *td, int timer_id, struct itimerspec *val)
1328253530Skib{
1329253530Skib	struct proc *p;
1330253530Skib	struct itimer *it;
1331253530Skib	int error;
1332253530Skib
1333253530Skib	p = td->td_proc;
1334151576Sdavidxu	PROC_LOCK(p);
1335253530Skib	if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) {
1336151576Sdavidxu		PROC_UNLOCK(p);
1337151576Sdavidxu		error = EINVAL;
1338151576Sdavidxu	} else {
1339151576Sdavidxu		PROC_UNLOCK(p);
1340151576Sdavidxu		itimer_enter(it);
1341253530Skib		error = CLOCK_CALL(it->it_clockid, timer_gettime, (it, val));
1342151576Sdavidxu		itimer_leave(it);
1343151576Sdavidxu		ITIMER_UNLOCK(it);
1344151576Sdavidxu	}
1345151576Sdavidxu	return (error);
1346151576Sdavidxu}
1347151576Sdavidxu
1348151576Sdavidxu#ifndef _SYS_SYSPROTO_H_
1349151576Sdavidxustruct timer_getoverrun_args {
1350156134Sdavidxu	int timerid;
1351151576Sdavidxu};
1352151576Sdavidxu#endif
1353151576Sdavidxuint
1354225617Skmacysys_ktimer_getoverrun(struct thread *td, struct ktimer_getoverrun_args *uap)
1355151576Sdavidxu{
1356151576Sdavidxu	struct proc *p = td->td_proc;
1357151576Sdavidxu	struct itimer *it;
1358151576Sdavidxu	int error ;
1359151576Sdavidxu
1360151576Sdavidxu	PROC_LOCK(p);
1361151576Sdavidxu	if (uap->timerid < 3 ||
1362164713Sdavidxu	    (it = itimer_find(p, uap->timerid)) == NULL) {
1363151576Sdavidxu		PROC_UNLOCK(p);
1364151576Sdavidxu		error = EINVAL;
1365151576Sdavidxu	} else {
1366151576Sdavidxu		td->td_retval[0] = it->it_overrun_last;
1367151576Sdavidxu		ITIMER_UNLOCK(it);
1368151869Sdavidxu		PROC_UNLOCK(p);
1369151576Sdavidxu		error = 0;
1370151576Sdavidxu	}
1371151576Sdavidxu	return (error);
1372151576Sdavidxu}
1373151576Sdavidxu
1374151576Sdavidxustatic int
1375151576Sdavidxurealtimer_create(struct itimer *it)
1376151576Sdavidxu{
1377151576Sdavidxu	callout_init_mtx(&it->it_callout, &it->it_mtx, 0);
1378151576Sdavidxu	return (0);
1379151576Sdavidxu}
1380151576Sdavidxu
1381151576Sdavidxustatic int
1382151576Sdavidxurealtimer_delete(struct itimer *it)
1383151576Sdavidxu{
1384151576Sdavidxu	mtx_assert(&it->it_mtx, MA_OWNED);
1385164713Sdavidxu
1386184067Sdavidxu	/*
1387184067Sdavidxu	 * clear timer's value and interval to tell realtimer_expire
1388184067Sdavidxu	 * to not rearm the timer.
1389184067Sdavidxu	 */
1390184067Sdavidxu	timespecclear(&it->it_time.it_value);
1391184067Sdavidxu	timespecclear(&it->it_time.it_interval);
1392164713Sdavidxu	ITIMER_UNLOCK(it);
1393164713Sdavidxu	callout_drain(&it->it_callout);
1394164713Sdavidxu	ITIMER_LOCK(it);
1395151576Sdavidxu	return (0);
1396151576Sdavidxu}
1397151576Sdavidxu
1398151576Sdavidxustatic int
1399151576Sdavidxurealtimer_gettime(struct itimer *it, struct itimerspec *ovalue)
1400151576Sdavidxu{
1401151869Sdavidxu	struct timespec cts;
1402151576Sdavidxu
1403151576Sdavidxu	mtx_assert(&it->it_mtx, MA_OWNED);
1404151576Sdavidxu
1405151869Sdavidxu	realtimer_clocktime(it->it_clockid, &cts);
1406151869Sdavidxu	*ovalue = it->it_time;
1407151576Sdavidxu	if (ovalue->it_value.tv_sec != 0 || ovalue->it_value.tv_nsec != 0) {
1408151869Sdavidxu		timespecsub(&ovalue->it_value, &cts);
1409151576Sdavidxu		if (ovalue->it_value.tv_sec < 0 ||
1410151576Sdavidxu		    (ovalue->it_value.tv_sec == 0 &&
1411151576Sdavidxu		     ovalue->it_value.tv_nsec == 0)) {
1412151576Sdavidxu			ovalue->it_value.tv_sec  = 0;
1413151576Sdavidxu			ovalue->it_value.tv_nsec = 1;
1414151576Sdavidxu		}
1415151576Sdavidxu	}
1416151576Sdavidxu	return (0);
1417151576Sdavidxu}
1418151576Sdavidxu
1419151576Sdavidxustatic int
1420151576Sdavidxurealtimer_settime(struct itimer *it, int flags,
1421151576Sdavidxu	struct itimerspec *value, struct itimerspec *ovalue)
1422151576Sdavidxu{
1423151869Sdavidxu	struct timespec cts, ts;
1424151869Sdavidxu	struct timeval tv;
1425151869Sdavidxu	struct itimerspec val;
1426151576Sdavidxu
1427151576Sdavidxu	mtx_assert(&it->it_mtx, MA_OWNED);
1428151576Sdavidxu
1429151869Sdavidxu	val = *value;
1430151869Sdavidxu	if (itimespecfix(&val.it_value))
1431151576Sdavidxu		return (EINVAL);
1432151576Sdavidxu
1433151869Sdavidxu	if (timespecisset(&val.it_value)) {
1434151869Sdavidxu		if (itimespecfix(&val.it_interval))
1435151576Sdavidxu			return (EINVAL);
1436151576Sdavidxu	} else {
1437151869Sdavidxu		timespecclear(&val.it_interval);
1438151576Sdavidxu	}
1439151576Sdavidxu
1440151576Sdavidxu	if (ovalue != NULL)
1441151576Sdavidxu		realtimer_gettime(it, ovalue);
1442151576Sdavidxu
1443151576Sdavidxu	it->it_time = val;
1444151869Sdavidxu	if (timespecisset(&val.it_value)) {
1445151869Sdavidxu		realtimer_clocktime(it->it_clockid, &cts);
1446151869Sdavidxu		ts = val.it_value;
1447151576Sdavidxu		if ((flags & TIMER_ABSTIME) == 0) {
1448151576Sdavidxu			/* Convert to absolute time. */
1449151869Sdavidxu			timespecadd(&it->it_time.it_value, &cts);
1450151576Sdavidxu		} else {
1451151869Sdavidxu			timespecsub(&ts, &cts);
1452151576Sdavidxu			/*
1453151869Sdavidxu			 * We don't care if ts is negative, tztohz will
1454151576Sdavidxu			 * fix it.
1455151576Sdavidxu			 */
1456151576Sdavidxu		}
1457151869Sdavidxu		TIMESPEC_TO_TIMEVAL(&tv, &ts);
1458151869Sdavidxu		callout_reset(&it->it_callout, tvtohz(&tv),
1459151576Sdavidxu			realtimer_expire, it);
1460151576Sdavidxu	} else {
1461151576Sdavidxu		callout_stop(&it->it_callout);
1462151576Sdavidxu	}
1463151576Sdavidxu
1464151576Sdavidxu	return (0);
1465151576Sdavidxu}
1466151576Sdavidxu
1467151576Sdavidxustatic void
1468151869Sdavidxurealtimer_clocktime(clockid_t id, struct timespec *ts)
1469151576Sdavidxu{
1470151576Sdavidxu	if (id == CLOCK_REALTIME)
1471151869Sdavidxu		getnanotime(ts);
1472151576Sdavidxu	else	/* CLOCK_MONOTONIC */
1473151869Sdavidxu		getnanouptime(ts);
1474151576Sdavidxu}
1475151576Sdavidxu
1476151869Sdavidxuint
1477156134Sdavidxuitimer_accept(struct proc *p, int timerid, ksiginfo_t *ksi)
1478151869Sdavidxu{
1479151869Sdavidxu	struct itimer *it;
1480151869Sdavidxu
1481151869Sdavidxu	PROC_LOCK_ASSERT(p, MA_OWNED);
1482164713Sdavidxu	it = itimer_find(p, timerid);
1483151869Sdavidxu	if (it != NULL) {
1484151869Sdavidxu		ksi->ksi_overrun = it->it_overrun;
1485151869Sdavidxu		it->it_overrun_last = it->it_overrun;
1486151869Sdavidxu		it->it_overrun = 0;
1487151869Sdavidxu		ITIMER_UNLOCK(it);
1488151869Sdavidxu		return (0);
1489151869Sdavidxu	}
1490151869Sdavidxu	return (EINVAL);
1491151869Sdavidxu}
1492151869Sdavidxu
1493151869Sdavidxuint
1494151869Sdavidxuitimespecfix(struct timespec *ts)
1495151869Sdavidxu{
1496151869Sdavidxu
1497151869Sdavidxu	if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000)
1498151869Sdavidxu		return (EINVAL);
1499151869Sdavidxu	if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000)
1500151869Sdavidxu		ts->tv_nsec = tick * 1000;
1501151869Sdavidxu	return (0);
1502151869Sdavidxu}
1503151869Sdavidxu
1504151576Sdavidxu/* Timeout callback for realtime timer */
1505151576Sdavidxustatic void
1506151576Sdavidxurealtimer_expire(void *arg)
1507151576Sdavidxu{
1508151869Sdavidxu	struct timespec cts, ts;
1509151869Sdavidxu	struct timeval tv;
1510151576Sdavidxu	struct itimer *it;
1511151576Sdavidxu
1512151576Sdavidxu	it = (struct itimer *)arg;
1513151576Sdavidxu
1514151869Sdavidxu	realtimer_clocktime(it->it_clockid, &cts);
1515151576Sdavidxu	/* Only fire if time is reached. */
1516151869Sdavidxu	if (timespeccmp(&cts, &it->it_time.it_value, >=)) {
1517151869Sdavidxu		if (timespecisset(&it->it_time.it_interval)) {
1518151869Sdavidxu			timespecadd(&it->it_time.it_value,
1519151869Sdavidxu				    &it->it_time.it_interval);
1520151869Sdavidxu			while (timespeccmp(&cts, &it->it_time.it_value, >=)) {
1521152983Sdavidxu				if (it->it_overrun < INT_MAX)
1522152983Sdavidxu					it->it_overrun++;
1523152983Sdavidxu				else
1524152983Sdavidxu					it->it_ksi.ksi_errno = ERANGE;
1525151869Sdavidxu				timespecadd(&it->it_time.it_value,
1526151869Sdavidxu					    &it->it_time.it_interval);
1527151576Sdavidxu			}
1528151576Sdavidxu		} else {
1529151576Sdavidxu			/* single shot timer ? */
1530151869Sdavidxu			timespecclear(&it->it_time.it_value);
1531151576Sdavidxu		}
1532151869Sdavidxu		if (timespecisset(&it->it_time.it_value)) {
1533151869Sdavidxu			ts = it->it_time.it_value;
1534151869Sdavidxu			timespecsub(&ts, &cts);
1535151869Sdavidxu			TIMESPEC_TO_TIMEVAL(&tv, &ts);
1536151869Sdavidxu			callout_reset(&it->it_callout, tvtohz(&tv),
1537151576Sdavidxu				 realtimer_expire, it);
1538151576Sdavidxu		}
1539184067Sdavidxu		itimer_enter(it);
1540151576Sdavidxu		ITIMER_UNLOCK(it);
1541151576Sdavidxu		itimer_fire(it);
1542151576Sdavidxu		ITIMER_LOCK(it);
1543184067Sdavidxu		itimer_leave(it);
1544151869Sdavidxu	} else if (timespecisset(&it->it_time.it_value)) {
1545151869Sdavidxu		ts = it->it_time.it_value;
1546151869Sdavidxu		timespecsub(&ts, &cts);
1547151869Sdavidxu		TIMESPEC_TO_TIMEVAL(&tv, &ts);
1548151869Sdavidxu		callout_reset(&it->it_callout, tvtohz(&tv), realtimer_expire,
1549151576Sdavidxu 			it);
1550151576Sdavidxu	}
1551151576Sdavidxu}
1552151576Sdavidxu
1553151576Sdavidxuvoid
1554151576Sdavidxuitimer_fire(struct itimer *it)
1555151576Sdavidxu{
1556151576Sdavidxu	struct proc *p = it->it_proc;
1557213642Sdavidxu	struct thread *td;
1558151576Sdavidxu
1559151869Sdavidxu	if (it->it_sigev.sigev_notify == SIGEV_SIGNAL ||
1560151869Sdavidxu	    it->it_sigev.sigev_notify == SIGEV_THREAD_ID) {
1561213642Sdavidxu		if (sigev_findtd(p, &it->it_sigev, &td) != 0) {
1562213642Sdavidxu			ITIMER_LOCK(it);
1563213642Sdavidxu			timespecclear(&it->it_time.it_value);
1564213642Sdavidxu			timespecclear(&it->it_time.it_interval);
1565213642Sdavidxu			callout_stop(&it->it_callout);
1566213642Sdavidxu			ITIMER_UNLOCK(it);
1567213642Sdavidxu			return;
1568213642Sdavidxu		}
1569151993Sdavidxu		if (!KSI_ONQ(&it->it_ksi)) {
1570152983Sdavidxu			it->it_ksi.ksi_errno = 0;
1571213642Sdavidxu			ksiginfo_set_sigev(&it->it_ksi, &it->it_sigev);
1572213642Sdavidxu			tdsendsignal(p, td, it->it_ksi.ksi_signo, &it->it_ksi);
1573151993Sdavidxu		} else {
1574152983Sdavidxu			if (it->it_overrun < INT_MAX)
1575152983Sdavidxu				it->it_overrun++;
1576152983Sdavidxu			else
1577152983Sdavidxu				it->it_ksi.ksi_errno = ERANGE;
1578151576Sdavidxu		}
1579151576Sdavidxu		PROC_UNLOCK(p);
1580151576Sdavidxu	}
1581151576Sdavidxu}
1582151576Sdavidxu
1583151576Sdavidxustatic void
1584151576Sdavidxuitimers_alloc(struct proc *p)
1585151576Sdavidxu{
1586151585Sdavidxu	struct itimers *its;
1587151585Sdavidxu	int i;
1588151576Sdavidxu
1589151585Sdavidxu	its = malloc(sizeof (struct itimers), M_SUBPROC, M_WAITOK | M_ZERO);
1590151585Sdavidxu	LIST_INIT(&its->its_virtual);
1591151585Sdavidxu	LIST_INIT(&its->its_prof);
1592151585Sdavidxu	TAILQ_INIT(&its->its_worklist);
1593151585Sdavidxu	for (i = 0; i < TIMER_MAX; i++)
1594151585Sdavidxu		its->its_timers[i] = NULL;
1595151576Sdavidxu	PROC_LOCK(p);
1596151585Sdavidxu	if (p->p_itimers == NULL) {
1597151585Sdavidxu		p->p_itimers = its;
1598151576Sdavidxu		PROC_UNLOCK(p);
1599151585Sdavidxu	}
1600151585Sdavidxu	else {
1601151576Sdavidxu		PROC_UNLOCK(p);
1602151585Sdavidxu		free(its, M_SUBPROC);
1603151576Sdavidxu	}
1604151576Sdavidxu}
1605151576Sdavidxu
1606161302Snetchildstatic void
1607161302Snetchilditimers_event_hook_exec(void *arg, struct proc *p, struct image_params *imgp __unused)
1608161302Snetchild{
1609164713Sdavidxu	itimers_event_hook_exit(arg, p);
1610161302Snetchild}
1611161302Snetchild
1612151576Sdavidxu/* Clean up timers when some process events are being triggered. */
1613153259Sdavidxustatic void
1614161302Snetchilditimers_event_hook_exit(void *arg, struct proc *p)
1615151576Sdavidxu{
1616151576Sdavidxu	struct itimers *its;
1617151576Sdavidxu	struct itimer *it;
1618153267Sdavidxu	int event = (int)(intptr_t)arg;
1619151576Sdavidxu	int i;
1620151576Sdavidxu
1621151585Sdavidxu	if (p->p_itimers != NULL) {
1622151585Sdavidxu		its = p->p_itimers;
1623151576Sdavidxu		for (i = 0; i < MAX_CLOCKS; ++i) {
1624151576Sdavidxu			if (posix_clocks[i].event_hook != NULL)
1625151576Sdavidxu				CLOCK_CALL(i, event_hook, (p, i, event));
1626151576Sdavidxu		}
1627151576Sdavidxu		/*
1628151576Sdavidxu		 * According to susv3, XSI interval timers should be inherited
1629151576Sdavidxu		 * by new image.
1630151576Sdavidxu		 */
1631151576Sdavidxu		if (event == ITIMER_EV_EXEC)
1632151576Sdavidxu			i = 3;
1633151576Sdavidxu		else if (event == ITIMER_EV_EXIT)
1634151576Sdavidxu			i = 0;
1635151576Sdavidxu		else
1636151576Sdavidxu			panic("unhandled event");
1637151576Sdavidxu		for (; i < TIMER_MAX; ++i) {
1638164713Sdavidxu			if ((it = its->its_timers[i]) != NULL)
1639253530Skib				kern_ktimer_delete(curthread, i);
1640151576Sdavidxu		}
1641151576Sdavidxu		if (its->its_timers[0] == NULL &&
1642151576Sdavidxu		    its->its_timers[1] == NULL &&
1643151576Sdavidxu		    its->its_timers[2] == NULL) {
1644151585Sdavidxu			free(its, M_SUBPROC);
1645151585Sdavidxu			p->p_itimers = NULL;
1646151576Sdavidxu		}
1647151576Sdavidxu	}
1648151576Sdavidxu}
1649