Spec-Zone.ru › GCC 6

6.52 Встроенные функции для атомарных операций с учётом модели памяти

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

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

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

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

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

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

Атомарная операция может как ограничивать перемещение кода, так и отображаться на аппаратные инструкции для синхронизации между потоками (например, барьер). В какой степени это происходит, контролируется порядками памяти, которые перечислены здесь приблизительно в порядке возрастания силы. Описание каждого порядка памяти предназначено только для приблизительного иллюстрации эффектов и не является спецификацией; см. модель памяти 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; }

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

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

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

{ tmp = *ptr; *ptr op= val; return tmp; }

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

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

Эта встроенная функция выполняет атомную операцию test-and-set над байтом по адресу *ptr. Байт устанавливается в некоторое определенное реализацией ненулевое значение «set», а возвращаемое значение равно true тогда и только тогда, когда предыдущее содержимое было «set». Она должна использоваться только для операндов типа 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-6.5.0/gcc/_005f_005fatomic-Builtins.html

Spec-Zone.ru

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