Split sys_getitimer and sys_setitimer to make it possible to share the

relevant code with the COMPAT_NETBSD32 version, and make the latter use
the new functions.

This fixes netbsd32_setitimer() which had drifted from the native syscall
and did not work properly anymore.
This commit is contained in:
cube 2005-07-11 19:50:42 +00:00
parent fbdec13c62
commit 08fd92bac5
3 changed files with 53 additions and 109 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: netbsd32_time.c,v 1.9 2005/05/31 00:41:09 christos Exp $ */
/* $NetBSD: netbsd32_time.c,v 1.10 2005/07/11 19:50:42 cube Exp $ */
/*
* Copyright (c) 1998, 2001 Matthew R. Green
@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: netbsd32_time.c,v 1.9 2005/05/31 00:41:09 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: netbsd32_time.c,v 1.10 2005/07/11 19:50:42 cube Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ntp.h"
@ -286,81 +286,30 @@ netbsd32_setitimer(l, v, retval)
syscallarg(netbsd32_itimervalp_t) oitv;
} */ *uap = v;
struct proc *p = l->l_proc;
struct netbsd32_itimerval s32it, *itvp;
struct netbsd32_itimerval s32it, *itv32;
int which = SCARG(uap, which);
struct netbsd32_getitimer_args getargs;
struct itimerval aitv;
int s, error;
struct ptimer *pt;
int error;
if ((u_int)which > ITIMER_PROF)
return (EINVAL);
itvp = (struct netbsd32_itimerval *)NETBSD32PTR64(SCARG(uap, itv));
if (itvp && (error = copyin(itvp, &s32it, sizeof(s32it))))
return (error);
netbsd32_to_itimerval(&s32it, &aitv);
itv32 = (struct netbsd32_itimerval *)NETBSD32PTR64(SCARG(uap, itv));
if (itv32) {
if ((error = copyin(itv32, &s32it, sizeof(s32it))))
return (error);
netbsd32_to_itimerval(&s32it, &aitv);
}
if (SCARG(uap, oitv) != 0) {
SCARG(&getargs, which) = which;
SCARG(&getargs, itv) = SCARG(uap, oitv);
if ((error = netbsd32_getitimer(l, &getargs, retval)) != 0)
return (error);
}
if (itvp == 0)
return (0);
if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
return (EINVAL);
if (itv32 == 0)
return 0;
/* XXX there should be a way to share code with kern_time */
/* XXX just copied some from there */
/*
* Don't bother allocating data structures if the process just
* wants to clear the timer.
*/
if (!timerisset(&aitv.it_value) &&
((p->p_timers == NULL) || (p->p_timers->pts_timers[which] == NULL)))
return (0);
if (p->p_timers == NULL)
timers_alloc(p);
if (p->p_timers->pts_timers[which] == NULL) {
pt = pool_get(&ptimer_pool, PR_WAITOK);
callout_init(&pt->pt_ch);
pt->pt_ev.sigev_notify = SIGEV_SIGNAL;
pt->pt_overruns = 0;
pt->pt_proc = p;
pt->pt_type = which;
switch (which) {
case ITIMER_REAL:
pt->pt_ev.sigev_signo = SIGALRM;
break;
case ITIMER_VIRTUAL:
pt->pt_ev.sigev_signo = SIGVTALRM;
break;
case ITIMER_PROF:
pt->pt_ev.sigev_signo = SIGPROF;
break;
}
} else
pt = p->p_timers->pts_timers[which];
pt->pt_time = aitv;
p->p_timers->pts_timers[which] = pt;
if (which == ITIMER_REAL) {
s = splclock();
callout_stop(&pt->pt_ch);
if (timerisset(&pt->pt_time.it_value)) {
timeradd(&pt->pt_time.it_value, &time,
&pt->pt_time.it_value);
/*
* Don't need to check hzto() return value, here.
* callout_reset() does it for us.
*/
callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value),
realtimerexpire, pt);
}
splx(s);
}
return (0);
return dosetitimer(p, which, &aitv);
}
int
@ -374,39 +323,14 @@ netbsd32_getitimer(l, v, retval)
syscallarg(netbsd32_itimervalp_t) itv;
} */ *uap = v;
struct proc *p = l->l_proc;
int which = SCARG(uap, which);
struct netbsd32_itimerval s32it;
struct itimerval aitv;
int s;
int error;
if ((u_int)which > ITIMER_PROF)
return (EINVAL);
error = dogetitimer(p, SCARG(uap, which), &aitv);
if (error)
return error;
/* XXX same as setitimer */
if ((p->p_timers == NULL) || (p->p_timers->pts_timers[which] == NULL)) {
timerclear(&aitv.it_value);
timerclear(&aitv.it_interval);
} else {
s = splclock();
if (which == ITIMER_REAL) {
/*
* Convert from absolute 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 = p->p_timers->pts_timers[ITIMER_REAL]->pt_time;
if (timerisset(&aitv.it_value)) {
if (timercmp(&aitv.it_value, &time, <))
timerclear(&aitv.it_value);
else
timersub(&aitv.it_value, &time, &aitv.it_value);
}
} else
aitv = p->p_timers->pts_timers[which]->pt_time;
splx(s);
}
netbsd32_from_itimerval(&aitv, &s32it);
return (copyout(&s32it, (caddr_t)NETBSD32PTR64(SCARG(uap, itv)),
sizeof(s32it)));

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_time.c,v 1.90 2005/06/23 23:15:12 thorpej Exp $ */
/* $NetBSD: kern_time.c,v 1.91 2005/07/11 19:50:42 cube Exp $ */
/*-
* Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc.
@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.90 2005/06/23 23:15:12 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.91 2005/07/11 19:50:42 cube Exp $");
#include "fs_nfs.h"
#include "opt_nfs.h"
@ -936,24 +936,32 @@ sys_getitimer(struct lwp *l, void *v, register_t *retval)
} */ *uap = v;
struct proc *p = l->l_proc;
struct itimerval aitv;
int s, which;
int error;
which = SCARG(uap, which);
error = dogetitimer(p, SCARG(uap, which), &aitv);
if (error)
return error;
return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)));
}
int
dogetitimer(struct proc *p, int which, struct itimerval *itvp)
{
int s;
if ((u_int)which > ITIMER_PROF)
return (EINVAL);
if ((p->p_timers == NULL) || (p->p_timers->pts_timers[which] == NULL)){
timerclear(&aitv.it_value);
timerclear(&aitv.it_interval);
timerclear(&itvp->it_value);
timerclear(&itvp->it_interval);
} else {
s = splclock();
timer_gettime(p->p_timers->pts_timers[which], &aitv);
timer_gettime(p->p_timers->pts_timers[which], itvp);
splx(s);
}
return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)));
return 0;
}
/* BSD routine to set/arm an interval timer. */
@ -969,10 +977,9 @@ sys_setitimer(struct lwp *l, void *v, register_t *retval)
struct proc *p = l->l_proc;
int which = SCARG(uap, which);
struct sys_getitimer_args getargs;
struct itimerval aitv;
const struct itimerval *itvp;
struct ptimer *pt;
int s, error;
struct itimerval aitv;
int error;
if ((u_int)which > ITIMER_PROF)
return (EINVAL);
@ -988,14 +995,24 @@ sys_setitimer(struct lwp *l, void *v, register_t *retval)
}
if (itvp == 0)
return (0);
if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
return dosetitimer(p, which, &aitv);
}
int
dosetitimer(struct proc *p, int which, struct itimerval *itvp)
{
struct ptimer *pt;
int s;
if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval))
return (EINVAL);
/*
* Don't bother allocating data structures if the process just
* wants to clear the timer.
*/
if (!timerisset(&aitv.it_value) &&
if (!timerisset(&itvp->it_value) &&
((p->p_timers == NULL) ||(p->p_timers->pts_timers[which] == NULL)))
return (0);
@ -1026,7 +1043,7 @@ sys_setitimer(struct lwp *l, void *v, register_t *retval)
} else
pt = p->p_timers->pts_timers[which];
pt->pt_time = aitv;
pt->pt_time = *itvp;
p->p_timers->pts_timers[which] = pt;
s = splclock();

View File

@ -1,4 +1,4 @@
/* $NetBSD: time.h,v 1.46 2005/03/17 20:51:00 kleink Exp $ */
/* $NetBSD: time.h,v 1.47 2005/07/11 19:50:42 cube Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@ -225,6 +225,9 @@ void timer_gettime(struct ptimer *, struct itimerval *);
void timers_alloc(struct proc *);
void timers_free(struct proc *, int);
void realtimerexpire(void *);
int dogetitimer(struct proc *, int, struct itimerval *);
int dosetitimer(struct proc *, int, struct itimerval *);
#else /* !_KERNEL */
#ifndef _STANDALONE