Spec-Zone.ru › GCC 14

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

Следующие встроенные функции предназначены для совместимости с функциями, описанными в разделе 7.4 спецификации Intel Itanium Processor-specific Application Binary Interface. В связи с этим они отличаются от обычной практики 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

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

Примечание: 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 перед операцией.

Встроенная функция: void __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.

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

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

Spec-Zone.ru

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