Commit d912d1ff218195c248c770eb677726695e07aa40

Authored by George Anzinger
Committed by Linus Torvalds
1 parent b7343f01e3

[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>

Showing 1 changed file with 16 additions and 21 deletions Side-by-side Diff

... ... @@ -112,28 +112,11 @@
112 112 return error;
113 113 }
114 114  
115   -/*
116   - * Called with P->sighand->siglock held and P->signal->real_timer inactive.
117   - * If interval is nonzero, arm the timer for interval ticks from now.
118   - */
119   -static inline void it_real_arm(struct task_struct *p, unsigned long interval)
120   -{
121   - p->signal->it_real_value = interval; /* XXX unnecessary field?? */
122   - if (interval == 0)
123   - return;
124   - if (interval > (unsigned long) LONG_MAX)
125   - interval = LONG_MAX;
126   - /* the "+ 1" below makes sure that the timer doesn't go off before
127   - * the interval requested. This could happen if
128   - * time requested % (usecs per jiffy) is more than the usecs left
129   - * in the current jiffy */
130   - p->signal->real_timer.expires = jiffies + interval + 1;
131   - add_timer(&p->signal->real_timer);
132   -}
133 115  
134 116 void it_real_fn(unsigned long __data)
135 117 {
136 118 struct task_struct * p = (struct task_struct *) __data;
  119 + unsigned long inc = p->signal->it_real_incr;
137 120  
138 121 send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
139 122  
140 123  
141 124  
... ... @@ -141,14 +124,23 @@
141 124 * Now restart the timer if necessary. We don't need any locking
142 125 * here because do_setitimer makes sure we have finished running
143 126 * before it touches anything.
  127 + * Note, we KNOW we are (or should be) at a jiffie edge here so
  128 + * we don't need the +1 stuff. Also, we want to use the prior
  129 + * expire value so as to not "slip" a jiffie if we are late.
  130 + * Deal with requesting a time prior to "now" here rather than
  131 + * in add_timer.
144 132 */
145   - it_real_arm(p, p->signal->it_real_incr);
  133 + if (!inc)
  134 + return;
  135 + while (time_before_eq(p->signal->real_timer.expires, jiffies))
  136 + p->signal->real_timer.expires += inc;
  137 + add_timer(&p->signal->real_timer);
146 138 }
147 139  
148 140 int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
149 141 {
150 142 struct task_struct *tsk = current;
151   - unsigned long val, interval;
  143 + unsigned long val, interval, expires;
152 144 cputime_t cval, cinterval, nval, ninterval;
153 145  
154 146 switch (which) {
... ... @@ -164,7 +156,10 @@
164 156 }
165 157 tsk->signal->it_real_incr =
166 158 timeval_to_jiffies(&value->it_interval);
167   - it_real_arm(tsk, timeval_to_jiffies(&value->it_value));
  159 + expires = timeval_to_jiffies(&value->it_value);
  160 + if (expires)
  161 + mod_timer(&tsk->signal->real_timer,
  162 + jiffies + 1 + expires);
168 163 spin_unlock_irq(&tsk->sighand->siglock);
169 164 if (ovalue) {
170 165 jiffies_to_timeval(val, &ovalue->it_value);