spin_lock в ядрах Linux с недопустимым приоритетом - PullRequest
4 голосов
/ 30 июля 2010

Я читал, что в системе с 1 ЦП и не имеющим преимеятельного ядра Linux (2.6.x) вызов spin_lock эквивалентен пустому вызову и, таким образом, реализован таким образом.: разве это не должно быть равносильно сну на мьютексе?Например, даже в ядрах без вытеснения обработчики прерываний могут выполняться, или я мог бы вызвать функцию, которая переводит исходный поток в спящий режим.Так что это неправда, что пустой вызов spin_lock является «безопасным», как если бы он был реализован как мьютекс.

Есть что-то, чего я не получаю?

Ответы [ 4 ]

6 голосов
/ 30 июля 2010

Если бы вы использовали spin_lock() в неперегрузочном ядре для защиты данных от обработчика прерываний, вы бы зашли в тупик (на однопроцессорной машине).

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

Спин-блокировки могут использоваться только в том случае, если держатель блокировки всегда может работать до завершения.

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

6 голосов
/ 31 июля 2010

Чтобы ответить на две части вашего вопроса:

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

spin_lock()не должен защищать от обработчиков прерываний - только код ядра пользовательского контекста.spin_lock_irqsave() является версией, отключающей прерывания, и эта не является запретом для неперегрузочного однопроцессора.

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

Нельзя спать, удерживая спин-блокировку.Это ошибка «Планирование пока атомно».Если вы хотите спать, вы должны вместо этого использовать мьютекс (опять же - это не запреты для неперегрузочного однопроцессора).

5 голосов
/ 31 июля 2010

Цитируется из «Драйверы устройств Linux» , Джонатаном Корбетом, Алессандро Рубини и Грегом Кроа-Хартманом:

Если непревзойденная однопроцессорная система когда-либо обернуласьзапереть, он будет крутиться вечно;никакой другой поток никогда не сможет получить процессор, чтобы снять блокировку (потому что он не мог дать).Из-за этого операции спин-блокировки в однопроцессорных системах без включенного вытеснения оптимизированы, чтобы ничего не делать, за исключением тех, которые изменяют статус маскирования IRQ (в Linux это будет spin_lock_irqsave()).Из-за вытеснения, даже если вы никогда не ожидаете, что ваш код будет работать в системе SMP, вам все равно нужно будет реализовать правильную блокировку.

Если вас интересует спин-блокировка, которая может быть взята кодом, работающим в контексте прерываний (аппаратное или программное обеспечение), вы должны использовать форму spin_lock_*, которая отключает прерывания.В противном случае система заблокируется, как только появится прерывание, когда вы вошли в критическую секцию.

1 голос
/ 30 июля 2010

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

...