int del_timer(struct timer_list *timer)
{
unsigned long flags;
tvec_base_t *base;
check_timer(timer);
repeat:
base = timer->base;
if (!base)
return 0;
spin_lock_irqsave(&base->lock, flags);
if (base != timer->base) {
spin_unlock_irqrestore(&base->lock, flags);
goto repeat;
}
list_del(&timer->entry);
/* Need to make sure that anybody who sees a NULL base also sees the list ops */
smp_wmb();
timer->base = NULL;
spin_unlock_irqrestore(&base->lock, flags);
return 1;
}
EXPORT_SYMBOL(del_timer);
#ifdef CONFIG_SMP
/***
* del_timer_sync - deactivate a timer and wait for the handler to finish.
* @timer: the timer to be deactivated
*
* This function only differs from del_timer() on SMP: besides deactivating
* the timer it also makes sure the handler has finished executing on other
* CPUs.
*
* Synchronization rules: callers must prevent restarting of the timer,
* otherwise this function is meaningless. It must not be called from
* interrupt contexts. The caller must not hold locks which would prevent
* completion of the timer's handler. Upon exit the timer is not queued and
* the handler is not running on any CPU.
*
* The function returns whether it has deactivated a pending timer or not.
*
* del_timer_sync() is slow and complicated because it copes with timer
* handlers which re-arm the timer (periodic timers). If the timer handler
* is known to not do this (a single shot timer) then use
* del_singleshot_timer_sync() instead.
*/
int del_timer_sync(struct timer_list *timer)
{
tvec_base_t *base;
int i, ret = 0;
check_timer(timer);
del_again:
ret += del_timer(timer);
for_each_online_cpu(i) {
base = &per_cpu(tvec_bases, i);
if (base->running_timer == timer) {
while (base->running_timer == timer) {
cpu_relax();
preempt_check_resched();
}
break;
}
}
smp_rmb();
if (timer_pending(timer))
goto del_again;
return ret;
}
{
unsigned long flags;
tvec_base_t *base;
check_timer(timer);
repeat:
base = timer->base;
if (!base)
return 0;
spin_lock_irqsave(&base->lock, flags);
if (base != timer->base) {
spin_unlock_irqrestore(&base->lock, flags);
goto repeat;
}
list_del(&timer->entry);
/* Need to make sure that anybody who sees a NULL base also sees the list ops */
smp_wmb();
timer->base = NULL;
spin_unlock_irqrestore(&base->lock, flags);
return 1;
}
EXPORT_SYMBOL(del_timer);
#ifdef CONFIG_SMP
/***
* del_timer_sync - deactivate a timer and wait for the handler to finish.
* @timer: the timer to be deactivated
*
* This function only differs from del_timer() on SMP: besides deactivating
* the timer it also makes sure the handler has finished executing on other
* CPUs.
*
* Synchronization rules: callers must prevent restarting of the timer,
* otherwise this function is meaningless. It must not be called from
* interrupt contexts. The caller must not hold locks which would prevent
* completion of the timer's handler. Upon exit the timer is not queued and
* the handler is not running on any CPU.
*
* The function returns whether it has deactivated a pending timer or not.
*
* del_timer_sync() is slow and complicated because it copes with timer
* handlers which re-arm the timer (periodic timers). If the timer handler
* is known to not do this (a single shot timer) then use
* del_singleshot_timer_sync() instead.
*/
int del_timer_sync(struct timer_list *timer)
{
tvec_base_t *base;
int i, ret = 0;
check_timer(timer);
del_again:
ret += del_timer(timer);
for_each_online_cpu(i) {
base = &per_cpu(tvec_bases, i);
if (base->running_timer == timer) {
while (base->running_timer == timer) {
cpu_relax();
preempt_check_resched();
}
break;
}
}
smp_rmb();
if (timer_pending(timer))
goto del_again;
return ret;
}