2016-08-08 15 views
1

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

Я подозреваю, что это связано с защитой памяти и, возможно, с синхронизацией с кешем, поэтому я попытался использовать smp_wmb() после записи, но, похоже, это не помогает. И насколько я знаю, я не могу явно контролировать синхронизацию кеша. Поэтому я немного застрял.

Любые идеи?

EDIT: уточнить, что описание является упрощенной версией.

+0

Может быть много чего. Поскольку модуль ядра заставляет меня предполагать C, вы объявили переменную volatile? –

+0

@GabeSechan Да, я пробовал это. – TFC

+0

Следуйте шаблонам, которые использует другой код ядра. Кроме того, если вы не делаете что-то невероятно необычное, барьер записи должен быть до записи. Какое значение передает это значение? –

ответ

-1

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

Вы пытались использовать volatile? Думаю, volatile будет работать в вашем случае.

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

+0

Неустойчивый классификатор обычно не влияет на значение переменной в кеше или в памяти. Обычно это влияет только на то, что значение переменной временно удерживается в регистре. –

0

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

Чтобы ответить на ваш вопрос более непосредственно - есть, по крайней мере, две проблемы, вы можете столкнуться здесь: 1. Инструкция перезаказа компилятором, который, как правило, заботятся компилятором барьеров (т.е. barrier()). 2. Выполнение нестандартного исполнения по когерентности ЦП и кэш-памяти, которые обычно заботятся о барьерах памяти.

Информация о архитектуре и специфике использования, но вы не указали какие-либо детали кода или архитектуры, которые мы могли бы проанализировать. Поэтому вам может потребоваться использовать по крайней мере любые и все barrier(), smp_wmb(), smp_rmb() и smp_read_barrier_depends().