label_t now structure
[unix-history] / usr / src / sys / kern / kern_time.c
CommitLineData
d01b68d6 1/* kern_time.c 5.5 82/09/08 */
aac7ea5b
BJ
2
3#include "../h/param.h"
b6f30e0a 4#include "../h/dir.h" /* XXX */
aac7ea5b 5#include "../h/user.h"
b6f30e0a 6#include "../h/kernel.h"
aac7ea5b
BJ
7#include "../h/reg.h"
8#include "../h/inode.h"
9#include "../h/proc.h"
b6f30e0a 10
1edb1cf8
BJ
11/*
12 * Time of day and interval timer support.
13 */
14
b6f30e0a 15gettimeofday()
4147b3f6 16{
b6f30e0a
BJ
17 register struct a {
18 struct timeval *tp;
19 struct timezone *tzp;
20 } *uap = (struct a *)u.u_ap;
21 struct timeval atv;
1edb1cf8 22 int s;
4147b3f6 23
1edb1cf8 24 s = spl7(); atv = time; splx(s);
b6f30e0a
BJ
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;
1edb1cf8 31 /* SHOULD HAVE PER-PROCESS TIMEZONE */
b6f30e0a
BJ
32 if (copyout((caddr_t)&tz, uap->tzp, sizeof (tz))) {
33 u.u_error = EFAULT;
34 return;
35 }
4147b3f6
BJ
36}
37
b6f30e0a 38settimeofday()
aac7ea5b 39{
b6f30e0a 40 register struct a {
1edb1cf8
BJ
41 struct timeval *tv;
42 struct timezone *tzp;
b6f30e0a
BJ
43 } *uap = (struct a *)u.u_ap;
44 struct timeval atv;
45 struct timezone atz;
4147b3f6 46
b6f30e0a
BJ
47 if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (struct timeval))) {
48 u.u_error = EFAULT;
49 return;
50 }
1edb1cf8
BJ
51 setthetime(&atv);
52 if (uap->tzp && suser()) {
b6f30e0a
BJ
53 if (copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof (atz))) {
54 u.u_error = EFAULT;
55 return;
56 }
b6f30e0a 57 }
4147b3f6
BJ
58}
59
1edb1cf8
BJ
60setthetime(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
b6f30e0a
BJ
73timevaladd(t1, t2)
74 struct timeval *t1, *t2;
4147b3f6
BJ
75{
76
b6f30e0a 77 t1->tv_sec += t2->tv_sec;
1edb1cf8 78 t1->tv_usec += t2->tv_usec;
b6f30e0a 79 timevalfix(t1);
4147b3f6
BJ
80}
81
b6f30e0a
BJ
82timevalsub(t1, t2)
83 struct timeval *t1, *t2;
4147b3f6
BJ
84{
85
b6f30e0a 86 t1->tv_sec -= t2->tv_sec;
1edb1cf8 87 t1->tv_usec -= t2->tv_usec;
b6f30e0a 88 timevalfix(t1);
aac7ea5b
BJ
89}
90
b6f30e0a
BJ
91timevalfix(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
105getitimer()
aac7ea5b
BJ
106{
107 register struct a {
b6f30e0a
BJ
108 u_int which;
109 struct itimerval *itv;
110 } *uap = (struct a *)u.u_ap;
d01b68d6 111 struct itimerval aitv;
b6f30e0a 112 int s;
aac7ea5b 113
b6f30e0a
BJ
114 if (uap->which > 2) {
115 u.u_error = EINVAL;
116 return;
aac7ea5b 117 }
b6f30e0a 118 s = spl7();
d01b68d6
BJ
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)))
aac7ea5b 130 u.u_error = EFAULT;
b6f30e0a 131 splx(s);
aac7ea5b
BJ
132}
133
b6f30e0a 134setitimer()
aac7ea5b
BJ
135{
136 register struct a {
b6f30e0a 137 u_int which;
1edb1cf8 138 struct itimerval *itv, *oitv;
b6f30e0a
BJ
139 } *uap = (struct a *)u.u_ap;
140 struct itimerval aitv;
141 int s;
d01b68d6 142 register struct proc *p = u.u_procp;
aac7ea5b 143
b6f30e0a
BJ
144 if (uap->which > 2) {
145 u.u_error = EINVAL;
1edb1cf8 146 return;
b6f30e0a
BJ
147 }
148 if (copyin((caddr_t)uap->itv, (caddr_t)&aitv,
149 sizeof (struct itimerval))) {
150 u.u_error = EFAULT;
1edb1cf8
BJ
151 return;
152 }
153 if (uap->oitv) {
154 uap->itv = uap->oitv;
155 getitimer();
b6f30e0a 156 }
1edb1cf8
BJ
157 if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) {
158 u.u_error = EINVAL;
159 return;
160 }
161 s = spl7();
d01b68d6
BJ
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
1edb1cf8 170 u.u_timer[uap->which] = aitv;
b6f30e0a 171 splx(s);
b6f30e0a
BJ
172}
173
d01b68d6
BJ
174unrto(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
1edb1cf8
BJ
197itimerfix(tv)
198 struct timeval *tv;
b6f30e0a 199{
b6f30e0a 200
d01b68d6
BJ
201 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
202 tv->tv_usec < 0 || tv->tv_usec >= 1000000)
1edb1cf8
BJ
203 return (EINVAL);
204 if (tv->tv_sec == 0 && tv->tv_usec < tick)
205 tv->tv_usec = tick;
206 return (0);
b6f30e0a
BJ
207}
208
209itimerdecr(itp, usec)
210 register struct itimerval *itp;
211 int usec;
212{
213
1edb1cf8
BJ
214 if (itp->it_value.tv_usec < usec) {
215 if (itp->it_value.tv_sec == 0) {
216 usec -= itp->it_value.tv_usec;
b6f30e0a 217 goto expire;
1edb1cf8
BJ
218 }
219 itp->it_value.tv_usec += 1000000;
220 itp->it_value.tv_sec--;
aac7ea5b 221 }
1edb1cf8
BJ
222 itp->it_value.tv_usec -= usec;
223 usec = 0;
224 if (timerisset(&itp->it_value))
b6f30e0a
BJ
225 return (1);
226expire:
1edb1cf8
BJ
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;
b6f30e0a 236 return (0);
aac7ea5b
BJ
237}
238
b6f30e0a
BJ
239#ifndef NOCOMPAT
240otime()
241{
242
243 u.u_r.r_time = time.tv_sec;
244}
245
1edb1cf8
BJ
246ostime()
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
b6f30e0a
BJ
258#include "../h/timeb.h"
259
260oftime()
aac7ea5b
BJ
261{
262 register struct a {
b6f30e0a 263 struct timeb *tp;
aac7ea5b 264 } *uap;
b6f30e0a 265 struct timeb t;
aac7ea5b 266
aac7ea5b 267 uap = (struct a *)u.u_ap;
b6f30e0a
BJ
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)
aac7ea5b
BJ
275 u.u_error = EFAULT;
276}
1edb1cf8 277#endif