diff options
-rw-r--r-- | sys/compat/linux/linux_misc.c | 97 | ||||
-rw-r--r-- | sys/kern/kern_time.c | 89 | ||||
-rw-r--r-- | sys/sys/systm.h | 3 |
3 files changed, 91 insertions, 98 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 0921907..cb77fe3 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -950,97 +950,66 @@ struct l_itimerval { l_timeval it_value; }; +#define B2L_ITIMERVAL(bip, lip) \ + (bip)->it_interval.tv_sec = (lip)->it_interval.tv_sec; \ + (bip)->it_interval.tv_usec = (lip)->it_interval.tv_usec; \ + (bip)->it_value.tv_sec = (lip)->it_value.tv_sec; \ + (bip)->it_value.tv_usec = (lip)->it_value.tv_usec; + int linux_setitimer(struct thread *td, struct linux_setitimer_args *uap) { int error; - caddr_t sg; - struct l_itimerval *lp, *lop, ls; - struct itimerval *p = NULL, *op = NULL, s; + struct l_itimerval ls; + struct itimerval aitv, oitv; #ifdef DEBUG if (ldebug(setitimer)) printf(ARGS(setitimer, "%p, %p"), (void *)uap->itv, (void *)uap->oitv); #endif - lp = uap->itv; - if (lp != NULL) { - sg = stackgap_init(); - p = stackgap_alloc(&sg, sizeof(struct itimerval)); - uap->itv = (struct l_itimerval *)p; - error = copyin(lp, &ls, sizeof(ls)); - if (error != 0) - return (error); - s.it_interval.tv_sec = ls.it_interval.tv_sec; - s.it_interval.tv_usec = ls.it_interval.tv_usec; - s.it_value.tv_sec = ls.it_value.tv_sec; - s.it_value.tv_usec = ls.it_value.tv_usec; - error = copyout(&s, p, sizeof(s)); - if (error != 0) - return (error); -#ifdef DEBUG - if (ldebug(setitimer)) { - printf("setitimer: value: sec: %ld, usec: %ld\n", - s.it_value.tv_sec, s.it_value.tv_usec); - printf("setitimer: interval: sec: %ld, usec: %ld\n", - s.it_interval.tv_sec, s.it_interval.tv_usec); - } -#endif - } - lop = uap->oitv; - if (lop != NULL) { - sg = stackgap_init(); - op = stackgap_alloc(&sg, sizeof(struct itimerval)); - uap->oitv = (struct l_itimerval *)op; + + if (uap->itv == NULL) { + uap->itv = uap->oitv; + return (linux_getitimer(td, (struct linux_getitimer_args *)uap)); } - error = setitimer(td, (struct setitimer_args *) uap); + + error = copyin(uap->itv, &ls, sizeof(ls)); if (error != 0) return (error); - if (lop != NULL) { - error = copyin(op, &s, sizeof(s)); - if (error != 0) - return (error); - ls.it_interval.tv_sec = s.it_interval.tv_sec; - ls.it_interval.tv_usec = s.it_interval.tv_usec; - ls.it_value.tv_sec = s.it_value.tv_sec; - ls.it_value.tv_usec = s.it_value.tv_usec; - error = copyout(&ls, lop, sizeof(ls)); + B2L_ITIMERVAL(&aitv, &ls); +#ifdef DEBUG + if (ldebug(setitimer)) { + printf("setitimer: value: sec: %ld, usec: %ld\n", + aitv.it_value.tv_sec, aitv.it_value.tv_usec); + printf("setitimer: interval: sec: %ld, usec: %ld\n", + aitv.it_interval.tv_sec, aitv.it_interval.tv_usec); } - return (error); +#endif + error = kern_setitimer(td, uap->which, &aitv, &oitv); + if (error != 0 || uap->oitv == NULL) + return (error); + B2L_ITIMERVAL(&ls, &oitv); + + return (copyout(&ls, uap->oitv, sizeof(ls))); } int linux_getitimer(struct thread *td, struct linux_getitimer_args *uap) { int error; - caddr_t sg; - struct l_itimerval *lp, ls; - struct itimerval *p = NULL, s; + struct l_itimerval ls; + struct itimerval aitv; #ifdef DEBUG if (ldebug(getitimer)) printf(ARGS(getitimer, "%p"), (void *)uap->itv); #endif - lp = uap->itv; - if (lp != NULL) { - sg = stackgap_init(); - p = stackgap_alloc(&sg, sizeof(struct itimerval)); - uap->itv = (struct l_itimerval *)p; - } - error = getitimer(td, (struct getitimer_args *) uap); + error = kern_getitimer(td, uap->which, &aitv); if (error != 0) return (error); - if (lp != NULL) { - error = copyin(p, &s, sizeof(s)); - if (error != 0) - return (error); - ls.it_interval.tv_sec = s.it_interval.tv_sec; - ls.it_interval.tv_usec = s.it_interval.tv_usec; - ls.it_value.tv_sec = s.it_value.tv_sec; - ls.it_value.tv_usec = s.it_value.tv_usec; - error = copyout(&ls, lp, sizeof(ls)); - } - return (error); + B2L_ITIMERVAL(&ls, &aitv); + return (copyout(&ls, uap->itv, sizeof(ls))); } #ifndef __alpha__ diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 4e6fe7f..c05732d 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -437,14 +437,25 @@ struct getitimer_args { int getitimer(struct thread *td, struct getitimer_args *uap) { + int error; + struct itimerval aitv; + + error = kern_getitimer(td, uap->which, &aitv); + if (error != 0) + return (error); + return (copyout(&aitv, uap->itv, sizeof (struct itimerval))); +} + +int +kern_getitimer(struct thread *td, u_int which, struct itimerval *aitv) +{ struct proc *p = td->td_proc; struct timeval ctv; - struct itimerval aitv; - if (uap->which > ITIMER_PROF) + if (which > ITIMER_PROF) return (EINVAL); - if (uap->which == ITIMER_REAL) { + if (which == ITIMER_REAL) { /* * Convert from absolute to relative time in .it_value * part of real time timer. If time for real time timer @@ -452,21 +463,21 @@ getitimer(struct thread *td, struct getitimer_args *uap) * current time and time for the timer to go off. */ PROC_LOCK(p); - aitv = p->p_realtimer; + *aitv = p->p_realtimer; PROC_UNLOCK(p); - if (timevalisset(&aitv.it_value)) { + if (timevalisset(&aitv->it_value)) { getmicrouptime(&ctv); - if (timevalcmp(&aitv.it_value, &ctv, <)) - timevalclear(&aitv.it_value); + if (timevalcmp(&aitv->it_value, &ctv, <)) + timevalclear(&aitv->it_value); else - timevalsub(&aitv.it_value, &ctv); + timevalsub(&aitv->it_value, &ctv); } } else { mtx_lock_spin(&sched_lock); - aitv = p->p_stats->p_timer[uap->which]; + *aitv = p->p_stats->p_timer[which]; mtx_unlock_spin(&sched_lock); } - return (copyout(&aitv, uap->itv, sizeof (struct itimerval))); + return (0); } #ifndef _SYS_SYSPROTO_H_ @@ -475,61 +486,71 @@ struct setitimer_args { struct itimerval *itv, *oitv; }; #endif + /* * MPSAFE */ int setitimer(struct thread *td, struct setitimer_args *uap) { - struct proc *p = td->td_proc; - struct itimerval aitv, oitv; - struct timeval ctv; int error; + struct itimerval aitv, oitv; if (uap->itv == NULL) { uap->itv = uap->oitv; return (getitimer(td, (struct getitimer_args *)uap)); } - if (uap->which > ITIMER_PROF) - return (EINVAL); if ((error = copyin(uap->itv, &aitv, sizeof(struct itimerval)))) return (error); - if (itimerfix(&aitv.it_value)) + error = kern_setitimer(td, uap->which, &aitv, &oitv); + if (error != 0 || uap->oitv == NULL) + return (error); + + return (copyout(&oitv, uap->oitv, sizeof(struct itimerval))); +} + +int +kern_setitimer(struct thread *td, u_int which, struct itimerval *aitv, struct itimerval *oitv) +{ + struct proc *p = td->td_proc; + struct timeval ctv; + + if (which > ITIMER_PROF) return (EINVAL); - if (!timevalisset(&aitv.it_value)) - timevalclear(&aitv.it_interval); - else if (itimerfix(&aitv.it_interval)) + if (itimerfix(&aitv->it_value)) + return (EINVAL); + if (!timevalisset(&aitv->it_value)) + timevalclear(&aitv->it_interval); + else if (itimerfix(&aitv->it_interval)) return (EINVAL); - if (uap->which == ITIMER_REAL) { + if (which == ITIMER_REAL) { PROC_LOCK(p); if (timevalisset(&p->p_realtimer.it_value)) callout_stop(&p->p_itcallout); getmicrouptime(&ctv); - if (timevalisset(&aitv.it_value)) { - callout_reset(&p->p_itcallout, tvtohz(&aitv.it_value), + if (timevalisset(&aitv->it_value)) { + callout_reset(&p->p_itcallout, tvtohz(&aitv->it_value), realitexpire, p); - timevaladd(&aitv.it_value, &ctv); + timevaladd(&aitv->it_value, &ctv); } - oitv = p->p_realtimer; - p->p_realtimer = aitv; + *oitv = p->p_realtimer; + p->p_realtimer = *aitv; PROC_UNLOCK(p); - if (timevalisset(&oitv.it_value)) { - if (timevalcmp(&oitv.it_value, &ctv, <)) - timevalclear(&oitv.it_value); + if (timevalisset(&oitv->it_value)) { + if (timevalcmp(&oitv->it_value, &ctv, <)) + timevalclear(&oitv->it_value); else - timevalsub(&oitv.it_value, &ctv); + timevalsub(&oitv->it_value, &ctv); } } else { mtx_lock_spin(&sched_lock); - oitv = p->p_stats->p_timer[uap->which]; - p->p_stats->p_timer[uap->which] = aitv; + *oitv = p->p_stats->p_timer[which]; + p->p_stats->p_timer[which] = *aitv; mtx_unlock_spin(&sched_lock); } - if (uap->oitv == NULL) - return (0); - return (copyout(&oitv, uap->oitv, sizeof(struct itimerval))); + return (0); } /* diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 36a8416..4b7dfd9 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -115,6 +115,7 @@ struct tty; struct ucred; struct uio; struct _jmp_buf; +struct itimerval; int setjmp(struct _jmp_buf *); void longjmp(struct _jmp_buf *, int) __dead2; @@ -199,6 +200,8 @@ int suword32(void *base, int32_t word); int suword64(void *base, int64_t word); intptr_t casuptr(intptr_t *p, intptr_t old, intptr_t new); +int kern_getitimer(struct thread *, u_int, struct itimerval *); +int kern_setitimer(struct thread *, u_int, struct itimerval *, struct itimerval *); void realitexpire(void *); void hardclock(struct clockframe *frame); |