1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)kern_time.c 7.20 (Berkeley) 10/11/92 8 */ 9 10 #include <sys/param.h> 11 #include <sys/resourcevar.h> 12 #include <sys/kernel.h> 13 #include <sys/systm.h> 14 #include <sys/proc.h> 15 #include <sys/vnode.h> 16 17 #include <machine/cpu.h> 18 19 /* 20 * Time of day and interval timer support. 21 * 22 * These routines provide the kernel entry points to get and set 23 * the time-of-day and per-process interval timers. Subroutines 24 * here provide support for adding and subtracting timeval structures 25 * and decrementing interval timers, optionally reloading the interval 26 * timers when they expire. 27 */ 28 29 struct gettimeofday_args { 30 struct timeval *tp; 31 struct timezone *tzp; 32 }; 33 /* ARGSUSED */ 34 gettimeofday(p, uap, retval) 35 struct proc *p; 36 register struct gettimeofday_args *uap; 37 int *retval; 38 { 39 struct timeval atv; 40 int error = 0; 41 42 if (uap->tp) { 43 microtime(&atv); 44 if (error = copyout((caddr_t)&atv, (caddr_t)uap->tp, 45 sizeof (atv))) 46 return (error); 47 } 48 if (uap->tzp) 49 error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, 50 sizeof (tz)); 51 return (error); 52 } 53 54 struct settimeofday_args { 55 struct timeval *tv; 56 struct timezone *tzp; 57 }; 58 /* ARGSUSED */ 59 settimeofday(p, uap, retval) 60 struct proc *p; 61 struct settimeofday_args *uap; 62 int *retval; 63 { 64 struct timeval atv, delta; 65 struct timezone atz; 66 int error, s; 67 68 if (error = suser(p->p_ucred, &p->p_acflag)) 69 return (error); 70 /* Verify all parameters before changing time. */ 71 if (uap->tv && 72 (error = copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof(atv)))) 73 return (error); 74 if (uap->tzp && 75 (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz)))) 76 return (error); 77 if (uap->tv) { 78 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 79 s = splclock(); 80 /* nb. delta.tv_usec may be < 0, but this is OK here */ 81 delta.tv_sec = atv.tv_sec - time.tv_sec; 82 delta.tv_usec = atv.tv_usec - time.tv_usec; 83 time = atv; 84 (void) splsoftclock(); 85 timevaladd(&boottime, &delta); 86 timevalfix(&boottime); 87 timevaladd(&runtime, &delta); 88 timevalfix(&runtime); 89 LEASE_UPDATETIME(delta.tv_sec); 90 splx(s); 91 resettodr(); 92 } 93 if (uap->tzp) 94 tz = atz; 95 return (0); 96 } 97 98 extern int tickadj; /* "standard" clock skew, us./tick */ 99 int tickdelta; /* current clock skew, us. per tick */ 100 long timedelta; /* unapplied time correction, us. */ 101 long bigadj = 1000000; /* use 10x skew above bigadj us. */ 102 103 struct adjtime_args { 104 struct timeval *delta; 105 struct timeval *olddelta; 106 }; 107 /* ARGSUSED */ 108 adjtime(p, uap, retval) 109 struct proc *p; 110 register struct adjtime_args *uap; 111 int *retval; 112 { 113 struct timeval atv; 114 register long ndelta, ntickdelta, odelta; 115 int s, error; 116 117 if (error = suser(p->p_ucred, &p->p_acflag)) 118 return (error); 119 if (error = 120 copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))) 121 return (error); 122 123 /* 124 * Compute the total correction and the rate at which to apply it. 125 * Round the adjustment down to a whole multiple of the per-tick 126 * delta, so that after some number of incremental changes in 127 * hardclock(), tickdelta will become zero, lest the correction 128 * overshoot and start taking us away from the desired final time. 129 */ 130 ndelta = atv.tv_sec * 1000000 + atv.tv_usec; 131 if (ndelta > bigadj) 132 ntickdelta = 10 * tickadj; 133 else 134 ntickdelta = tickadj; 135 if (ndelta % ntickdelta) 136 ndelta = ndelta / ntickdelta * ntickdelta; 137 138 /* 139 * To make hardclock()'s job easier, make the per-tick delta negative 140 * if we want time to run slower; then hardclock can simply compute 141 * tick + tickdelta, and subtract tickdelta from timedelta. 142 */ 143 if (ndelta < 0) 144 ntickdelta = -ntickdelta; 145 s = splclock(); 146 odelta = timedelta; 147 timedelta = ndelta; 148 tickdelta = ntickdelta; 149 splx(s); 150 151 if (uap->olddelta) { 152 atv.tv_sec = odelta / 1000000; 153 atv.tv_usec = odelta % 1000000; 154 (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta, 155 sizeof(struct timeval)); 156 } 157 return (0); 158 } 159 160 /* 161 * Get value of an interval timer. The process virtual and 162 * profiling virtual time timers are kept in the p_stats area, since 163 * they can be swapped out. These are kept internally in the 164 * way they are specified externally: in time until they expire. 165 * 166 * The real time interval timer is kept in the process table slot 167 * for the process, and its value (it_value) is kept as an 168 * absolute time rather than as a delta, so that it is easy to keep 169 * periodic real-time signals from drifting. 170 * 171 * Virtual time timers are processed in the hardclock() routine of 172 * kern_clock.c. The real time timer is processed by a timeout 173 * routine, called from the softclock() routine. Since a callout 174 * may be delayed in real time due to interrupt processing in the system, 175 * it is possible for the real time timeout routine (realitexpire, given below), 176 * to be delayed in real time past when it is supposed to occur. It 177 * does not suffice, therefore, to reload the real timer .it_value from the 178 * real time timers .it_interval. Rather, we compute the next time in 179 * absolute time the timer should go off. 180 */ 181 struct getitimer_args { 182 u_int which; 183 struct itimerval *itv; 184 }; 185 /* ARGSUSED */ 186 getitimer(p, uap, retval) 187 struct proc *p; 188 register struct getitimer_args *uap; 189 int *retval; 190 { 191 struct itimerval aitv; 192 int s; 193 194 if (uap->which > ITIMER_PROF) 195 return (EINVAL); 196 s = splclock(); 197 if (uap->which == ITIMER_REAL) { 198 /* 199 * Convert from absoulte to relative time in .it_value 200 * part of real time timer. If time for real time timer 201 * has passed return 0, else return difference between 202 * current time and time for the timer to go off. 203 */ 204 aitv = p->p_realtimer; 205 if (timerisset(&aitv.it_value)) 206 if (timercmp(&aitv.it_value, &time, <)) 207 timerclear(&aitv.it_value); 208 else 209 timevalsub(&aitv.it_value, 210 (struct timeval *)&time); 211 } else 212 aitv = p->p_stats->p_timer[uap->which]; 213 splx(s); 214 return (copyout((caddr_t)&aitv, (caddr_t)uap->itv, 215 sizeof (struct itimerval))); 216 } 217 218 struct setitimer_args { 219 u_int which; 220 struct itimerval *itv, *oitv; 221 }; 222 /* ARGSUSED */ 223 setitimer(p, uap, retval) 224 struct proc *p; 225 register struct setitimer_args *uap; 226 int *retval; 227 { 228 struct itimerval aitv; 229 register struct itimerval *itvp; 230 int s, error; 231 232 if (uap->which > ITIMER_PROF) 233 return (EINVAL); 234 itvp = uap->itv; 235 if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv, 236 sizeof(struct itimerval)))) 237 return (error); 238 if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval))) 239 return (error); 240 if (itvp == 0) 241 return (0); 242 if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) 243 return (EINVAL); 244 s = splclock(); 245 if (uap->which == ITIMER_REAL) { 246 untimeout(realitexpire, (caddr_t)p); 247 if (timerisset(&aitv.it_value)) { 248 timevaladd(&aitv.it_value, (struct timeval *)&time); 249 timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value)); 250 } 251 p->p_realtimer = aitv; 252 } else 253 p->p_stats->p_timer[uap->which] = aitv; 254 splx(s); 255 return (0); 256 } 257 258 /* 259 * Real interval timer expired: 260 * send process whose timer expired an alarm signal. 261 * If time is not set up to reload, then just return. 262 * Else compute next time timer should go off which is > current time. 263 * This is where delay in processing this timeout causes multiple 264 * SIGALRM calls to be compressed into one. 265 */ 266 void 267 realitexpire(arg) 268 void *arg; 269 { 270 register struct proc *p; 271 int s; 272 273 p = (struct proc *)arg; 274 psignal(p, SIGALRM); 275 if (!timerisset(&p->p_realtimer.it_interval)) { 276 timerclear(&p->p_realtimer.it_value); 277 return; 278 } 279 for (;;) { 280 s = splclock(); 281 timevaladd(&p->p_realtimer.it_value, 282 &p->p_realtimer.it_interval); 283 if (timercmp(&p->p_realtimer.it_value, &time, >)) { 284 timeout(realitexpire, (caddr_t)p, 285 hzto(&p->p_realtimer.it_value)); 286 splx(s); 287 return; 288 } 289 splx(s); 290 } 291 } 292 293 /* 294 * Check that a proposed value to load into the .it_value or 295 * .it_interval part of an interval timer is acceptable, and 296 * fix it to have at least minimal value (i.e. if it is less 297 * than the resolution of the clock, round it up.) 298 */ 299 itimerfix(tv) 300 struct timeval *tv; 301 { 302 303 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 304 tv->tv_usec < 0 || tv->tv_usec >= 1000000) 305 return (EINVAL); 306 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 307 tv->tv_usec = tick; 308 return (0); 309 } 310 311 /* 312 * Decrement an interval timer by a specified number 313 * of microseconds, which must be less than a second, 314 * i.e. < 1000000. If the timer expires, then reload 315 * it. In this case, carry over (usec - old value) to 316 * reduce the value reloaded into the timer so that 317 * the timer does not drift. This routine assumes 318 * that it is called in a context where the timers 319 * on which it is operating cannot change in value. 320 */ 321 itimerdecr(itp, usec) 322 register struct itimerval *itp; 323 int usec; 324 { 325 326 if (itp->it_value.tv_usec < usec) { 327 if (itp->it_value.tv_sec == 0) { 328 /* expired, and already in next interval */ 329 usec -= itp->it_value.tv_usec; 330 goto expire; 331 } 332 itp->it_value.tv_usec += 1000000; 333 itp->it_value.tv_sec--; 334 } 335 itp->it_value.tv_usec -= usec; 336 usec = 0; 337 if (timerisset(&itp->it_value)) 338 return (1); 339 /* expired, exactly at end of interval */ 340 expire: 341 if (timerisset(&itp->it_interval)) { 342 itp->it_value = itp->it_interval; 343 itp->it_value.tv_usec -= usec; 344 if (itp->it_value.tv_usec < 0) { 345 itp->it_value.tv_usec += 1000000; 346 itp->it_value.tv_sec--; 347 } 348 } else 349 itp->it_value.tv_usec = 0; /* sec is already 0 */ 350 return (0); 351 } 352 353 /* 354 * Add and subtract routines for timevals. 355 * N.B.: subtract routine doesn't deal with 356 * results which are before the beginning, 357 * it just gets very confused in this case. 358 * Caveat emptor. 359 */ 360 timevaladd(t1, t2) 361 struct timeval *t1, *t2; 362 { 363 364 t1->tv_sec += t2->tv_sec; 365 t1->tv_usec += t2->tv_usec; 366 timevalfix(t1); 367 } 368 369 timevalsub(t1, t2) 370 struct timeval *t1, *t2; 371 { 372 373 t1->tv_sec -= t2->tv_sec; 374 t1->tv_usec -= t2->tv_usec; 375 timevalfix(t1); 376 } 377 378 timevalfix(t1) 379 struct timeval *t1; 380 { 381 382 if (t1->tv_usec < 0) { 383 t1->tv_sec--; 384 t1->tv_usec += 1000000; 385 } 386 if (t1->tv_usec >= 1000000) { 387 t1->tv_sec++; 388 t1->tv_usec -= 1000000; 389 } 390 } 391