И таймер запускается! Следует обратить внимание на важность значения поля expired
Иногда может потребоваться изменить момент времени срабатывания таймера, который уже активизирован. В ядре реализована функция mod_timer
mod_timer(&my_timer, jiffies + new_delay); /* установка нового времени
срабатывания */
Функция mod_timer
mod_timer активизирует его. Эта функция возвращает значение 0, если таймер был неактивным, и значение 1, если таймер был активным. В любом случае перед возвратом из функции mod_timer таймер будут активизирован, и его время срабатывания будет установлено в указанное значение.Для того чтобы деактивизировать таймер до момента его срабатывания, необходимо использовать функцию del_timer
del_timer(&my_timer);
Эта функция работает как с активными, так и неактивными таймерами. Если таймер уже неактивен, то функция возвращает значение 0, в другом случае возвращается значение 1. Следует обратить внимание, что нет необходимости вызывать эту функцию для таймеров, интервал ожидания которых истек, так как они автоматически деактивизируются.
При удалении таймеров потенциально может возникнуть состояние конкуренции. Когда функция del_timer
del_timer_sync:del_timer_sync(&my_timer);
В отличие от функции del_timer
del_timer_sync не может вызываться из контекста прерывания.Состояния конкуренции, связанные с таймерами
Так как таймеры выполняются асинхронно по отношению к выполняемому в данный момент коду, то потенциально могут возникнуть несколько типов состояний конкуренции за ресурсы. Во-первых, никогда нельзя использовать следующий код, как замену функции mod_timer
del_timer(my_timer);
my_timer->expires = jiffies + new_delay;
add_timer(my_timer);
Во-вторых, практически во всех случаях следует использовать функцию del_timer_sync
del_timer. В противном случае нельзя гарантировать, что обработчик таймера в данный момент не выполняется. Представьте себе, что после удаления таймера код освободит память или каким-либо другим образом вмешается в ресурсы, которые использует обработчик таймера. Поэтому синхронная версия более предпочтительна.Наконец, необходимо гарантировать защиту всех совместно используемых дан- пых, к которым обращается функция-обработчик таймера. Ядро выполняет эту функцию асинхронно по отношению к другому коду. Совместно используемые данные должны защищаться так, как рассматривалось в главах 8 и 9.
Реализация таймеров
Ядро выполняет обработчики таймеров в контексте обработчика отложенного прерывания после завершения обработки прерывания таймера. Обработчик прерывания таймера вызывает функцию update_process_times
run_local_timers, имеющую следующий вид.void run_local_timers(void) {
raise_softirq(TIMER_SOFTIRQ);
}
Отложенное прерывание с номером TIMER_SOFTIRQ
run_timer_softirq. Эта функция выполняет на локальном процессоре обработчики всех таймеров, для которых истек период времени ожидания (если такие есть).