> On Fri, 20 Nov 1998, Finn Arne Gangstad wrote:
>
> >If the timer was already pending, you have just DESTROYED its expires
> >value. This means you have no control over when it will expire at all,
>
> I don' t want to have control on its exipres value. Look at
> do_getitimer(). At do_getitimer() runtime, the other CPU could
> be running it_real_fn() and so we could have the same timer inserted two
> times in the timer list. This is the _only_ reason for adding that check.
> The other way is running the del_timer in do_getitimer() in a bh atomic
> context, but my way was more efficient because it would block nothing.
Maybe the solution for do_getitimer is something like this:
Make a new function timer_expires: (WARNING: untested code!)
int timer_expires(struct timer_list *timer, unsigned long *expires)
{
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&timerlist_lock, flags);
if (timer->prev) {
*expires = timer->expires;
ret = 1;
}
spin_unlock_irqrestore(&timerlist_lock, flags);
return ret;
}
and then change the code in do_getitimer to: (pseudo-diff format)
- register unsigned long val, interval;
+ register unsigned long interval;
+ unsigned long val;
switch (which) {
case ITIMER_REAL:
interval = current->it_real_incr;
val = 0;
- if (del_timer(¤t->real_timer)) {
+ if (timer_expires(¤t->real_timer, &val)) {
unsigned long now = jiffies;
- val = current->real_timer.expires;
- add_timer(¤t->real_timer);
/* look out for negative/zero itimer.. */
if (val <= now)
val = now+1;
val -= now;
}
break;
(val <= now) should be replaced by !time_after(val, now)
This looks cleaner than the current race-prone code..
As for setitimer, it could use mod_timer instead of add_timer.
- Finn Arne
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/