LINUX.ORG.RU

atomic builtins - для чего они применяются?

 


0

2

Наткнулся на http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gcc/Atomic-Builtins.html :

> The definition given in the Intel documentation allows only for
> the use of the types int, long, long long as well as their
> unsigned counterparts. GCC will allow any integral scalar or
> pointer type that is 1, 2, 4 or 8 bytes in length.

> Not all operations are supported by all target processors. If a
> particular operation cannot be implemented on the target
> processor, a warning will be generated and a call an external
> function will be generated ...

Правильно ли я понял, что защита переменных этими функциями нужна
только для процессоров, у которых чтение/запись в 1-,2-,4-,8-байтовые
целочисленные переменные (integer) - реализована как не атомарная?

★★★★★

не... ты список операций посмотри, там сложение/умножение/etc. Штука в том, что эти операции гарантированно атомарны, а значит не убьют тебе многопоточную софтину. И, да, это всё есть в C11, так что гнутые расширения не нужны.

anonymous
()

Даже если на определенной архитектуре load/store атомарны, есть еще такие вещи как оптимизации компилятора и memory barriers.
И если первое решается использованием volatile, то второе только ассемблерными инструкциями либо atomic builtin'ами - так что проще всего не изобретать велосипед, а использовать либо atomic builtins, либо библиотеки типа libatomic_ops.

rand
()

там же не одна операция

namezys ★★★★
()
Ответ на: комментарий от pacify

Дело в том, что как компилятор, так и процессор могут переупорядочивать инструкции если смысл кода от этого не меняется. Но если не использовать явных механизмов синхронизации, ни компилятор ни процессор ничего не знают о наличии тредов - и такая перестановка может полностью «испортить» код.
Приведу пример из википедии:

// первый тред
while (f == 0)
  ;
 // Memory fence required here
 print x;
// второй тред
x = 42;
 // Memory fence required here
 f = 1;
Так вот, если не знать, что переменные f и x используются в нескольких тредах - что компилятор, что CPU могут поменять местами store во втором треде. И в результате print в 1 треде может отработать раньше чем «x = 42» во втором.
Компилятор можно успокоить ключевым словом volatile, а для CPU и используются memory barriers.
Тема довольно большая, так что если действительно хочется с этим разобраться, гуглить сабж + «memory model».

rand
()

Для атомарности защита этими (или подобными) ф-циями нужна всегда. Если целевой CPU (который определяется аржитектурой и march=...) не поддерживает - будет одно из двух - или вызов тяжелой ф-ции с блокировкой, или сборка завалится на этапе компиляции или линковки. В твоих доках написано первое, но я встречал с gcc и второе.

Pavval ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.