xref: /csrg-svn/sys/kern/kern_time.c (revision 8114)
1 /*	kern_time.c	5.5	82/09/08	*/
2 
3 #include "../h/param.h"
4 #include "../h/dir.h"		/* XXX */
5 #include "../h/user.h"
6 #include "../h/kernel.h"
7 #include "../h/reg.h"
8 #include "../h/inode.h"
9 #include "../h/proc.h"
10 
11 /*
12  * Time of day and interval timer support.
13  */
14 
15 gettimeofday()
16 {
17 	register struct a {
18 		struct	timeval *tp;
19 		struct	timezone *tzp;
20 	} *uap = (struct a *)u.u_ap;
21 	struct timeval atv;
22 	int s;
23 
24 	s = spl7(); atv = time; splx(s);
25 	if (copyout((caddr_t)&atv, (caddr_t)uap->tp, sizeof (atv))) {
26 		u.u_error = EFAULT;
27 		return;
28 	}
29 	if (uap->tzp == 0)
30 		return;
31 	/* SHOULD HAVE PER-PROCESS TIMEZONE */
32 	if (copyout((caddr_t)&tz, uap->tzp, sizeof (tz))) {
33 		u.u_error = EFAULT;
34 		return;
35 	}
36 }
37 
38 settimeofday()
39 {
40 	register struct a {
41 		struct	timeval *tv;
42 		struct	timezone *tzp;
43 	} *uap = (struct a *)u.u_ap;
44 	struct timeval atv;
45 	struct timezone atz;
46 
47 	if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (struct timeval))) {
48 		u.u_error = EFAULT;
49 		return;
50 	}
51 	setthetime(&atv);
52 	if (uap->tzp && suser()) {
53 		if (copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof (atz))) {
54 			u.u_error = EFAULT;
55 			return;
56 		}
57 	}
58 }
59 
60 setthetime(tv)
61 	struct timeval *tv;
62 {
63 	register int delta;
64 	int s;
65 
66 	if (!suser())
67 		return;
68 	boottime.tv_sec += tv->tv_sec - time.tv_sec;
69 	s = spl7(); time = *tv; splx(s);
70 	clockset();
71 }
72 
73 timevaladd(t1, t2)
74 	struct timeval *t1, *t2;
75 {
76 
77 	t1->tv_sec += t2->tv_sec;
78 	t1->tv_usec += t2->tv_usec;
79 	timevalfix(t1);
80 }
81 
82 timevalsub(t1, t2)
83 	struct timeval *t1, *t2;
84 {
85 
86 	t1->tv_sec -= t2->tv_sec;
87 	t1->tv_usec -= t2->tv_usec;
88 	timevalfix(t1);
89 }
90 
91 timevalfix(t1)
92 	struct timeval *t1;
93 {
94 
95 	if (t1->tv_usec < 0) {
96 		t1->tv_sec--;
97 		t1->tv_usec += 1000000;
98 	}
99 	if (t1->tv_usec >= 1000000) {
100 		t1->tv_sec++;
101 		t1->tv_usec -= 1000000;
102 	}
103 }
104 
105 getitimer()
106 {
107 	register struct a {
108 		u_int	which;
109 		struct	itimerval *itv;
110 	} *uap = (struct a *)u.u_ap;
111 	struct itimerval aitv;
112 	int s;
113 
114 	if (uap->which > 2) {
115 		u.u_error = EINVAL;
116 		return;
117 	}
118 	s = spl7();
119 	if (uap->which == ITIMER_REAL) {
120 		aitv = u.u_procp->p_realtimer;
121 		if (timerisset(&aitv.it_value))
122 			if (timercmp(&aitv.it_value, &time, <))
123 				timerclear(&aitv.it_value);
124 			else
125 				timevalsub(&aitv.it_value, &time);
126 	} else
127 		aitv = u.u_timer[uap->which];
128 	splx(s);
129 	if (copyout((caddr_t)&aitv, uap->itv, sizeof (struct itimerval)))
130 		u.u_error = EFAULT;
131 	splx(s);
132 }
133 
134 setitimer()
135 {
136 	register struct a {
137 		u_int	which;
138 		struct	itimerval *itv, *oitv;
139 	} *uap = (struct a *)u.u_ap;
140 	struct itimerval aitv;
141 	int s;
142 	register struct proc *p = u.u_procp;
143 
144 	if (uap->which > 2) {
145 		u.u_error = EINVAL;
146 		return;
147 	}
148 	if (copyin((caddr_t)uap->itv, (caddr_t)&aitv,
149 	    sizeof (struct itimerval))) {
150 		u.u_error = EFAULT;
151 		return;
152 	}
153 	if (uap->oitv) {
154 		uap->itv = uap->oitv;
155 		getitimer();
156 	}
157 	if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) {
158 		u.u_error = EINVAL;
159 		return;
160 	}
161 	s = spl7();
162 	if (uap->which == ITIMER_REAL) {
163 		untimeout(unrto, p);
164 		if (timerisset(&aitv.it_value)) {
165 			timevaladd(&aitv.it_value, &time);
166 			timeout(unrto, p, hzto(&aitv.it_value));
167 		}
168 		p->p_realtimer = aitv;
169 	} else
170 		u.u_timer[uap->which] = aitv;
171 	splx(s);
172 }
173 
174 unrto(p)
175 	register struct proc *p;
176 {
177 	int s;
178 
179 	psignal(p, SIGALRM);
180 	if (!timerisset(&p->p_realtimer.it_interval)) {
181 		timerclear(&p->p_realtimer.it_value);
182 		return;
183 	}
184 	for (;;) {
185 		s = spl7();
186 		timevaladd(&p->p_realtimer.it_value,
187 		    &p->p_realtimer.it_interval);
188 		if (timercmp(&p->p_realtimer.it_value, &time, >)) {
189 			timeout(unrto, p, hzto(&p->p_realtimer.it_value));
190 			splx(s);
191 			return;
192 		}
193 		splx(s);
194 	}
195 }
196 
197 itimerfix(tv)
198 	struct timeval *tv;
199 {
200 
201 	if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
202 	    tv->tv_usec < 0 || tv->tv_usec >= 1000000)
203 		return (EINVAL);
204 	if (tv->tv_sec == 0 && tv->tv_usec < tick)
205 		tv->tv_usec = tick;
206 	return (0);
207 }
208 
209 itimerdecr(itp, usec)
210 	register struct itimerval *itp;
211 	int usec;
212 {
213 
214 	if (itp->it_value.tv_usec < usec) {
215 		if (itp->it_value.tv_sec == 0) {
216 			usec -= itp->it_value.tv_usec;
217 			goto expire;
218 		}
219 		itp->it_value.tv_usec += 1000000;
220 		itp->it_value.tv_sec--;
221 	}
222 	itp->it_value.tv_usec -= usec;
223 	usec = 0;
224 	if (timerisset(&itp->it_value))
225 		return (1);
226 expire:
227 	if (timerisset(&itp->it_interval)) {
228 		itp->it_value = itp->it_interval;
229 		itp->it_value.tv_usec -= usec;
230 		if (itp->it_value.tv_usec < 0) {
231 			itp->it_value.tv_usec += 1000000;
232 			itp->it_value.tv_sec--;
233 		}
234 	} else
235 		itp->it_value.tv_usec = 0;
236 	return (0);
237 }
238 
239 #ifndef NOCOMPAT
240 otime()
241 {
242 
243 	u.u_r.r_time = time.tv_sec;
244 }
245 
246 ostime()
247 {
248 	register struct a {
249 		int	time;
250 	} *uap = (struct a *)u.u_ap;
251 	struct timeval tv;
252 
253 	tv.tv_sec = uap->time;
254 	tv.tv_usec = 0;
255 	setthetime(&tv);
256 }
257 
258 #include "../h/timeb.h"
259 
260 oftime()
261 {
262 	register struct a {
263 		struct	timeb	*tp;
264 	} *uap;
265 	struct timeb t;
266 
267 	uap = (struct a *)u.u_ap;
268 	(void) spl7();
269 	t.time = time.tv_sec;
270 	t.millitm = time.tv_usec / 1000;
271 	(void) spl0();
272 	t.timezone = tz.tz_minuteswest;
273 	t.dstflag = tz.tz_dsttime;
274 	if (copyout((caddr_t)&t, (caddr_t)uap->tp, sizeof(t)) < 0)
275 		u.u_error = EFAULT;
276 }
277 #endif
278