ротация аппаратных прерываний PCI-шины
Линии прерываний INTA – INTB соединяются с выводами PIRQ0 – PIRQ3 контроллера PCI-шины, а оттуда через роутер (PCI Interrupt Router) попадают в контроллер прерываний, тем или иным образом отображаясь на четыре линии IRQ, не занятые никакими ISA-устройствами. Поскольку, количество установленных PCI-устройств обычно много больше четырех (мы считаем также и внутренние устройства, такие например, как интегрированный контроллер USB, чаще всего повешенный на INTD), несколько устройств вынуждены делить одно прерывание между собой. В отличии от ISA, в PCI-шине совместное использование прерываний является ее нормальным состояниям. Генерация прерываний осуществляется не по переходу, а по состоянию и устройство может удерживать линию прерывания в соответствующем состоянии до тех пор, пока его запрос не будет обработан. Теоретически это легко. Практически же… Даже поверхностное тестирование обнаруживает большое количество устройств и драйверов не вполне соответствующих спецификациям и не желающих делить свое PIRQ с другими (или делающих это настолько неумело, что производительность падает в разы). Следование спецификациям предотвращает конфликты, но оставляет проблему падения производительности в силе. При совместном использовании прерываний, драйвера получают сигналы не только от своих, но и от чужих устройств, заставляя их обращаться к своему устройству за подтверждением, и если выяснится, что прерывание сгенерировало не оно, запрос передается следующему драйверу в цепочке. А теперь представьте, что произойдет, если на одном прерывании висит десяток устройств и драйвер наиболее "беспокойного" из них попадет в самый хвост очереди?
Для достижения наивысшей производительности следует, во-первых, оптимально распределить PCI-карты по слотам (например, если у вас на шесть PCI-слотов приходятся две PCI-карты, то втыкая устройства в первый и пятый слот, вы вешаете их на одно PIRQ), по возможности совмещая на одном PIRQ только наименее темпераментные устройства, т. е. такие, которые генерируют прерывания реже всего. Во-вторых, каждое PIRQ должно отображаться на свое IRQ. Какое – не суть важно (ведь приоритет PCI-прерываний одинаков), но только свое. Совместное использование одного IRQ несколькими PIRQ обычно не приводит к конфликтам, но негативно сказывается на производительности, ведь драйвера работают не с PIRQ, а с IRQ!
ACPI-ядра, работающие с PCI-шиной через ACPI-контроллер, лишены возможности управлять отображением PIRQ на IRQ по своему усмотрению. Не может управлять этим и BIOS (во всяком случае легальными средствами). Сам же ACPI стремится повесить все PIRQ на одно IRQ (обычно IRQ9) и помешать ему очень трудно. Если количество установленных PCI-устройств намного больше четырех, то разница в производительности между ACPI- и не ACPI-ядрами несущественна, поскольку даже отказавшись от ACPI вы все равно будете вынуждены разделять одно PIRQ между несколькими устройствами. Другое дело, если количество PCI-устройств невелико и наиболее темпераментные из них висят на своих прерываниях – тогда при переходе с ACPI на не ACPI-ядро разница в быстродействии системы может оказаться очень значительной (тоже самое относится и к неудачно спроектированным устройствам, не умеющих делить прерывания с другими и не имеющих достойной замены, например, дорогой видео ускоритель, RAID-контроллер и т. д.).
К сожалению, просто взять и отключить ACPI нельзя, поскольку он является не только менеджером питания, распределителем ресурсов, но еще и корневым перечислителем. ACPI- и не ACPI-ядра используют различные деревья устройств и потому взаимно несовместимы. Смена ядра в обязательном порядке требует переустановки системы, в противном случае та отражается загружаться. Это существенно затрудняет сравнение быстродействия ACPI и не ACPI ядер, поскольку переустановка системы радикальным и непредсказуемым образом изменяет ее производительность.