lkml.org 
[lkml]   [2000]   [Jul]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[patch] timers
- 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
\
 
 \ /
  Last update: 2005-03-22 13:57    [W:0.055 / U:0.196 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site