+ if (uap->which > ITIMER_PROF) {
+ u.u_error = EINVAL;
+ return;
+ }
+ s = splclock();
+ if (uap->which == ITIMER_REAL) {
+ /*
+ * Convert from absoulte to relative time in .it_value
+ * part of real time timer. If time for real time timer
+ * has passed return 0, else return difference between
+ * current time and time for the timer to go off.
+ */
+ aitv = u.u_procp->p_realtimer;
+ if (timerisset(&aitv.it_value))
+ if (timercmp(&aitv.it_value, &time, <))
+ timerclear(&aitv.it_value);
+ else
+ timevalsub(&aitv.it_value, &time);
+ } else
+ aitv = u.u_timer[uap->which];
+ splx(s);
+ u.u_error = copyout((caddr_t)&aitv, (caddr_t)uap->itv,
+ sizeof (struct itimerval));
+}
+
+setitimer()
+{
+ register struct a {
+ u_int which;
+ struct itimerval *itv, *oitv;
+ } *uap = (struct a *)u.u_ap;
+ struct itimerval aitv;
+ register struct itimerval *itvp;
+ int s;
+ register struct proc *p = u.u_procp;
+
+ if (uap->which > ITIMER_PROF) {
+ u.u_error = EINVAL;
+ return;
+ }
+ itvp = uap->itv;
+ if (itvp && (u.u_error = copyin((caddr_t)itvp, (caddr_t)&aitv,
+ sizeof(struct itimerval))))
+ return;
+ if (uap->itv = uap->oitv) {
+ getitimer();
+ if (u.u_error)
+ return;
+ }
+ if (itvp == 0)
+ return;
+ if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) {
+ u.u_error = EINVAL;
+ return;
+ }
+ s = splclock();
+ if (uap->which == ITIMER_REAL) {
+ untimeout(realitexpire, (caddr_t)p);
+ if (timerisset(&aitv.it_value)) {
+ timevaladd(&aitv.it_value, &time);
+ timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value));
+ }
+ p->p_realtimer = aitv;
+ } else
+ u.u_timer[uap->which] = aitv;
+ splx(s);