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:
parent
fbdec13c62
commit
08fd92bac5
|
@ -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)));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue