[patch] timers

From: Andrew Morton (andrewm@uow.edu.au)
Date: Sat Jul 15 2000 - 08:15:32 EDT

  • Next message: Rasmus Andersen: "Compile error in drivers/net/arcnet/com20020isa_setup.c"

    - Moves timer_enter(), timer_exit(), timer_is_running() and
      timer_synchronize() out of include/linux/timer.h. Also
      unexports running_timer.

      I suggest all this stuff not be exported to the world - it's
      delicate and will have to be changed if we go for concurrent
      timer handlers in 2.5.

    - Adds an extra `volatile' to the running_timer decl. Right
      now we're telling the compiler that the timer_list is
      volatile, not the pointer to it. Future improvements in gcc
      could cause lockups.

    - Implements and exports sync_timers(). This is a quite inefficient
      function, but Rusty requires it for

        "module unload, where module count is decremented by timer;
         timer must be finished. Also:

            `if (!del_timer(timer)) sync_timers();' == del_timer_sync()

         for self-destructing timers."

    Patch against test5-pre1 is attached.

    --- linux-2.4.0-test5-pre1/include/linux/timer.h Tue Jul 11 22:21:17 2000
    +++ linux-akpm/include/linux/timer.h Sat Jul 15 21:33:11 2000
    @@ -24,14 +24,23 @@
             void (*function)(unsigned long);
     };
     
    -extern volatile struct timer_list *running_timer;
     extern void add_timer(struct timer_list * timer);
     extern int del_timer(struct timer_list * timer);
     
    +#ifdef CONFIG_SMP
    +extern int del_timer_sync(struct timer_list * timer);
    +extern void sync_timers(void);
    +#else
    +#define del_timer_sync(t) del_timer(t)
    +#define sync_timers() do { } while (0)
    +#endif
    +
     /*
      * mod_timer is a more efficient way to update the expire field of an
      * active timer (if the timer is inactive it will be activated)
    - * mod_timer(a,b) is equivalent to del_timer(a); a->expires = b; add_timer(a)
    + * mod_timer(a,b) is equivalent to del_timer(a); a->expires = b; add_timer(a).
    + * If the timer is known to be not pending (ie, in the handler), mod_timer
    + * is less efficient than a->expires = b; add_timer(a).
      */
     int mod_timer(struct timer_list *timer, unsigned long expires);
     
    @@ -46,20 +55,6 @@
     {
             return timer->list.next != NULL;
     }
    -
    -#ifdef CONFIG_SMP
    -#define timer_enter(t) do { running_timer = t; mb(); } while (0)
    -#define timer_exit() do { running_timer = NULL; } while (0)
    -#define timer_is_running(t) (running_timer == t)
    -#define timer_synchronize(t) while (timer_is_running(t)) barrier()
    -extern int del_timer_sync(struct timer_list * timer);
    -#else
    -#define timer_enter(t) do { } while (0)
    -#define timer_exit() do { } while (0)
    -#define timer_is_running(t) (0)
    -#define timer_synchronize(t) do { (void)(t); barrier(); } while(0)
    -#define del_timer_sync(t) del_timer(t)
    -#endif
     
     /*
      * These inlines deal with timer wrapping correctly. You are
    --- linux-2.4.0-test5-pre1/kernel/timer.c Sat Jul 15 19:36:09 2000
    +++ linux-akpm/kernel/timer.c Sat Jul 15 21:33:11 2000
    @@ -162,7 +162,19 @@
     
     /* Initialize both explicitly - let's try to have them in the same cache line */
     spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED;
    -volatile struct timer_list *running_timer = NULL;
    +volatile struct timer_list * volatile running_timer = NULL;
    +
    +#ifdef CONFIG_SMP
    +#define timer_enter(t) do { running_timer = t; mb(); } while (0)
    +#define timer_exit() do { running_timer = NULL; } while (0)
    +#define timer_is_running(t) (running_timer == t)
    +#define timer_synchronize(t) while (timer_is_running(t)) barrier()
    +#else
    +#define timer_enter(t) do { } while (0)
    +#define timer_exit() do { } while (0)
    +#define timer_is_running(t) (0)
    +#define timer_synchronize(t) do { (void)(t); barrier(); } while(0)
    +#endif
     
     void add_timer(struct timer_list *timer)
     {
    @@ -216,6 +228,11 @@
     }
     
     #ifdef CONFIG_SMP
    +void sync_timers(void)
    +{
    + spin_unlock_wait(&global_bh_lock);
    +}
    +
     /*
      * SMP specific function to delete periodic timer.
      * Caller must disable by some means restarting the timer

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



    This archive was generated by hypermail 2b29 : Sat Jul 15 2000 - 15:47:18 EDT