Почему Linux отключает вытеснение ядра после того, как код ядра содержит спин-блокировку?

Я новичок в Linux и читаю книгу о драйверах устройств для Linux от Rubini & Corbet. Меня смущает одно утверждение, относящееся к spinlocks; в книге говорится

Если бы непреодолимая однопроцессорная система когда-либо переключилась на блокировку, она бы вращалась вечно; ни один другой поток никогда не сможет получить доступ к ЦП для снятия блокировки. По этой причине операции спин-блокировки в однопроцессорных системах без включенного приоритетного прерывания оптимизированы так, чтобы ничего не делать, за исключением тех, которые изменяют статус маскирования IRQ.

Далее в книге говорится

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

Вопрос: В однопроцессорной системе, если приоритет ядра отключен всякий раз, когда код ядра (выполняющийся от имени пользовательского процесса) удерживает спин-блокировку, то как может другой процесс когда-либо получить шанс запустить и, следовательно, попытаться получить спин-блокировку? Почему ядро ​​Linux отключает вытеснение ядра всякий раз, когда код ядра содержит спин-блокировку?


person Vishal Gandhi    schedule 15.08.2013    source источник


Ответы (4)


Ответ на ваш первый вопрос лежит в основе вашего второго.

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

Нет причин, по которым это должно быть реализовано таким образом; это просто простой способ его реализации, который предотвращает запуск любого процесса на блокировке, удерживаемой ядром. Но этот трюк работает только в том случае, когда ядро ​​установило блокировку: пользовательские процессы не могут отключить приоритетное прерывание, и если ядро ​​вращается (т.е. оно пытается получить спин-блокировку, но другой процесс уже удерживает ее), лучше оставить приоритетное прерывание. на! В противном случае система зависнет, поскольку ядро ​​ожидает блокировки, которая не будет снята, поскольку удерживающий ее процесс не может ее снять.

Ядро, получающее спин-блокировку, представляет собой особый случай. Если программа уровня пользователя получает спин-блокировку, приоритетное прерывание не будет отключено.

person superdesk    schedule 15.08.2013
comment
спасибо superdesk, но я все еще сомневаюсь; если получение спин-блокировки отключает вытеснение ядра, процесс, получивший спин-блокировку, имеет монопольный доступ к критическому разделу и может выполнять его даже без вытеснения (если только процесс, удерживающий спин-блокировку, явно не освобождает процессор). Тогда как другой процесс может запускаться и вращаться на спин-блокировке? Я упускаю здесь что-то базовое? - person Vishal Gandhi; 15.08.2013
comment
Вытеснение отключается только в том случае, если блокировку получает ядро, и ядру доверено снять блокировку после ее завершения. Вы абсолютно правы; в этом случае никакой другой процесс не будет вращаться на замке. Но это частный случай. В большинстве случаев это будут программы пользовательского уровня, которые будут пытаться получить спин-блокировку. Вытеснение НЕ будет отключено, и если два процесса попытаются получить одну и ту же блокировку, один из них закончит работу. - person superdesk; 15.08.2013
comment
К вашему сведению, если вы скомпилируете ядро ​​Linux без CONFIG_SMP, макрос для спин-блокировок отключит только локальную систему прерываний и обновит некоторые переменные для планировщика. не будет занятого ожидания. Я думаю, они разработали это так, потому что вы, вероятно, в любом случае знаете, что делаете, когда пишете для ядра. - person hoholee12; 15.01.2021

И процесс A, и процесс B имеют доступ к одним и тем же данным, поэтому вы определяете SPIN LOCK. если A удерживает блокировку, но сохраняет включенным приоритетное прерывание. тогда A может быть запланировано, и B имеет шанс бежать. если B попытается получить блокировку. B будет вращать и тратить ЦП.

Блокировка спина разработана для эффективности и защиты малых и быстрых критических зон. так что спин-блок отключает вытеснение. если вы хотите заблокировать, но оставьте включенным приоритетное прерывание. вы можете использовать блокировку мьютекса.

когда процесс A снимает блокировку, приоритетное прерывание снова активируется. так что у другого процесса есть шанс запустить. до этого могут работать только аппаратные прерывания и программные IRQ.

person yuanjianpeng    schedule 24.10.2019

Спин-блокировки отключают приоритетное прерывание только на однопроцессорных системах. Итак, в случае с одним процессором: допустим, у планировщика есть следующие процессы в очереди: P1, P2, P3, P4 - все запрашивают спин-блокировку L. Все они получат блокировку, когда они поставлены в очередь (т.е. P1, за которым следует P2 и т. Д.)

Причина, по которой приоритетное отключение отключено в однопроцессорной системе: Если нет: P1 удерживает блокировку и по истечении определенного времени запланировано отключение. Теперь P2 начинает выполнение и, скажем, запрашивает ту же спин-блокировку. Поскольку P1 не освободил спин-блокировку, P2 должен вращаться и ничего не делать. Таким образом, время выполнения P2 тратится. Более разумно позволить P1 снять блокировку, а затем позволить ей быть вытесненной. Кроме того, поскольку нет другого процессора, просто запрещая приоритетное прерывание, мы знаем, что никогда не будет другого процесса, который будет работать параллельно на другом процессоре и обращается к той же критической секции.

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

person Surbhi    schedule 22.10.2019

Каждый раз, когда код ядра удерживает спин-блокировку, приоритетное отключение отключается только на соответствующем процессоре. Это означает, что если это система SMP, приоритетное прерывание отключено только на текущем процессоре, другие процессоры, работающие одновременно, по-прежнему свободны для получения этой блокировки и ожидания. Таким образом, сон после удержания спин-блокировки может вызвать тупик.

В то время как в случае однопроцессорной системы приоритетное прерывание должно быть отключено, потому что, если другой процесс удерживает блокировку, он будет продолжать ждать и не позволит первому процессу снять блокировку.

person Saurabh Sengar    schedule 24.12.2020