Восстановление потерянного прерывания
Функция do iRQ , несмотря на малый объем и простоту, корректно работает в большинстве случаев. В самом деле, флаги irq pending, irq inprogress и irq disabled гарантируют надлежащую обработку прерываний, даже если имеют место аппаратные неполадки. Тем не менее в многопроцессорной системе иногда не все протекает столь гладко.
Предположим, у некоторого процессора включена IRQ-линия. Аппаратное устройство генерирует прерывание, и многоконтроллерная APIC-система выбирает наш процессор для его обработки. Прежде чем процессор подтвердит прерывание, IRQ-линию маскирует другой процессор. В результате, флаг
irq disabled оказывается установленным. В следующий момент наш процессор начинает обработку "висящего" прерывания. Функция do iRQ подтверждает прерывание и возвращает управление, не выполнив процедуры обработки прерываний, потому что обнаружила установленный флаг irq disabled. Следовательно, хотя прерывание и случилось до отключения линии IRQ, оно теряется.
Чтобы справиться с такой ситуацией, функция enabie irqo, которую ядро вызывает для включения IRQ-линии, вначале проверяет, не потеряно ли прерывание. Если это так, она заставляет аппаратную часть сгенерировать новое появление потерянного прерывания:
spin_lock_irqsave(&(irq_desc[irq].lock), flags); if (—irq_desc[irq].depth == 0) {
irq_desc[irq].status &= ~IRQ_DISABLED;
if (irq_desc[irq].status & (IRQ_PENDING | IRQ_REPLAY))
== IRQ_PENDING) { irq_desc[irq].status |= IRQ_REPLAY; hw_resend_irq(irq_desc[irq].handler,irq);
}
irq_desc[irq].handler->enable(irq);
}
spin_lock_irqrestore(&(irq_desc[irq].lock), flags);
Потерю прерывания функция распознает, проверяя состояние флага irq pending. Он всегда сбрасывается при выходе из обработчика прерываний. Следовательно, если IRQ-линия отключена, а флаг установлен, то прерывание было подтверждено, но не обработано. В таком случае функция hw resend irqo возбуждает новое прерывание. С этой целью она заставляет локальный APIC-контроллер сгенерировать автопрерывание.
Предыдущая страница | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | Следующая страница