Встроенные функции gcc

http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Atomic-Builtins.html

Я считаю, что следующий код увеличивает значение var атомарно.

volatile int var = 0;
__sync_fetch_and_add( &var, 1 )

Я понял приведенные выше коды как следующую логику:

  • Загрузите адрес переменной var
  • напишите номер 1 на переменную var atomically - через регистр/кеш, как-то

Однако, я сомневаюсь, что следующее атомарное тоже

volatile int var = 0;
volatile int num = 1;
__sync_fetch_and_add( &var, num )

Так как это можно интерпретировать как

  • Загрузите адрес переменной var
  • Загрузите значение переменной num в регистр
  • записать значение в переменную var.

После выполнения # 2, но до # 3, CPU/thread прерывается, а другие обновления CPU/потока значение переменной num.

Другими словами, при использовании _sync *() gcc, могу ли я использовать переменную, а не константу, как второй аргумент?

Разве это не разрушает атомарность?

Ответы

Ответ 1

Операция - это действительно две операции.

__sync_fetch_and_add( &var, num )

Загрузка num является атомарной. Добавление его в var является атомарным. Но две атомные операции не выполняют атомную операцию при объединении. Вот почему так сложно изобретать новые блокированные структуры данных. Как правило, две поточно-безопасные операции не обязательно обеспечивают потокобезопасную работу при составлении. Вот почему так сложно делать правильные многопоточные приложения.

Вы видите, что __sync_fetch_and_add действительно атомарно, но ведет себя как обычная функция - поэтому он принимает текущее значение "num" в качестве параметра. Не совсем корректно говорить, что атомарность функции нарушена, потому что на нее отвечает пользователь, загружающий значение из num, и он не является частью функционального интерфейса. Я мог бы также жаловаться на это:

__sync_fetch_and_add(&var, some_really_long_function());

Или хуже,

__sync_fetch_and_add(long_function_1(), long_function_2());

Вы говорите, что это "может быть истолковано как"

  • Загрузите адрес переменной var
  • Загрузите значение переменной num
  • Выполнение добавления атома

Но, согласно спецификации C, это не значит, что это может быть интерпретировано таким образом, но, скорее, это должно интерпретироваться таким образом, иначе компилятор не будет соответствовать (на самом деле он мог бы заменить # 1 и # 2, но что здесь не важно).