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