В Kernel v4.3, право определение preempt_enable
here является:
#define preempt_enable() \
do { \
barrier(); \
if (unlikely(preempt_count_dec_and_test())) \
__preempt_schedule(); \
} while (0)
и аналогично для preempt_disable
является here:
#define preempt_disable() \
do { \
preempt_count_inc(); \
barrier(); \
} while (0)
preempt_enable
вставки оптимизации барьер перед тем упреждения включена и preempt_disable
вставки барьер после того, как счетчик превышения увеличивается. Однако в соответствии с comment, когда нет превентивного вмешательства, а просто препятствия для защиты выгруженного региона.
EDIT: В UP и не-PREEMPT соответственно, спин-блокировка и упреждение отключить/включить пункты затушили полностью, потому что нет регулярного кода, который никогда не может попасть в таком параллелизме они предназначены для защищать от.
Однако, в то время как нет регулярного кода, который может вызвать планирование, мы сделать в конечный итоге, некоторый исключительный (буквально!) Код, который может сделать так, и что нам нужно, чтобы убедиться, что не когда-нибудь перемещаемыми в критическую область компилятором.
В частности, get_user() и put_user(), как правило, реализуются в виде заявления инлайн ассемблера (даже если встроенный ASM может затем сделать вызов инструкции для вызова вне линии), и, очевидно, могут вызвать страницу ошибка и IO в результате. Если этот встроенный asm был запланирован на в середине защищенной от вторсырья (или защищенной от спин-блокировки) области кода, мы, очевидно, проиграем .
Теперь, по общему признанию, это очень вряд ли когда-либо произойдет, и мы не видели примеров фактических ошибок, связанных с этим. Но частично именно потому, что его так сложно вызвать, и получившаяся ошибка настолько утончена, что мы должны быть осторожны, чтобы получить это право.
Поэтому убедитесь, что даже когда упреждение отключен, и мы не должны генерировать любые фактические код явно указать системе, что мы находимся в упреждение-инвалидов области, мы должны, по крайней мере сказать компилятор не для перемещения предметов вокруг критической области. Source
[preempt_disable] (http://lxr.free-electrons.com/source/include/linux/preempt.h#L163) 'ы для реализации требуется 'CONFIG_PREEMPT_COUNT', [This] (http://lxr.free-electrons.com/source/include/linux/preempt.h#L236) (' #define preempt_disable() барьер() ') - это когда 'CONFIG_PREEMPT_COUNT' выключен. –
Чтобы добавить к вышеприведенному описанию, ядро может быть скомпилировано двумя способами, а именно с упреждающим режимом и не превентивным режимом. (Я не берусь о приостановке пользовательского пространства, которое всегда существует). Kconfig [источник] (http://lxr.free-electrons.com/source/kernel/Kconfig.preempt), который контролирует включение/выключение preemption. Когда мы включаем CONFIG_PREEMPT, автоматически включается CONFIG_PREEMPT_COUNT (см. Kconfig.preempt). Когда PREEMPT отключен, вызовы заменяются барьером(), который только для сброса записи в DRAM. – Nithin