lkml.org 
[lkml]   [2005]   [Apr]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [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/

    \
     
     \ /
      Last update: 2005-04-06 13:31    [W:0.032 / U:0.232 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site