| up ↑ |
I wrote these notes to record what I discovered when I investigated whether it is save to call a timer function like mod_timer while holding a spinlock that is also used by the timer handler. I was concerned that a deadlock might occur because each of these functions would need to lock a spinlock associated with the timer (see lock_timer_base). I was concerned about the following scenario:
Fortunately, deadlock is avoided by the way the function __run_timers is coded, so that the timer base spinlock is unlocked before each timer handler is called.
del_timer_sync loops and calls try_to_del_timer_sync until it succeeds.
try_to_del_timer_sync locks the spinlock of the timer base (an implementation), and checks whether the timer is currently running.
This is all done under the protection of the timer base spinlock, which is released before return from the function.
Observation: On an SMP system this function will loop until it succeeds, and each iteration of the loop will spin until the timer base spinlock is available.
mod_timer eventually calls __mod_timer, which locks the timer base spinlock, detaches the timer if it is pending, updates the necessary data, calls internal_add_timer to re-add the timer, and releases the spinlock.
add_timer calls __mod_timer to do the work. The only reall difference seems to be an optimization in mod_timer that returns immediately if the timer expiration time is just being set to the same value it already has.
Observation: Comments in the code state that mod_timer is more efficient than add_timer and go on to say that "if there are multiple unserialized concurrent users of the same timer, then mod_timer is the only safe way to modify the timeout, since add_timer cannot modify an already running timer." These comments seem to be no longer valid, except for the tiny optimization above.
| ($Id) |