* (обработчик прерывания rtc и обработчик прерывания системного
* таймера могут выполняться одновременно на двух разных
* процессорах). Следовательно, необходимо сериализировать доступ
* к микросхеме с помощью спин-блокировки rtc_lock, что должно
* быть сделано для всех аппаратных платформ в коде работы с
* таймером. (Тело функции set_rtc_mmss() ищите в файлах
* ./arch/XXXX/kernel/time.c)
*/
static irqreturn_t rtc_interrupt(int irq, void *dev_id,
struct pt_regs *regs) {
/*
* Прерывание может оказаться прерыванием таймера, прерыванием
* завершения обновления или периодическим прерыванием.
* Состояние (причина) прерывания хранится в самом
* младшем байте, а общее количество прерывание — в оставшейся
* части переменной rtc_irq_data
*/
spin_lock(&rtc_lock);
rtc_irq_data += 0x100;
rtc_irq_data &= ~0xff;
rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
if (rtc_status & RTC_TIMER_ON)
mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
spin_unlock(&rtc_lock);
/*
* Теперь выполним остальные действия
*/
spin_lock(&rtc_task_lock);
if (rtc_callback)
rtc_callback->func(rtc_callback->private_data);
spin_unlock(&rtc_task_lock);
wake_up_interruptible(&rtc_wait);
kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
return IRQ_HANDLED;
}
Эта функция вызывается всякий раз, когда система получает прерывание от устройства RTC. Прежде всего, следует обратить внимание на вызовы функций работы со спин-блокировками: первая группа вызовов гарантирует, что к переменной rtc_irq_data
не будет конкурентных обращений другими процессами на SMP-машине, а вторая — защищает в аналогичной ситуации параметры структуры rtc_callback
. Блокировки обсуждаются в главе 9, "Средства синхронизации в ядре".
Переменная rtc_irq_data
содержит информацию об устройстве RTC и обновляется с помощью функции mod_timer()
. О таймерах рассказывается в главе 10, "Таймеры и управление временем".
Последняя часть кода, окруженная спин-блокировками, выполняет функцию обратного вызова (callback), которая может быть установлена извне. Драйвер RTC позволяет устанавливать функцию обратного вызова, которая может быть зарегистрирована пользователем и будет исполняться при каждом прерывании, приходящем от устройства RTC.
В конце функция обработки прерывания возвращает значение IRQ_HANDLED
, чтобы указать, что прерывание от данного устройства обработано правильно. Так как этот обработчик прерывания не поддерживает совместное использование линий прерывания и не существует механизма, посредством которого обработчик прерываний RTC может обнаружить вложенные запросы на прерывание, то этот обработчик всегда возвращает значение IRQ_HANDLED
.
Контекст прерывания
При выполнении обработчика прерывания или обработчика нижней половины, ядро находится в current
возвращает указатель на соответствующее задание. Более того, поскольку в контексте процесса процесс связан с ядром, то контекст процесса может переходить в состояние ожидания или использовать функции планировщика каким- либо другим способом..