2015-01-20 1 views
4

Я пытаюсь изменить код, который приносит вниз центральный процессор, и попал во что-то я не совсем понимаю:Почему возникает вызов mdelay (1) при сбросе аффинности прерывания?

Одна из вещей, которые происходят после того, как ядро ​​удаляются из cpu_online_mask, является переналаживанией прервать сродство. Это делается в функции fixup_irqs(), которая находится в /arch/x86/kernel/irq.c. Функция сбрасывает аффинности прерываний, затем вызывает mdelay (1) (который просто ждет 1 миллисекунду) и, наконец, обращается к возможно «потерянным» прерываниям.

Мой вопрос: почему нужен вызов mdelay (1)? что может произойти без него? Моя догадка заключается в том, что требуется время для перенаправления в APIC, чтобы вступить в силу ... но я уверен, что для этого есть более убедительное объяснение.

Спасибо!

+2

Если вам повезет, это может быть добавлено сообщение 2.6.12, и если вы выполняете «git-вину» и обнаруживаете фиксацию, которая ввела эту задержку, может возникнуть объяснение в сообщении фиксации. – Shahbaz

+2

@Shahbaz, yup, здесь возможно информация: 5231a68614b9. – 0andriy

+0

@ Энди Шевченко, если вы имеете в виду [это] (http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5231a68614b94f60e8f6c56bc6e3d75955b9e75e), то я не думаю, что это дает объяснение. Этот фиксатор просто удаляет прерывание/запрет, окружающий mdelay (1). А именно, mdelay был там до ... – Noamiko

ответ

1

В оболочке ореха есть условие гонки в fixup_irq() - функция начинается с перебора всех IRQ, направляемых на CPU, который отключается, и сообщает HW, чтобы перенаправить их в другое место.

Дело в том, что процесс изменения этой маршрутизации прерываний не является атомарным или мгновенным. Сделка, которая изменяет маршрутизацию на чипе ПОС может мчаться с транзакцией, которая посылает прерывание - и это может занять несколько циклов, чтобы прибыть, так что вы могли бы в конечном итоге с:

  1. Поведать APIC послать прерывания на некоторые другой процессор, а не я.
  2. Прерывание!

Так что код делает в основном:

  1. Поведать APIC послать прерывания в какой-то другой процессор не меня.
  2. Подождите немного. Прежде всего, чтобы обеспечить повторный маршрут прерывания, он будет завершен. (Как узнать, сколько времени достаточно, чтобы ждать? Возможно, его документировано в спецификации APIC, возможно, его внутренние знания, которые некоторые инженеры Intel VLSI показали своим пользователям Linux - я не знаю :-)
  3. Проверьте, произошло ли прерывание путем чтения регистра на APIC, который защелкивается, когда было отправлено прерывание, и если вы найдете его, отправьте его на нужную цель в качестве IPI.
  4. Теперь мы знаем, что никакое прерывание не подойдет к нам.
+0

Действительно - звучит разумно. Но если это так - как отправка ложных прерываний является альтернативой этому подходу? Как комментарий в коде говорит: 'Мы можем удалить mdelay(), а затем отправить прерывистые прерывания в новые цели cpu для всех irq, которые были обработаны ранее этим процессором.' Но - что гарантирует, что отправка ложных прерываний занимает больше времени, чем требуется для повторной маршрутизации APIC? Почему мы не можем отправлять ложные прерывания, APIC не завершит перенаправление, а другое прерывание будет отправлено на исходный процессор, поэтому остается необработанным ... – Noamiko

+0

@NoamShalev Я не знаю. Либо есть какая-то глубокая внутренняя причина, почему это безопасно из-за того, как создается APIC или, и это было бы моим догадком, это просто неправильно, но человек, который написал код, не думал об этом, и окно состояния гонки так маленький он не видел этого в тестах, и так как код вверх делает mdelay(), он так и не узнал ... :-) – gby

Смежные вопросы