Кодовая база имеет COMPILER_BARRIER
макрос определяется как __asm__ volatile("" ::: "memory")
, Цель макроса — не дать компилятору переупорядочить операции чтения и записи через барьер. Обратите внимание, что это явно барьер компилятора, и не барьер памяти на уровне процессора.
Как это, это довольно переносимо, так как в AssemblerTemplate нет реальных инструкций по сборке, только volatile
и memory
тряпки. Поэтому, если компилятор учитывает синтаксис GCC Extended Asm, он должен работать нормально. Тем не менее, мне любопытно, как правильно выразить это в атомарном API C ++ 11, если это возможно.
Казалось, что это может быть правильной идеей: atomic_signal_fence(memory_order_acq_rel);
,
Мои рассуждения таковы:
<atomic>
Только API atomic_signal_fence
а также atomic_thread_fence
не требуется адрес памяти, по которому можно работать.atomic_thread_fence
влияет на порядок памяти, который нам не нужен для барьера компилятора.memory
Clobber в расширенной версии Asm не различает чтение и запись, поэтому кажется, что мы хотим получить и выпустить семантику, поэтому memory_order_acq_rel
кажется, требуется, как минимум.memory_order_seq_cst
кажется ненужным, поскольку нам не требуется общий порядок между потоками — нас интересует только последовательность команд в текущем потоке.Можно ли выразить эквивалент __asm__ volatile("" ::: "memory")
полностью переносимо с помощью атомарного API C ++ 11? Если это так, atomic_signal_fence
правильный API для использования? Если да, то какой аргумент порядка памяти здесь уместен / необходим?
Или я здесь в сорняках, и есть лучший способ приблизиться к этому?
__asm__ volatile("" ::: "memory")
даже не полный барьер компилятора; это только вынуждает упорядочивать загрузки / сохранения к объектам, адреса которых потенциально доступны для блока asm, который не будет включать локальные переменные, для которых компилятор может отследить, что адрес не течет. Например, memset(password, 0, len);
с последующим __asm__ volatile("" ::: "memory");
может быть не в состоянии фактически обнулить память, используемую password[]
,
Это можно исправить, передав адреса таких объектов как входные данные в блок asm, но я не вижу идеального эквивалента с atomic_signal_fence
, Самое близкое, что вы могли бы сделать, это сохранить адрес объекта во внешнем соединении. volatile
объект указателя (будьте осторожны, чтобы сделать указатель, а не указатель на тип, volatile
квалифицированный), а затем atomic_signal_fence
придется предположить, что к нему можно получить доступ из обработчика сигнала.
Других решений пока нет …