[patch] timers

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


- 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 - 21:00:21 EST