Messages in this thread | | | Date | Fri, 01 Apr 2005 15:59:46 +0400 | From | Oleg Nesterov <> | Subject | Re: [RFC][PATCH] timers fixes/improvements |
| |
Here it is code snippets for easier review.
typedef struct timer_base_s { spinlock_t lock; struct timer_list *running_timer; } timer_base_t;
struct tvec_t_base_s { timer_base_t t_base; ... } tvec_bases[];
struct timer_list { ... timer_base_t *_base; };
int timer_pending(struct timer_list * timer) { return timer->entry.next != NULL; }
void init_timer(struct timer_list *timer) { timer->entry.next = NULL; timer->_base = &per_cpu(tvec_bases).t_base; }
timer_base_t *lock_timer_base(struct timer_list *timer, unsigned long *flags) { for (;;) { timer_base_t *base = timer->_base; if (base != NULL) { spin_lock_irqsave(&base->lock, *flags); if (base == timer->_base) return base; spin_unlock_irqrestore(&base->lock, *flags); } } }
int __mod_timer(struct timer_list *timer, unsigned long expires) { timer_base_t *base; tvec_base_t *new_base; int ret = -1;
do { base = lock_timer_base(timer, &flags); new_base = &__get_cpu_var(tvec_bases);
/* Ensure the timer is serialized. */ if (base != &new_base->t_base && base->running_timer == timer) goto unlock;
ret = 0; if (timer_pending(timer)) { __list_del(timer->entry); ret = 1; }
if (base != &new_base->t_base) { timer->_base = NULL; spin_unlock(&base->lock); base = &new_base->t_base; spin_lock(&base->lock); timer->_base = base; }
timer->expires = expires; internal_add_timer(new_base, timer); unlock: spin_unlock_irqrestore(&base->lock, flags); } while (ret < 0);
return ret; }
void detach_timer(struct timer_list *timer) { __list_del(timer->entry); entry->next = NULL; }
int del_timer(struct timer_list *timer) { int ret = 0;
if (timer_pending(timer)) { timer_base_t *base = lock_timer_base(timer); if (timer_pending(timer)) { detach_timer(timer); ret = 1; } spin_unlock_irqrestore(&base->lock, flags); }
return ret; }
int del_timer_sync(struct timer_list *timer) { int ret = -1;
do { timer_base_t *base = lock_timer_base(timer);
if (base->running_timer == timer) goto unlock;
ret = 0; if (timer_pending(timer)) { detach_timer(timer); ret = 1; } unlock: spin_unlock_irqrestore(&base->lock, flags); } while (ret < 0);
return ret; }
void __run_timers(tvec_base_t *base) { spin_lock_irq(&base->t_base.lock);
for_each_expired_timer(timer) { base->t_base.running_timer = timer; detach_timer(timer); spin_unlock(&base->t_base.lock); timer->function(data); spin_lock(&base->t_base.lock); } } - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |