[PATCH] itimer fixes
Fix the recent off-by-one fix in the itimer code: 1. The repeating timer is figured using the requested time (not +1 as we know where we are in the jiffie). 2. The tests for interval too large are left to the time_val to jiffie code. Signed-off-by: George Anzinger <george@mvista.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
b7343f01e3
commit
d912d1ff21
@ -112,28 +112,11 @@ asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Called with P->sighand->siglock held and P->signal->real_timer inactive.
|
|
||||||
* If interval is nonzero, arm the timer for interval ticks from now.
|
|
||||||
*/
|
|
||||||
static inline void it_real_arm(struct task_struct *p, unsigned long interval)
|
|
||||||
{
|
|
||||||
p->signal->it_real_value = interval; /* XXX unnecessary field?? */
|
|
||||||
if (interval == 0)
|
|
||||||
return;
|
|
||||||
if (interval > (unsigned long) LONG_MAX)
|
|
||||||
interval = LONG_MAX;
|
|
||||||
/* the "+ 1" below makes sure that the timer doesn't go off before
|
|
||||||
* the interval requested. This could happen if
|
|
||||||
* time requested % (usecs per jiffy) is more than the usecs left
|
|
||||||
* in the current jiffy */
|
|
||||||
p->signal->real_timer.expires = jiffies + interval + 1;
|
|
||||||
add_timer(&p->signal->real_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void it_real_fn(unsigned long __data)
|
void it_real_fn(unsigned long __data)
|
||||||
{
|
{
|
||||||
struct task_struct * p = (struct task_struct *) __data;
|
struct task_struct * p = (struct task_struct *) __data;
|
||||||
|
unsigned long inc = p->signal->it_real_incr;
|
||||||
|
|
||||||
send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
|
send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
|
||||||
|
|
||||||
@ -141,14 +124,23 @@ void it_real_fn(unsigned long __data)
|
|||||||
* Now restart the timer if necessary. We don't need any locking
|
* Now restart the timer if necessary. We don't need any locking
|
||||||
* here because do_setitimer makes sure we have finished running
|
* here because do_setitimer makes sure we have finished running
|
||||||
* before it touches anything.
|
* before it touches anything.
|
||||||
|
* Note, we KNOW we are (or should be) at a jiffie edge here so
|
||||||
|
* we don't need the +1 stuff. Also, we want to use the prior
|
||||||
|
* expire value so as to not "slip" a jiffie if we are late.
|
||||||
|
* Deal with requesting a time prior to "now" here rather than
|
||||||
|
* in add_timer.
|
||||||
*/
|
*/
|
||||||
it_real_arm(p, p->signal->it_real_incr);
|
if (!inc)
|
||||||
|
return;
|
||||||
|
while (time_before_eq(p->signal->real_timer.expires, jiffies))
|
||||||
|
p->signal->real_timer.expires += inc;
|
||||||
|
add_timer(&p->signal->real_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
|
int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
|
||||||
{
|
{
|
||||||
struct task_struct *tsk = current;
|
struct task_struct *tsk = current;
|
||||||
unsigned long val, interval;
|
unsigned long val, interval, expires;
|
||||||
cputime_t cval, cinterval, nval, ninterval;
|
cputime_t cval, cinterval, nval, ninterval;
|
||||||
|
|
||||||
switch (which) {
|
switch (which) {
|
||||||
@ -164,7 +156,10 @@ again:
|
|||||||
}
|
}
|
||||||
tsk->signal->it_real_incr =
|
tsk->signal->it_real_incr =
|
||||||
timeval_to_jiffies(&value->it_interval);
|
timeval_to_jiffies(&value->it_interval);
|
||||||
it_real_arm(tsk, timeval_to_jiffies(&value->it_value));
|
expires = timeval_to_jiffies(&value->it_value);
|
||||||
|
if (expires)
|
||||||
|
mod_timer(&tsk->signal->real_timer,
|
||||||
|
jiffies + 1 + expires);
|
||||||
spin_unlock_irq(&tsk->sighand->siglock);
|
spin_unlock_irq(&tsk->sighand->siglock);
|
||||||
if (ovalue) {
|
if (ovalue) {
|
||||||
jiffies_to_timeval(val, &ovalue->it_value);
|
jiffies_to_timeval(val, &ovalue->it_value);
|
||||||
|
Loading…
Reference in New Issue
Block a user