1 /* kern_time.c 5.6 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 oalarm() 279 { 280 register struct a { 281 int deltat; 282 } *uap = (struct a *)u.u_ap; 283 register struct proc *p = u.u_procp; 284 struct timeval atv; 285 int s = spl7(); 286 287 untimeout(unrto, p); 288 timerclear(&p->p_realtimer.it_interval); 289 u.u_r.r_val1 = 0; 290 if (timerisset(&p->p_realtimer.it_value) && 291 timercmp(&p->p_realtimer.it_value, &time, >)) 292 u.u_r.r_val1 = p->p_realtimer.it_value.tv_sec - time.tv_sec; 293 if (uap->deltat == 0) { 294 splx(s); 295 return; 296 } 297 p->p_realtimer.it_value = time; 298 p->p_realtimer.it_value.tv_sec += uap->deltat; 299 timeout(unrto, p, hzto(&p->p_realtimer.it_value)); 300 splx(s); 301 } 302 303