kern_time.c revision 1.35
1/*	$NetBSD: kern_time.c,v 1.35 1998/07/31 22:50:51 perry Exp $	*/
2
3/*
4 * Copyright (c) 1982, 1986, 1989, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 *	@(#)kern_time.c	8.4 (Berkeley) 5/26/95
36 */
37
38#include "fs_nfs.h"
39#include "opt_nfsserver.h"
40
41#include <sys/param.h>
42#include <sys/resourcevar.h>
43#include <sys/kernel.h>
44#include <sys/systm.h>
45#include <sys/proc.h>
46#include <sys/vnode.h>
47#include <sys/signalvar.h>
48#include <sys/syslog.h>
49
50#include <sys/mount.h>
51#include <sys/syscallargs.h>
52
53#if defined(NFS) || defined(NFSSERVER)
54#include <nfs/rpcv2.h>
55#include <nfs/nfsproto.h>
56#include <nfs/nfs_var.h>
57#endif
58
59#include <machine/cpu.h>
60
61static int	settime __P((struct timeval *));
62
63/*
64 * Time of day and interval timer support.
65 *
66 * These routines provide the kernel entry points to get and set
67 * the time-of-day and per-process interval timers.  Subroutines
68 * here provide support for adding and subtracting timeval structures
69 * and decrementing interval timers, optionally reloading the interval
70 * timers when they expire.
71 */
72
73/* This function is used by clock_settime and settimeofday */
74static int
75settime(tv)
76	struct timeval *tv;
77{
78	struct timeval delta;
79	int s;
80
81	/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
82	s = splclock();
83	timersub(tv, &time, &delta);
84	if ((delta.tv_sec < 0 || delta.tv_usec < 0) && securelevel > 1)
85		return (EPERM);
86#ifdef notyet
87	if ((delta.tv_sec < 86400) && securelevel > 0)
88		return (EPERM);
89#endif
90	time = *tv;
91	(void) splsoftclock();
92	timeradd(&boottime, &delta, &boottime);
93	timeradd(&runtime, &delta, &runtime);
94#	if defined(NFS) || defined(NFSSERVER)
95		nqnfs_lease_updatetime(delta.tv_sec);
96#	endif
97	splx(s);
98	resettodr();
99	return (0);
100}
101
102/* ARGSUSED */
103int
104sys_clock_gettime(p, v, retval)
105	struct proc *p;
106	void *v;
107	register_t *retval;
108{
109	register struct sys_clock_gettime_args /* {
110		syscallarg(clockid_t) clock_id;
111		syscallarg(struct timespec *) tp;
112	} */ *uap = v;
113	clockid_t clock_id;
114	struct timeval atv;
115	struct timespec ats;
116
117	clock_id = SCARG(uap, clock_id);
118	if (clock_id != CLOCK_REALTIME)
119		return (EINVAL);
120
121	microtime(&atv);
122	TIMEVAL_TO_TIMESPEC(&atv,&ats);
123
124	return copyout(&ats, SCARG(uap, tp), sizeof(ats));
125}
126
127/* ARGSUSED */
128int
129sys_clock_settime(p, v, retval)
130	struct proc *p;
131	void *v;
132	register_t *retval;
133{
134	register struct sys_clock_settime_args /* {
135		syscallarg(clockid_t) clock_id;
136		syscallarg(const struct timespec *) tp;
137	} */ *uap = v;
138	clockid_t clock_id;
139	struct timeval atv;
140	struct timespec ats;
141	int error;
142
143	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
144		return (error);
145
146	clock_id = SCARG(uap, clock_id);
147	if (clock_id != CLOCK_REALTIME)
148		return (EINVAL);
149
150	if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
151		return (error);
152
153	TIMESPEC_TO_TIMEVAL(&atv,&ats);
154	if ((error = settime(&atv)))
155		return (error);
156
157	return 0;
158}
159
160int
161sys_clock_getres(p, v, retval)
162	struct proc *p;
163	void *v;
164	register_t *retval;
165{
166	register struct sys_clock_getres_args /* {
167		syscallarg(clockid_t) clock_id;
168		syscallarg(struct timespec *) tp;
169	} */ *uap = v;
170	clockid_t clock_id;
171	struct timespec ts;
172	int error = 0;
173
174	clock_id = SCARG(uap, clock_id);
175	if (clock_id != CLOCK_REALTIME)
176		return (EINVAL);
177
178	if (SCARG(uap, tp)) {
179		ts.tv_sec = 0;
180		ts.tv_nsec = 1000000000 / hz;
181
182		error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
183	}
184
185	return error;
186}
187
188/* ARGSUSED */
189int
190sys_nanosleep(p, v, retval)
191	struct proc *p;
192	void *v;
193	register_t *retval;
194{
195	static int nanowait;
196	register struct sys_nanosleep_args/* {
197		syscallarg(struct timespec *) rqtp;
198		syscallarg(struct timespec *) rmtp;
199	} */ *uap = v;
200	struct timespec rqt;
201	struct timespec rmt;
202	struct timeval atv, utv;
203	int error, s, timo;
204
205	error = copyin((caddr_t)SCARG(uap, rqtp), (caddr_t)&rqt,
206		       sizeof(struct timespec));
207	if (error)
208		return (error);
209
210	TIMESPEC_TO_TIMEVAL(&atv,&rqt)
211	if (itimerfix(&atv))
212		return (EINVAL);
213
214	s = splclock();
215	timeradd(&atv,&time,&atv);
216	timo = hzto(&atv);
217	/*
218	 * Avoid inadvertantly sleeping forever
219	 */
220	if (timo == 0)
221		timo = 1;
222	splx(s);
223
224	error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
225	if (error == ERESTART)
226		error = EINTR;
227	if (error == EWOULDBLOCK)
228		error = 0;
229
230	if (SCARG(uap, rmtp)) {
231		int error;
232
233		s = splclock();
234		utv = time;
235		splx(s);
236
237		timersub(&atv, &utv, &utv);
238		if (utv.tv_sec < 0)
239			timerclear(&utv);
240
241		TIMEVAL_TO_TIMESPEC(&utv,&rmt);
242		error = copyout((caddr_t)&rmt, (caddr_t)SCARG(uap,rmtp),
243			sizeof(rmt));
244		if (error)
245			return (error);
246	}
247
248	return error;
249}
250
251/* ARGSUSED */
252int
253sys_gettimeofday(p, v, retval)
254	struct proc *p;
255	void *v;
256	register_t *retval;
257{
258	register struct sys_gettimeofday_args /* {
259		syscallarg(struct timeval *) tp;
260		syscallarg(struct timezone *) tzp;
261	} */ *uap = v;
262	struct timeval atv;
263	int error = 0;
264	struct timezone tzfake;
265
266	if (SCARG(uap, tp)) {
267		microtime(&atv);
268		error = copyout(&atv, SCARG(uap, tp), sizeof(atv));
269		if (error)
270			return (error);
271	}
272	if (SCARG(uap, tzp)) {
273		/*
274		 * NetBSD has no kernel notion of time zone, so we just
275		 * fake up a timezone struct and return it if demanded.
276		 */
277		tzfake.tz_minuteswest = 0;
278		tzfake.tz_dsttime = 0;
279		error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake));
280	}
281	return (error);
282}
283
284/* ARGSUSED */
285int
286sys_settimeofday(p, v, retval)
287	struct proc *p;
288	void *v;
289	register_t *retval;
290{
291	struct sys_settimeofday_args /* {
292		syscallarg(const struct timeval *) tv;
293		syscallarg(const struct timezone *) tzp;
294	} */ *uap = v;
295	struct timeval atv;
296	struct timezone atz;
297	int error;
298
299	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
300		return (error);
301	/* Verify all parameters before changing time. */
302	if (SCARG(uap, tv) && (error = copyin(SCARG(uap, tv),
303	    &atv, sizeof(atv))))
304		return (error);
305	/* XXX since we don't use tz, probably no point in doing copyin. */
306	if (SCARG(uap, tzp) && (error = copyin(SCARG(uap, tzp),
307	    &atz, sizeof(atz))))
308		return (error);
309	if (SCARG(uap, tv))
310		if ((error = settime(&atv)))
311			return (error);
312	/*
313	 * NetBSD has no kernel notion of time zone, and only an
314	 * obsolete program would try to set it, so we log a warning.
315	 */
316	if (SCARG(uap, tzp))
317		log(LOG_WARNING, "pid %d attempted to set the "
318		    "(obsolete) kernel time zone\n", p->p_pid);
319	return (0);
320}
321
322int	tickdelta;			/* current clock skew, us. per tick */
323long	timedelta;			/* unapplied time correction, us. */
324long	bigadj = 1000000;		/* use 10x skew above bigadj us. */
325
326/* ARGSUSED */
327int
328sys_adjtime(p, v, retval)
329	struct proc *p;
330	void *v;
331	register_t *retval;
332{
333	register struct sys_adjtime_args /* {
334		syscallarg(const struct timeval *) delta;
335		syscallarg(struct timeval *) olddelta;
336	} */ *uap = v;
337	struct timeval atv;
338	register long ndelta, ntickdelta, odelta;
339	int s, error;
340
341	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
342		return (error);
343
344	error = copyin(SCARG(uap, delta), &atv, sizeof(struct timeval));
345	if (error)
346		return (error);
347
348	/*
349	 * Compute the total correction and the rate at which to apply it.
350	 * Round the adjustment down to a whole multiple of the per-tick
351	 * delta, so that after some number of incremental changes in
352	 * hardclock(), tickdelta will become zero, lest the correction
353	 * overshoot and start taking us away from the desired final time.
354	 */
355	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
356	if (ndelta > bigadj)
357		ntickdelta = 10 * tickadj;
358	else
359		ntickdelta = tickadj;
360	if (ndelta % ntickdelta)
361		ndelta = ndelta / ntickdelta * ntickdelta;
362
363	/*
364	 * To make hardclock()'s job easier, make the per-tick delta negative
365	 * if we want time to run slower; then hardclock can simply compute
366	 * tick + tickdelta, and subtract tickdelta from timedelta.
367	 */
368	if (ndelta < 0)
369		ntickdelta = -ntickdelta;
370	s = splclock();
371	odelta = timedelta;
372	timedelta = ndelta;
373	tickdelta = ntickdelta;
374	splx(s);
375
376	if (SCARG(uap, olddelta)) {
377		atv.tv_sec = odelta / 1000000;
378		atv.tv_usec = odelta % 1000000;
379		(void) copyout(&atv, SCARG(uap, olddelta),
380		    sizeof(struct timeval));
381	}
382	return (0);
383}
384
385/*
386 * Get value of an interval timer.  The process virtual and
387 * profiling virtual time timers are kept in the p_stats area, since
388 * they can be swapped out.  These are kept internally in the
389 * way they are specified externally: in time until they expire.
390 *
391 * The real time interval timer is kept in the process table slot
392 * for the process, and its value (it_value) is kept as an
393 * absolute time rather than as a delta, so that it is easy to keep
394 * periodic real-time signals from drifting.
395 *
396 * Virtual time timers are processed in the hardclock() routine of
397 * kern_clock.c.  The real time timer is processed by a timeout
398 * routine, called from the softclock() routine.  Since a callout
399 * may be delayed in real time due to interrupt processing in the system,
400 * it is possible for the real time timeout routine (realitexpire, given below),
401 * to be delayed in real time past when it is supposed to occur.  It
402 * does not suffice, therefore, to reload the real timer .it_value from the
403 * real time timers .it_interval.  Rather, we compute the next time in
404 * absolute time the timer should go off.
405 */
406/* ARGSUSED */
407int
408sys_getitimer(p, v, retval)
409	struct proc *p;
410	void *v;
411	register_t *retval;
412{
413	register struct sys_getitimer_args /* {
414		syscallarg(int) which;
415		syscallarg(struct itimerval *) itv;
416	} */ *uap = v;
417	int which = SCARG(uap, which);
418	struct itimerval aitv;
419	int s;
420
421	if ((u_int)which > ITIMER_PROF)
422		return (EINVAL);
423	s = splclock();
424	if (which == ITIMER_REAL) {
425		/*
426		 * Convert from absolute to relative time in .it_value
427		 * part of real time timer.  If time for real time timer
428		 * has passed return 0, else return difference between
429		 * current time and time for the timer to go off.
430		 */
431		aitv = p->p_realtimer;
432		if (timerisset(&aitv.it_value))
433			if (timercmp(&aitv.it_value, &time, <))
434				timerclear(&aitv.it_value);
435			else
436				timersub(&aitv.it_value, &time, &aitv.it_value);
437	} else
438		aitv = p->p_stats->p_timer[which];
439	splx(s);
440	return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)));
441}
442
443/* ARGSUSED */
444int
445sys_setitimer(p, v, retval)
446	struct proc *p;
447	register void *v;
448	register_t *retval;
449{
450	register struct sys_setitimer_args /* {
451		syscallarg(int) which;
452		syscallarg(const struct itimerval *) itv;
453		syscallarg(struct itimerval *) oitv;
454	} */ *uap = v;
455	int which = SCARG(uap, which);
456	struct sys_getitimer_args getargs;
457	struct itimerval aitv;
458	register const struct itimerval *itvp;
459	int s, error;
460
461	if ((u_int)which > ITIMER_PROF)
462		return (EINVAL);
463	itvp = SCARG(uap, itv);
464	if (itvp && (error = copyin(itvp, &aitv, sizeof(struct itimerval))))
465		return (error);
466	if (SCARG(uap, oitv) != NULL) {
467		SCARG(&getargs, which) = which;
468		SCARG(&getargs, itv) = SCARG(uap, oitv);
469		if ((error = sys_getitimer(p, &getargs, retval)) != 0)
470			return (error);
471	}
472	if (itvp == 0)
473		return (0);
474	if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
475		return (EINVAL);
476	s = splclock();
477	if (which == ITIMER_REAL) {
478		untimeout(realitexpire, p);
479		if (timerisset(&aitv.it_value)) {
480			timeradd(&aitv.it_value, &time, &aitv.it_value);
481			timeout(realitexpire, p, hzto(&aitv.it_value));
482		}
483		p->p_realtimer = aitv;
484	} else
485		p->p_stats->p_timer[which] = aitv;
486	splx(s);
487	return (0);
488}
489
490/*
491 * Real interval timer expired:
492 * send process whose timer expired an alarm signal.
493 * If time is not set up to reload, then just return.
494 * Else compute next time timer should go off which is > current time.
495 * This is where delay in processing this timeout causes multiple
496 * SIGALRM calls to be compressed into one.
497 */
498void
499realitexpire(arg)
500	void *arg;
501{
502	register struct proc *p;
503	int s;
504
505	p = (struct proc *)arg;
506	psignal(p, SIGALRM);
507	if (!timerisset(&p->p_realtimer.it_interval)) {
508		timerclear(&p->p_realtimer.it_value);
509		return;
510	}
511	for (;;) {
512		s = splclock();
513		timeradd(&p->p_realtimer.it_value,
514		    &p->p_realtimer.it_interval, &p->p_realtimer.it_value);
515		if (timercmp(&p->p_realtimer.it_value, &time, >)) {
516			timeout(realitexpire, p,
517			    hzto(&p->p_realtimer.it_value));
518			splx(s);
519			return;
520		}
521		splx(s);
522	}
523}
524
525/*
526 * Check that a proposed value to load into the .it_value or
527 * .it_interval part of an interval timer is acceptable, and
528 * fix it to have at least minimal value (i.e. if it is less
529 * than the resolution of the clock, round it up.)
530 */
531int
532itimerfix(tv)
533	struct timeval *tv;
534{
535
536	if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
537	    tv->tv_usec < 0 || tv->tv_usec >= 1000000)
538		return (EINVAL);
539	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
540		tv->tv_usec = tick;
541	return (0);
542}
543
544/*
545 * Decrement an interval timer by a specified number
546 * of microseconds, which must be less than a second,
547 * i.e. < 1000000.  If the timer expires, then reload
548 * it.  In this case, carry over (usec - old value) to
549 * reduce the value reloaded into the timer so that
550 * the timer does not drift.  This routine assumes
551 * that it is called in a context where the timers
552 * on which it is operating cannot change in value.
553 */
554int
555itimerdecr(itp, usec)
556	register struct itimerval *itp;
557	int usec;
558{
559
560	if (itp->it_value.tv_usec < usec) {
561		if (itp->it_value.tv_sec == 0) {
562			/* expired, and already in next interval */
563			usec -= itp->it_value.tv_usec;
564			goto expire;
565		}
566		itp->it_value.tv_usec += 1000000;
567		itp->it_value.tv_sec--;
568	}
569	itp->it_value.tv_usec -= usec;
570	usec = 0;
571	if (timerisset(&itp->it_value))
572		return (1);
573	/* expired, exactly at end of interval */
574expire:
575	if (timerisset(&itp->it_interval)) {
576		itp->it_value = itp->it_interval;
577		itp->it_value.tv_usec -= usec;
578		if (itp->it_value.tv_usec < 0) {
579			itp->it_value.tv_usec += 1000000;
580			itp->it_value.tv_sec--;
581		}
582	} else
583		itp->it_value.tv_usec = 0;		/* sec is already 0 */
584	return (0);
585}
586