Почему "барьер ()" достаточно для отключения или включения вытеснения?

Из кода ядра 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 был запланирован в середине области кода, защищенной от вытеснения (или защищенной от блокировки), мы, очевидно, проиграем.

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

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

Другие вопросы по тегам