Spec-Zone.ru › GCC 11

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

6.55 Встроенные функции для операций с атомной памятью с учётом модели памяти ¶

Следующие встроенные функции примерно соответствуют требованиям модели памяти C++11. Все они идентифицируются префиксом «__atomic», и большинство из них перегружены для работы с несколькими типами данных.

Эти функции предназначены для замены устаревших встроенных функций «__sync». Основное различие заключается в том, что порядок памяти является параметром этих функций. Новый код всегда должен использовать встроенные функции «__atomic» вместо функций «__sync».

Обратите внимание, что встроенные функции «__atomic» предполагают, что программы будут соответствовать модели памяти C++11. В частности, они предполагают, что программы не содержат гонок данных. Подробные требования см. в стандарте C++11.

Встроенные функции «__atomic» можно использовать с любым целочисленным скалярным типом или указателем, длина которого составляет 1, 2, 4 или 8 байт. Целочисленные типы длиной 16 байт также разрешены, если архитектура поддерживает тип «__int128» (см. 128-битные целые числа).

Четыре функции, не связанные с арифметическими операциями (load, store, exchange и compare_exchange), также имеют общую версию. Эта общая версия работает с любым типом данных. Она использует встроенную функцию без блокировки, если размер конкретного типа данных позволяет это; в противном случае выполняется внешний вызов, который разрешается во время выполнения. Этот внешний вызов имеет тот же формат, с добавлением параметра «size_t», помещенного в качестве первого параметра, указывающего размер объекта, на который указывает указатель. Все объекты должны иметь одинаковый размер.

Существует 6 различных порядков памяти, которые могут быть заданы. Они соответствуют порядкам памяти C++11 с теми же названиями, см. стандарт C++11 или страницу GCC wiki по атомной синхронизации для подробных определений. Отдельные целевые платформы могут также поддерживать дополнительные порядки памяти для использования на определённых архитектурах. Подробности см. в документации целевой платформы.

Атомная операция может как ограничивать перемещение кода, так и быть отображена в машинные инструкции для синхронизации между потоками (например, барьер). Степень этого определяется порядками памяти, которые перечислены здесь приблизительно по возрастанию силы. Описание каждого порядка памяти предназначено лишь для иллюстрации эффектов и не является спецификацией; см. модель памяти C++11 для точного определения семантики.

__ATOMIC_RELAXED

Не подразумевает никаких ограничений на порядок взаимодействия между потоками.

__ATOMIC_CONSUME

В настоящее время эта реализация использует более сильный порядок памяти __ATOMIC_ACQUIRE, из-за недостатка в семантике C++11 для memory_order_consume.

__ATOMIC_ACQUIRE

Создаёт ограничение «происходит до» для взаимодействия между потоками от операции записи (или более сильной) до этой операции чтения. Может предотвратить подъём кода до операции.

__ATOMIC_RELEASE

Создаёт ограничение «происходит до» для взаимодействия между потоками для операций чтения (или более сильной) считывания из операции записи с семантикой «сброс». Может предотвратить опускание кода после операции.

__ATOMIC_ACQ_REL

Объединяет эффекты __ATOMIC_ACQUIRE и __ATOMIC_RELEASE.

__ATOMIC_SEQ_CST

Навязывает общий порядок со всеми другими __ATOMIC_SEQ_CST операциями.

Обратите внимание, что в модели памяти C++11, барьеры (например, «__atomic_thread_fence») вступают в силу в сочетании с другими атомными операциями на определённых участках памяти (например, атомными чтениями); операции на определённых участках памяти не обязательно влияют на другие операции таким же образом.

Архитектуры целевых платформ рекомендуются для предоставления собственных шаблонов для каждой атомной встроенной функции. При отсутствии целевой платформы используются исходные встроенные атомные функции «__sync», а также любые необходимые барьеры синхронизации, окружающие их, для достижения правильного поведения. Выполнение в этом случае подчиняется тем же ограничениям, что и эти встроенные функции.

Если нет шаблона или механизма для предоставления последовательности инструкций без блокировок, вызов передаётся внешней процедуре с теми же параметрами для разрешения во время выполнения.

При реализации шаблонов для этих встроенных функций параметр порядка памяти может быть проигнорирован, если шаблон реализует наименее строгий __ATOMIC_SEQ_CST порядок памяти. Любые другие порядки памяти будут выполняться корректно с этим порядком памяти, но, возможно, не будут выполняться так эффективно, как с более соответствующей реализацией ослабленных требований.

Обратите внимание, что стандарт C++11 допускает определение параметра порядка памяти во время выполнения, а не во время компиляции. Эти встроенные функции отображают любое значение времени выполнения на __ATOMIC_SEQ_CST , а не вызывают вызов библиотеки во время выполнения или встраивают оператор switch. Это соответствует стандарту, безопасно и является самым простым подходом на данный момент.

Параметр порядка памяти — целое число со знаком, но только 16 младших битов зарезервированы для порядка памяти. Остаток целого числа со знаком зарезервирован для использования целевой платформой и должен быть равен 0. Использование предопределённых атомных значений гарантирует правильное использование.

Встроенная функция: type __atomic_load_n (type *ptr, int memorder) ¶

Эта встроенная функция реализует атомную операцию чтения. Она возвращает содержимое *ptr.

Допустимые варианты порядка памяти — __ATOMIC_RELAXED, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE, и __ATOMIC_CONSUME.

Встроенная функция: void __atomic_load (type *ptr, type *ret, int memorder) ¶

