Могу ли я не использовать освобождение и приобретать барьеры в этом случае? - PullRequest
0 голосов
/ 22 мая 2018

Этот учебник говорит следующее:

каждые загрузка в x86 / 64 уже подразумевает семантику получения, а каждое хранилище подразумеваетсемантика релиза.

Теперь скажите, что у меня есть следующий код (я написал свои вопросы в комментариях):

/* Global Variables */

int flag = 0;
int number1;
int number2;

//------------------------------------

/* Thread A */

number1 = 12345;
number2 = 678910;
flag = 1; /* This is a "store", so can I not use a release barrier here? */

//------------------------------------

/* Thread B */

while (flag == 0) {} /* This is a "load", so can I not use an acquire barrier here? */
printf("%d", number1);
printf("%d", number2);

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Предположим, что код написан на C99, а целевая архитектура - x86.Модель сильной памяти x86 действует только на уровне машинного кода.С99 не имеет модели памяти.Я объясню, что может пойти не так, и расскажу, существует ли C99-совместимый способ решения проблем.

Во-первых, мы должны убедиться, что ни одна из переменных не оптимизирована, и что все обращаются к flag, number1 и number2 происходят из памяти, а не кэшируются в регистрах ЦП 1 .Это может быть достигнуто в C99, квалифицируя все три переменные с volatile.

Во-вторых, мы должны убедиться, что хранилище к flag в первом потоке имеет семантику выпуска.Эта семантика включает две гарантии: сохранение в flag не переупорядочивается при предыдущих обращениях к памяти и делает хранилище видимым для второго потока.Ключевое слово volatile сообщает компилятору, что доступ к переменной может иметь видимые побочные эффекты.Это предотвращает изменение порядка доступа компилятором к изменчивым переменным по отношению к другим операциям, которые компилятор также имеет наблюдаемые побочные эффекты.То есть, создав все три переменные volatile, компилятор будет поддерживать порядок всех трех хранилищ в первом потоке.Тем не менее, если есть другие доступы к энергонезависимой памяти, которые находятся выше или ниже хранилища до flag, то такие доступы все еще могут быть переупорядочены.Таким образом, стандарт volatile обеспечивает только семантику частичного выпуска.

В-третьих ... фактически для вашего конкретного фрагмента кода атомарность не требуется.Это связано с тем, что в хранилище flag изменяется только один бит, который по своей природе является атомарным.Так что для этого конкретного кода вам не нужно беспокоиться об атомарности.Но в целом, если хранилище на flag может измениться более чем на один бит, и если условие, проверенное во втором потоке, может вести себя по-разному в зависимости от того, видит ли он все или некоторые изменения в битах, то вам, безусловно, нужно убедиться, чточто доступ к 'flag` является атомарным.К сожалению, в C99 нет понятия атомарности.

Чтобы получить полную семантику и атомарность релиза, вы можете использовать атомарность C11 (как обсуждалось в статье, которую вы цитировали), или вы можете прибегнуть к методам, специфичным для компилятора (также обсуждаемымв статье, которую вы цитировали).Конечно, вы все равно можете просто посмотреть на сгенерированный машинный код и посмотреть, предлагает ли сама модель памяти x86 необходимые требования для корректности.Это невозможно на больших базах кода.Кроме того, при следующей компиляции кода сгенерированный машинный код может измениться.Наконец, поскольку вы всего лишь человек, вы можете ошибиться.


(1) В цитируемой статье переменная A объявлена ​​как общая глобальная переменная.Теперь, скорее всего, компилятор выделит его из памяти.Но соответствует ли это строгому стандарту?Что мешает компилятору размещать его в регистре на протяжении всего времени жизни программы?Не уверен насчет этого.

0 голосов
/ 23 мая 2018

В учебнике речь идет о нагрузках и хранилищах на уровне сборки / машины, где вы можете положиться на семантику x86 ISA, которая включает в себя сборку при загрузке и выпуск при включении-store.

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

...