Spec-Zone.ru › GCC 4

6.52 Встроенные функции для операций с атомными данными, учитывающие модель памяти

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

GCC допускает любые целочисленные скалярные типы или указатели длиной 1, 2, 4 или 8 байт. Целочисленные типы длиной 16 байт также допускаются, если ‘__int128’ (см. __int128) поддерживается архитектурой.

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

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

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

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

__ATOMIC_RELAXED
Нет барьеров и синхронизации.
__ATOMIC_CONSUME
Только зависимость данных для барьера и синхронизации с другим потоком.
__ATOMIC_ACQUIRE
Барьер для подъёма кода и синхронизация с операциями хранения (или более сильными) с семантикой выпуска из другого потока.
__ATOMIC_RELEASE
Барьер для опускания кода и синхронизация с операциями загрузки (или более сильными) с семантикой приобретения из другого потока.
__ATOMIC_ACQ_REL
Полный барьер в обоих направлениях и синхронизация с загрузкой приобретения и операциями хранения выпуска в другом потоке.
__ATOMIC_SEQ_CST
Полный барьер в обоих направлениях и синхронизация с загрузкой приобретения и операциями хранения выпуска во всех потоках.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Эта встроенная функция реализует операцию атомарного обмена. Она записывает 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 memmodel)

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

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

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

Возвращает true, если desired записано в *ptr, и выполнение считается соответствующим модели памяти, указанной success_memmodel. Нет ограничений на модель памяти, которую можно использовать здесь.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

— Встроенная функция: 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 указывает, что следует использовать типичное выравнивание. Компилятор также может игнорировать этот параметр.

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

Spec-Zone.ru

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