Spec-Zone.ru › GCC 11

Далее: Встроенные функции для операций с атомарной памятью, учитывающими модель памяти, Предыдущее: Поддержка offsetof, Наверх: Расширения для семейства языков C [Оглавление][Индекс]

6.54 Встроенные функции __sync для атомарного доступа к памяти ¶

Следующие встроенные функции предназначены для совместимости с функциями, описанными в спецификации Intel Itanium Processor-specific Application Binary Interface, раздел 7.4. Таким образом, они отличаются от обычной практики GCC, не используя префикс «__builtin_», а также перегружены, чтобы работать с несколькими типами.

Определение, данное в документации Intel, допускает использование только типов int, long, long long или их беззнаковых аналогов. GCC допускает любые скалярные типы размером 1, 2, 4 или 8 байт, кроме типа C _Bool или типа C++ bool. Операции с указателями выполняются так, как если бы операнды были типа uintptr_t. То есть, они не масштабируются на размер типа, на который указывает указатель.

Эти функции реализованы через встроенные функции «__atomic» (см. Встроенные функции для операций с атомарной памятью, учитывающими модель памяти). Их не следует использовать в новом коде, который должен использовать встроенные функции «__atomic» вместо них.

Не все операции поддерживаются всеми целевыми процессорами. Если определенная операция не может быть реализована на целевом процессоре, генерируется предупреждение и вызов внешней функции. Внешняя функция имеет то же имя, что и встроенная версия, с дополнительным суффиксом «_n», где n — размер типа данных.

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

Все процедуры описаны в документации Intel как принимающие «необязательный список переменных, защищенных барьером памяти». Непонятно, что это значит; это может означать, что только указанные переменные защищены, или это может означать список дополнительных переменных, которые нужно защитить. Список игнорируется GCC, который обрабатывает его как пустой. GCC интерпретирует пустой список как означающий, что все глобально доступные переменные должны быть защищены.

type __sync_fetch_and_add (type *ptr, type value, ...)
type __sync_fetch_and_sub (type *ptr, type value, ...)
type __sync_fetch_and_or (type *ptr, type value, ...)
type __sync_fetch_and_and (type *ptr, type value, ...)
type __sync_fetch_and_xor (type *ptr, type value, ...)
type __sync_fetch_and_nand (type *ptr, type value, ...)

Эти встроенные функции выполняют операцию, предложенную их именем, и возвращают значение, которое ранее находилось в памяти. То есть, операции с целочисленными операндами имеют следующие семантику. Операции с указателями выполняются так, как если бы операнды были типа uintptr_t. То есть, они не масштабируются на размер типа, на который указывает указатель.

{ tmp = *ptr; *ptr op= value; return tmp; }
{ tmp = *ptr; *ptr = ~(tmp & value); return tmp; }   // nand

Объект, на который указывает первый аргумент, должен быть целочисленного или указательного типа. Он не должен быть типом «bool».

Примечание: GCC 4.4 и более поздние версии реализуют __sync_fetch_and_nand как *ptr = ~(tmp & value) вместо *ptr = ~tmp & value.

type __sync_add_and_fetch (type *ptr, type value, ...)
type __sync_sub_and_fetch (type *ptr, type value, ...)
type __sync_or_and_fetch (type *ptr, type value, ...)
type __sync_and_and_fetch (type *ptr, type value, ...)
type __sync_xor_and_fetch (type *ptr, type value, ...)
type __sync_nand_and_fetch (type *ptr, type value, ...)

Эти встроенные функции выполняют операцию, предложенную их именем, и возвращают новое значение. То есть, операции с целочисленными операндами имеют следующие семантику. Операции с указательными операндами выполняются так, как если бы тип операнда был uintptr_t.

{ *ptr op= value; return *ptr; }
{ *ptr = ~(*ptr & value); return *ptr; }   // nand

Те же ограничения на аргументы, что и для соответствующих встроенных функций __sync_op_and_fetch.

Примечание: GCC 4.4 и более поздние версии реализуют __sync_nand_and_fetch как *ptr = ~(*ptr & value) вместо *ptr = ~*ptr & value.

bool __sync_bool_compare_and_swap (type *ptr, type oldval, type newval, ...)
type __sync_val_compare_and_swap (type *ptr, type oldval, type newval, ...)

Эти встроенные функции выполняют атомарное сравнение и обмен. То есть, если текущее значение *ptr равно oldval, то запишите newval в *ptr.

Версия «bool» возвращает true если сравнение прошло успешно и newval записано. Версия «val» возвращает содержимое *ptr до операции.

__sync_synchronize (...)

Эта встроенная функция вызывает полный барьер памяти.

type __sync_lock_test_and_set (type *ptr, type value, ...)

Эта встроенная функция, как описано в документации Intel, не является традиционной операцией "тест-и-установить", а скорее атомарной операцией обмена. Она записывает value в *ptr, и возвращает предыдущее содержимое *ptr.

Многие целевые платформы имеют только минимальную поддержку таких блокировок и не поддерживают полную операцию обмена. В этом случае целевая платформа может поддерживать здесь пониженную функциональность, при которой единственное допустимое значение для сохранения — немедленная константа 1. Точное значение, фактически сохранённое в *ptr, определяется реализацией.

Эта встроенная функция не является полным барьером, а скорее барьером приобретения. Это означает, что ссылки после операции не могут перемещаться к (или быть предположительно расположены) до операции, но предыдущие сохранения памяти могут быть ещё не глобально видимы, и предыдущие загрузки памяти могут еще не быть удовлетворены.

void __sync_lock_release (type *ptr, ...)

Эта встроенная функция разблокирует блокировку, приобретённую функцией __sync_lock_test_and_set. Обычно это означает запись константы 0 в *ptr.

Эта встроенная функция не является полным барьером, а скорее барьером освобождения. Это означает, что все предыдущие сохранения памяти глобально видимы, и все предыдущие загрузки памяти выполнены, но последующие чтения памяти не предотвращены от спекулятивного расположения до барьера.

Далее: Встроенные функции для операций с атомарной памятью, учитывающими модель памяти, Предыдущее: Поддержка offsetof, Наверх: Расширения для семейства языков C [Оглавление][Индекс]

© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-11.4.0/gcc/_005f_005fsync-Builtins.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API