Как избежать сна, удерживая спинлок - PullRequest
5 голосов
/ 09 сентября 2010

Я недавно прочитал раздел 5.5.2 (спин-блокировки и атомарный контекст) книги LDDv3:

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

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

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

Заранее спасибо!

Ответы [ 2 ]

5 голосов
/ 09 сентября 2010

А как насчет включения "проверки сна-спин-блокировки" для вашего ядра?Обычно он находится в разделе «Отладка ядра» при запуске make config.Вы также можете попытаться повторить его поведение в вашем коде.

0 голосов
/ 15 сентября 2010

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

Спин-блокировка linux существует только в многопроцессорных сборках (в однопроцессных сборках препроцессор блокировок определяется как пустые) спин-блокировки предназначены для краткосрочных блокировок на многопроцессорной платформе.

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

Примитив irqsave spinlock - это аккуратный способ отключения / включения прерываний, чтобы драйвер мог заблокировать обработчик прерываний, но это следует проводить только достаточно долго, чтобы процесс обновлял некоторые переменные, используемые совместно с обработчиком прерываний, если вы отключите перехваты вы не собираетесь планировать.

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

Для общей блокировки ядра вы должны использовать API mutex / семафор, который будет спать в блокировке, если потребуется.

Чтобы заблокировать код, запущенный в других процессах, используйте muxtex / семафор Чтобы заблокировать код, работающий в контексте прерывания, используйте irq save / restore или spinlock_irq save / restore

Чтобы заблокировать код, запущенный на других процессорах, используйте спин-блокировки и избегайте длительного удержания блокировки.

Надеюсь, это поможет

...