Это общая версия атомного чтения. Она возвращает содержимое *ptr в *ret.

Встроенная функция: void __atomic_store_n (type *ptr, type val, int memorder) ¶

Эта встроенная функция реализует атомную операцию записи. Она записывает val в *ptr.

Допустимые варианты порядка памяти — __ATOMIC_RELAXED, __ATOMIC_SEQ_CST, и __ATOMIC_RELEASE.

Встроенная функция: void __atomic_store (type *ptr, type *val, int memorder) ¶

Это общая версия атомной записи. Она записывает значение *val в *ptr.

Встроенная функция: type __atomic_exchange_n (type *ptr, type val, int memorder) ¶

Эта встроенная функция реализует атомную операцию обмена. Она записывает val в *ptr, и возвращает предыдущее содержимое *ptr.

Допустимые варианты порядка памяти — __ATOMIC_RELAXED, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE, __ATOMIC_RELEASE, и __ATOMIC_ACQ_REL.

Встроенная функция: void __atomic_exchange (type *ptr, type *val, type *ret, int memorder) ¶

Это общая версия атомного обмена. Она записывает содержимое *val в *ptr. Исходное значение *ptr копируется в *ret.

Встроенная функция: bool __atomic_compare_exchange_n (type *ptr, type *expected, type desired, bool weak, int success_memorder, int failure_memorder) ¶

Эта встроенная функция реализует атомную операцию сравнения и обмена. Она сравнивает содержимое *ptr с содержимым *expected. Если они равны, операция является операцией чтение-модификация-запись, которая записывает desired в *ptr. Если они не равны, операция является чтением, и текущее содержимое *ptr записывается в *expected. weak — true для слабого сравнения и обмена, которое может случайным образом завершиться неудачей, и false для сильной версии, которая никогда не завершается неудачей случайным образом. Многие целевые платформы предлагают только сильную версию и игнорируют параметр. В случае сомнения используйте сильную версию.

Если desired записано в *ptr, то true возвращается, и память изменяется в соответствии с порядком памяти, заданным success_memorder. Здесь нет ограничений на порядок памяти, который можно использовать.

В противном случае, false возвращается, и память изменяется в соответствии с failure_memorder. Этот порядок памяти не может быть __ATOMIC_RELEASE ни __ATOMIC_ACQ_REL. Он также не может быть сильнее, чем порядок, заданный success_memorder.

Встроенная функция: bool __atomic_compare_exchange (type *ptr, type *expected, type *desired, bool weak, int success_memorder, int failure_memorder) ¶

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

Встроенная функция: type __atomic_add_fetch (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_sub_fetch (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_and_fetch (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_xor_fetch (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_or_fetch (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_nand_fetch (type *ptr, type val, int memorder) ¶

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

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

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

Встроенная функция: type __atomic_fetch_add (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_fetch_sub (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_fetch_and (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_fetch_xor (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_fetch_or (type *ptr, type val, int memorder) ¶
Встроенная функция: type __atomic_fetch_nand (type *ptr, type val, int memorder) ¶

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

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

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

Встроенная функция: bool __atomic_test_and_set (void *ptr, int memorder) ¶

Эта встроенная функция выполняет атомную операцию «проверка и установка» для байта по адресу *ptr. Байт устанавливается в некоторое реализационно-заданное ненулевое значение «установки», а возвращаемое значение равно true, только если предыдущее содержимое было «установлено». Она должна использоваться только для операндов типа bool или char. Для других типов может быть установлена только часть значения.

Все порядки памяти допустимы.

Встроенная функция: void __atomic_clear (bool *ptr, int memorder) ¶

Эта встроенная функция выполняет атомную операцию очистки для *ptr. После операции *ptr содержит 0. Она должна использоваться только для операндов типа bool или char, и в сочетании с __atomic_test_and_set. Для других типов она может очистить только частично. Если тип не bool, предпочтительнее использовать __atomic_store.

Допустимые варианты порядков памяти — __ATOMIC_RELAXED, __ATOMIC_SEQ_CST, и __ATOMIC_RELEASE.

Встроенная функция: void __atomic_thread_fence (int memorder) ¶

Эта встроенная функция действует как барьер синхронизации между потоками на основе заданного порядка памяти.

Все порядки памяти допустимы.

Встроенная функция: void __atomic_signal_fence (int memorder) ¶

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

Все порядки памяти допустимы.

Встроенная функция: bool __atomic_always_lock_free (size_t size, void *ptr) ¶

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

ptr — необязательный указатель на объект, который может использоваться для определения выравнивания. Значение 0 указывает на то, что следует использовать типовое выравнивание. Компилятор может также проигнорировать этот параметр.

if (__atomic_always_lock_free (sizeof (long long), 0))
Встроенная функция: bool __atomic_is_lock_free (size_t size, void *ptr) ¶

Эта встроенная функция возвращает true, если объекты размером size байт всегда генерируют инструкции атомарного доступа без блокировок для целевой архитектуры. Если встроенная функция не известна как безблокировочная, вызывается рутинная программа времени выполнения с именем __atomic_is_lock_free.

ptr — необязательный указатель на объект, который может использоваться для определения выравнивания. Значение 0 указывает на то, что следует использовать типовое выравнивание. Компилятор может также проигнорировать этот параметр.

Далее: Встроенные функции для проверки переполнения при арифметических операциях, Предыдущий: Устаревшие __sync встроенные функции для атомарного доступа к памяти, Наверх: Расширения языка семейства 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_005fatomic-Builtins.html

Spec-Zone.ru

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