Использование spinlock и cli вместе - PullRequest
2 голосов
/ 15 июля 2010

Я недавно скачал источник linux с http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.34.1.tar.bz2.Я наткнулся на следующий абзац в файле с именем spinlocks.txt в папке linux-2.6.34.1 \ Documentation.

"это означает означает, что если у вас есть код, который выполняет

cli();
.. critical section ..
sti();

и другая последовательность, которая выполняет

spin_lock_irqsave(flags);
.. critical section ..
spin_unlock_irqrestore(flags);

, тогда они НЕ являются взаимоисключающими, и критические области могут возникать одновременно на двух разных ЦП. Это хорошо само по себе, но критическоерегионы лучше критиковать для разных вещей (то есть они не могут топтать друг друга). "

Как они могут повлиять, если какой-то код использует cli () / sti () и другую часть того же кодаиспользует spin_lock_irqsave (флаги) / spin_unlock_irqrestore (флаги)?

1 Ответ

7 голосов
/ 17 июля 2010

Ключевая часть здесь - "на двух разных процессорах ".Немного предыстории:

  • Исторически в однопроцессорных (UP) системах единственным источником параллелизма были аппаратные прерывания.Этого было достаточно cli/sti вокруг критической секции, чтобы не допустить путаницы обработчиком IRQ.
  • Затем была конструкция гигантский замок , в которой ядро ​​эффективно работало на одном ЦП.и только один процесс мог быть в ядре за раз (для этого был гигантский замок).Опять же, отключения прерываний было достаточно, чтобы защитить ядро ​​от самого себя.
  • В системах с полной SMP, когда в ядре могут быть активны несколько потоков одновременно, и прерывания могут доставляться практически на любой процессор, это больше недостаточно отключить прерывания только на одном процессоре или захватить только одну блокировку.Требуется и то и другое: отключение прерываний защищает обработчик IRQ на том же процессоре , удержание блокировки защищает от других потоков, входящих в те же критические секции на разных процессорах .Именно поэтому были изобретены spin_lock_irqsave() и spin_unlock_irqrestore().
...