summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_time.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_time.c')
-rw-r--r--sys/kern/kern_time.c89
1 files changed, 55 insertions, 34 deletions
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);
}
/*
OpenPOWER on IntegriCloud