7.13.26 Встроенные функции аппаратной транзакционной памяти PowerPC
GCC предоставляет два интерфейса для доступа к инструкциям аппаратной транзакционной памяти (HTM), доступным на некоторых процессорах семейства PowerPC (например, POWER8). Один интерфейс низкого уровня состоит из встроенных функций, специфичных для PowerPC, а интерфейс более высокого уровня — из встроенных функций, общих для PowerPC и S/390.
- Встроенные функции HTM низкого уровня для PowerPC
- Встроенные функции HTM высокого уровня для PowerPC
7.13.26.1 Встроенные функции HTM низкого уровня для PowerPC
Следующие встроенные функции низкого уровня доступны при использовании -mhtm или -mcpu=CPU, где CPU — ‘power8’ или более поздняя версия. Каждая из них генерирует машинную инструкцию, указанную в её имени.
Встроенные функции HTM (за исключением __builtin_tbegin) возвращают полное 4-битное значение регистра условий, устанавливаемое соответствующей аппаратной инструкцией. Заголовочный файл htmintrin.h определяет несколько макросов, которые можно использовать для интерпретации возвращаемого значения. Встроенная функция __builtin_tbegin возвращает простое значение true или false в зависимости от того, была ли успешно начата транзакция. Аргументы встроенных функций в точности соответствуют типу и порядку операндов соответствующей аппаратной инструкции, за исключением встроенной функции __builtin_tcheck, которая не принимает входных аргументов. Описание операндов каждой инструкции см. в руководстве по ISA.
unsigned int __builtin_tbegin (unsigned int); unsigned int __builtin_tend (unsigned int); unsigned int __builtin_tabort (unsigned int); unsigned int __builtin_tabortdc (unsigned int, unsigned int, unsigned int); unsigned int __builtin_tabortdci (unsigned int, unsigned int, int); unsigned int __builtin_tabortwc (unsigned int, unsigned int, unsigned int); unsigned int __builtin_tabortwci (unsigned int, unsigned int, int); unsigned int __builtin_tcheck (void); unsigned int __builtin_treclaim (unsigned int); unsigned int __builtin_trechkpt (void); unsigned int __builtin_tsr (unsigned int);
Помимо перечисленных выше встроенных функций HTM добавлены встроенные функции для некоторых распространённых расширенных мнемоник инструкций HTM:
unsigned int __builtin_tendall (void); unsigned int __builtin_tresume (void); unsigned int __builtin_tsuspend (void);
Обратите внимание, что семантика приведённых выше встроенных функций HTM должна имитировать семантику блокировок, используемую в критических секциях. Встроенные функции, используемые для создания новой транзакции или возобновления приостановленной транзакции, должны иметь семантику получения блокировки, а функции, завершающие или приостанавливающие транзакцию, — семантику освобождения блокировки. В частности, эта семантика должна соответствовать семантике блокировок, заданной в C++11. Например, получение блокировки эквивалентно выполнению __atomic_exchange_n(&globallock,1,__ATOMIC_ACQUIRE), возвращающему 0, а освобождение блокировки эквивалентно выполнению __atomic_store(&globallock,0,__ATOMIC_RELEASE), где globallock — это неявная блокировка, определяемая реализацией и используемая для всех транзакций. Инструкции HTM, связанные со встроенными функциями, сами обеспечивают необходимые аппаратные барьеры получения и освобождения блокировки. Однако компилятор также должен быть лишён возможности перемещать загрузки и сохранения через встроенные функции так, чтобы это нарушало их семантику. Для этого к соответствующим инструкциям HTM были добавлены барьеры памяти (это консервативный способ обеспечить семантику получения и освобождения блокировки). В более ранних версиях компилятора инструкции HTM не считались барьерами памяти. Добавлен макрос __TM_FENCE__, позволяющий определить, считает ли текущий компилятор инструкции HTM барьерами памяти. Это позволяет пользователю явно добавлять барьеры памяти в свой код при использовании более ранней версии компилятора.
Для доступа к специальным регистрам специального назначения HTM доступны следующие встроенные функции.
unsigned long __builtin_get_texasr (void); unsigned long __builtin_get_texasru (void); unsigned long __builtin_get_tfhar (void); unsigned long __builtin_get_tfiar (void); void __builtin_set_texasr (unsigned long); void __builtin_set_texasru (unsigned long); void __builtin_set_tfhar (unsigned long); void __builtin_set_tfiar (unsigned long);
Пример использования этих встроенных функций низкого уровня:
#include <htmintrin.h>
int num_retries = 10;
while (1)
{
if (__builtin_tbegin (0))
{
/* Transaction State Initiated. */
if (is_locked (lock))
__builtin_tabort (0);
... transaction code...
__builtin_tend (0);
break;
}
else
{
/* Transaction State Failed. Use locks if the transaction
failure is "persistent" or we've tried too many times. */
if (num_retries-- <= 0
|| _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
{
acquire_lock (lock);
... non transactional fallback path...
release_lock (lock);
break;
}
}
}
Добавлена ещё одна встроенная функция, возвращающая значение 2-битового поля состояния транзакции регистра состояния машины (MSR), сохранённое в CR0.
unsigned long __builtin_ttest (void)
Эту встроенную функцию можно использовать для определения текущего состояния транзакции, как показано в следующем примере кода:
#include <htmintrin.h>
unsigned char tx_state = _HTM_STATE (__builtin_ttest ());
if (tx_state == _HTM_TRANSACTIONAL)
{
/* Code to use in transactional state. */
}
else if (tx_state == _HTM_NONTRANSACTIONAL)
{
/* Code to use in non-transactional state. */
}
else if (tx_state == _HTM_SUSPENDED)
{
/* Code to use in transaction suspended state. */
}
7.13.26.2 Встроенные функции HTM высокого уровня для PowerPC
Следующий высокоуровневый интерфейс HTM становится доступен при подключении <htmxlintrin.h> и использовании -mhtm или -mcpu=CPU, где CPU — ‘power8’ или более поздняя версия. Этот интерфейс общий для PowerPC и S/390, что позволяет пользователям писать одну реализацию HTM, которую можно скомпилировать и выполнить в любой из этих систем.
long __TM_simple_begin (void); long __TM_begin (void* const TM_buff); long __TM_end (void); void __TM_abort (void); void __TM_named_abort (unsigned char const code); void __TM_resume (void); void __TM_suspend (void); long __TM_is_user_abort (void* const TM_buff); long __TM_is_named_user_abort (void* const TM_buff, unsigned char *code); long __TM_is_illegal (void* const TM_buff); long __TM_is_footprint_exceeded (void* const TM_buff); long __TM_nesting_depth (void* const TM_buff); long __TM_is_nested_too_deep(void* const TM_buff); long __TM_is_conflict(void* const TM_buff); long __TM_is_failure_persistent(void* const TM_buff); long __TM_failure_address(void* const TM_buff); long long __TM_failure_code(void* const TM_buff);
Используя этот общий набор встроенных функций HTM, можно создать более переносимую версию примера HTM из предыдущего раздела, которая будет работать как на PowerPC, так и на S/390:
#include <htmxlintrin.h>
int num_retries = 10;
TM_buff_type TM_buff;
while (1)
{
if (__TM_begin (TM_buff) == _HTM_TBEGIN_STARTED)
{
/* Transaction State Initiated. */
if (is_locked (lock))
__TM_abort ();
... transaction code...
__TM_end ();
break;
}
else
{
/* Transaction State Failed. Use locks if the transaction
failure is "persistent" or we've tried too many times. */
if (num_retries-- <= 0
|| __TM_is_failure_persistent (TM_buff))
{
acquire_lock (lock);
... non transactional fallback path...
release_lock (lock);
break;
}
}
}
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/PowerPC-Hardware-Transactional-Memory-Built_002din-Functions.html