summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_time.c
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2005-01-25 21:28:28 +0000
committersobomax <sobomax@FreeBSD.org>2005-01-25 21:28:28 +0000
commit35611d3699c36115663062a3dfab7643e7b1606c (patch)
tree456c8ac6de6b93d9e82d010bb3c8fd3b1845a31e /sys/kern/kern_time.c
parent9748840f3a756ba1575a89356fd7bdfec8d28705 (diff)
downloadFreeBSD-src-35611d3699c36115663062a3dfab7643e7b1606c.zip
FreeBSD-src-35611d3699c36115663062a3dfab7643e7b1606c.tar.gz
Split out kernel side of {get,set}itimer(2) into two parts: the first that
pops data from the userland and pushes results back and the second which does actual processing. Use the latter to eliminate stackgap in the linux wrappers of those syscalls. MFC after: 2 weeks
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