Почему "барьер ()" достаточно для отключения или включения вытеснения?
Из кода ядра Linux , я вижу preempt_enable()
а также preempt_disable()
ничего кроме barrier()
:
#define preempt_disable() barrier()
#define preempt_enable() barrier()
Я не могу этого понять. Почему просто barrier()
достаточно для отключения или включения выгрузки?
2 ответа
Потому что вы не используете выгружаемое ядро. Процесс пользовательского пространства, однако, является преимущественным.
Проверьте, установлен ли CONFIG_PREEMPT_VOLUNTARY в конфигурации вашего ядра.
Смотрите Что такое preemption / Что такое preemtible ядро? Для чего это?
Барьер был добавлен начиная с https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable/+/386afc91144b36b42117b0092893f15bc8798a80%5E!/
В Kernel v4.3 правильное определение для preempt_enable
здесь:
#define preempt_enable() \
do { \
barrier(); \
if (unlikely(preempt_count_dec_and_test())) \
__preempt_schedule(); \
} while (0)
и аналогично для preempt_disable
здесь:
#define preempt_disable() \
do { \
preempt_count_inc(); \
barrier(); \
} while (0)
preempt_enable
вставляет барьер оптимизации до того, как выгрузка включена preempt_disable
вставляет барьер после увеличения счетчика вытеснения. Тем не менее, согласно комментарию, когда нет вытеснения, а только барьеры для защиты вытесненного региона.
РЕДАКТИРОВАТЬ: В UP и non-preemp соответственно точки отключения / включения спин-блокировки и вытеснения полностью заглушаются, потому что нет обычного кода, который когда-либо попадал бы в тот тип параллелизма, от которого они должны защищать.
Однако, хотя нет обычного кода, который может вызвать планирование, у насдействительно есть некоторый исключительный (буквально!) Код, который может это сделать, и что нам нужно убедиться, что компилятор никогда не попадет в критическую область.
В частности, get_user() и put_user() обычно реализуются как встроенные операторы asm (даже если встроенный asm может затем сделать инструкцию вызова для вызова вне строки) и, очевидно, может вызвать ошибку страницы и IO в результате, Если этот встроенный asm был запланирован в середине области кода, защищенной от вытеснения (или защищенной от блокировки), мы, очевидно, проиграем.
Теперь, по общему признанию, это очень вряд ли когда-либо случится, и мы не видели примеров реальных ошибок, связанных с этим. Но отчасти именно потому, что его так сложно вызвать, а получающаяся ошибка настолько тонкая, мы должны быть очень осторожны, чтобы сделать это правильно.
Поэтому убедитесь, что даже когда приоритетное прерывание отключено, и нам не нужно генерировать какой-либо фактический код, чтобы явно сказать системе, что мы находимся в области с отключенным вытеснением, нам нужно, по крайней мере, сказать компилятору не перемещать объекты вокруг критическая область. Источник