summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/compat/linux/linux_misc.c97
-rw-r--r--sys/kern/kern_time.c89
-rw-r--r--sys/sys/systm.h3
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);
OpenPOWER on IntegriCloud