Требуется ли спин-блокировка для каждого обработчика прерываний?
В главе 5 ULK автор утверждает следующее:
"... каждый обработчик прерываний сериализуется по отношению к самому себе, то есть он не может выполнять более одного одновременно. Таким образом, доступ к структуре данных не требует примитивов синхронизации"
Я не совсем понимаю, почему обработчики прерываний "сериализуются" на современных процессорах с несколькими ядрами. Я думаю, что возможно, что один и тот же ISR может работать одновременно на разных ядрах, верно? Если это произойдет, если вы не используете спин-блокировку для защиты своих данных, она может прийти в состояние гонки.
Итак, мой вопрос в современной системе с несколькими процессорами для каждого обработчика прерываний, который вы собираетесь писать, который будет читать и записывать некоторые данные, всегда нужен спин-блоки?
Ответы
Ответ 1
При выполнении обработчиков прерываний ядро явно отключает эту конкретную строку прерывания на контроллере прерываний, поэтому один обработчик прерываний не может выполняться несколько раз одновременно. (Однако обработчики других прерываний могут работать одновременно.)
Ответ 2
Уточнение: согласно CL. примечание ниже - ядро не запустит обработчик прерываний для одного и того же прерывания, но если у вас есть несколько регистраций одного и того же обработчика прерываний для нескольких прерываний, чем, как я считаю, правильный ответ.
Вы правы, что один и тот же обработчик прерываний может работать одновременно на нескольких ядрах и что общие данные должны быть защищены. Однако спин-блокировка не является единственным и, конечно, не всегда рекомендуемым способом достижения этого.
Для защиты общих данных может использоваться множество других методов синхронизации, данных из одного процессора, доступа к общим данным только с использованием атомных операций и даже вариантов Read-Copy-Update.
Ответ 3
В обработчике прерываний не всегда нужна спин-блокировка.
Обратите внимание на одно:
Когда прерывание определенного устройства происходит на контроллере прерываний, это прерывание отключается на контроллере прерываний и, следовательно, на всех ядрах для этого конкретного устройства. Таким образом, прерывание одного и того же устройства не может поступать на весь процессор одновременно.
Таким образом, в нормальном случае не будет никакой блокировки спина, поскольку код не будет повторно включен.
Хотя есть два случая ниже, в которых спин-блокировка необходима в обработчике прерываний.
- Обратите внимание, что когда прерывание происходит от устройства и линии IRQ, эти ядра отключают все остальные прерывания на этом ядре, а также для этого прерывания устройства на другом ядре. Прерывание от других устройств может происходить на другом ядре.
Таким образом, может быть случай, когда один и тот же обработчик прерываний зарегистрирован для разных устройств.
например: -
request_irq (А, FUNC,..);
reqest_irq (В, FUNC,..);
для устройства вызывается функция обработчика прерываний.
для устройства B вызывается тот же самый обработчик прерываний.
Таким образом, спин-блокировка должна использоваться в этом случае, чтобы предотвратить условие поднятия.
- Когда тот же ресурс используется в обработчике прерываний, а также какой-то другой код, который выполняется в контексте процесса.
Например: - есть ресурс A
Таким образом, может быть случай, когда один сердечник работает в режиме прерывания, обработчик прерываний и модифицирует ресурс A и другие ядра в контексте процесса и также модифицирует один и тот же ресурс в каком-либо другом месте.
Поэтому, чтобы представить условие повышения для этого ресурса, мы должны использовать блокировку спина.
Ответ 4
раздел 4.6 "Понимание ядра Linux" , 3-е издание Марко Чезати, Дэниел П. Бовет рассказал вам ответ.
Фактический обработчик прерываний - это процесс handle_IRQ_event
. irq_desc[irq].lock
предотвращать одновременный доступ к handle_IRQ_event
любым другим процессором.
Ответ 5
Если критически важные данные распределяются по б/з обработчику прерываний и вашему процессу (может быть потоком ядра), тогда вам необходимо защитить свои данные, и, следовательно, требуется прямая блокировка. Общим ядром для спин-блокировки является: spin_lock().
Существуют также варианты этих api, например. spin_lock_irqsave(), который может помочь избежать проблем с тупиком, с которыми можно столкнуться при приобретении/удержании спиновых блокировок. Пожалуйста, перейдите по ссылке ниже, чтобы найти информацию о предмете:
http://www.linuxjournal.com/article/5833