]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/doc/gcc/extensions-to-the-c-language-family/target-builtins/powerpc-hardware-transactional-memory-built-in-functions.rst
sphinx: add missing trailing newline
[thirdparty/gcc.git] / gcc / doc / gcc / extensions-to-the-c-language-family / target-builtins / powerpc-hardware-transactional-memory-built-in-functions.rst
CommitLineData
c63539ff
ML
1..
2 Copyright 1988-2022 Free Software Foundation, Inc.
3 This is part of the GCC manual.
4 For copying conditions, see the copyright.rst file.
5
6.. _powerpc-hardware-transactional-memory-built-in-functions:
7
8PowerPC Hardware Transactional Memory Built-in Functions
9^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10
11GCC provides two interfaces for accessing the Hardware Transactional
12Memory (HTM) instructions available on some of the PowerPC family
13of processors (eg, POWER8). The two interfaces come in a low level
14interface, consisting of built-in functions specific to PowerPC and a
15higher level interface consisting of inline functions that are common
16between PowerPC and S/390.
17
18PowerPC HTM Low Level Built-in Functions
19~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20
21The following low level built-in functions are available with
22:option:`-mhtm` or :option:`-mcpu=CPU` where CPU is 'power8' or later.
23They all generate the machine instruction that is part of the name.
24
25The HTM builtins (with the exception of ``__builtin_tbegin``) return
26the full 4-bit condition register value set by their associated hardware
27instruction. The header file ``htmintrin.h`` defines some macros that can
28be used to decipher the return value. The ``__builtin_tbegin`` builtin
29returns a simple ``true`` or ``false`` value depending on whether a transaction was
30successfully started or not. The arguments of the builtins match exactly the
31type and order of the associated hardware instruction's operands, except for
32the ``__builtin_tcheck`` builtin, which does not take any input arguments.
33Refer to the ISA manual for a description of each instruction's operands.
34
35.. code-block:: c++
36
37 unsigned int __builtin_tbegin (unsigned int);
38 unsigned int __builtin_tend (unsigned int);
39
40 unsigned int __builtin_tabort (unsigned int);
41 unsigned int __builtin_tabortdc (unsigned int, unsigned int, unsigned int);
42 unsigned int __builtin_tabortdci (unsigned int, unsigned int, int);
43 unsigned int __builtin_tabortwc (unsigned int, unsigned int, unsigned int);
44 unsigned int __builtin_tabortwci (unsigned int, unsigned int, int);
45
46 unsigned int __builtin_tcheck (void);
47 unsigned int __builtin_treclaim (unsigned int);
48 unsigned int __builtin_trechkpt (void);
49 unsigned int __builtin_tsr (unsigned int);
50
51In addition to the above HTM built-ins, we have added built-ins for
52some common extended mnemonics of the HTM instructions:
53
54.. code-block:: c++
55
56 unsigned int __builtin_tendall (void);
57 unsigned int __builtin_tresume (void);
58 unsigned int __builtin_tsuspend (void);
59
60Note that the semantics of the above HTM builtins are required to mimic
61the locking semantics used for critical sections. Builtins that are used
62to create a new transaction or restart a suspended transaction must have
63lock acquisition like semantics while those builtins that end or suspend a
64transaction must have lock release like semantics. Specifically, this must
65mimic lock semantics as specified by C++11, for example: Lock acquisition is
66as-if an execution of __atomic_exchange_n(&globallock,1,__ATOMIC_ACQUIRE)
67that returns 0, and lock release is as-if an execution of
68__atomic_store(&globallock,0,__ATOMIC_RELEASE), with globallock being an
69implicit implementation-defined lock used for all transactions. The HTM
70instructions associated with with the builtins inherently provide the
71correct acquisition and release hardware barriers required. However,
72the compiler must also be prohibited from moving loads and stores across
73the builtins in a way that would violate their semantics. This has been
74accomplished by adding memory barriers to the associated HTM instructions
75(which is a conservative approach to provide acquire and release semantics).
76Earlier versions of the compiler did not treat the HTM instructions as
77memory barriers. A ``__TM_FENCE__`` macro has been added, which can
78be used to determine whether the current compiler treats HTM instructions
79as memory barriers or not. This allows the user to explicitly add memory
80barriers to their code when using an older version of the compiler.
81
82The following set of built-in functions are available to gain access
83to the HTM specific special purpose registers.
84
85.. code-block:: c++
86
87 unsigned long __builtin_get_texasr (void);
88 unsigned long __builtin_get_texasru (void);
89 unsigned long __builtin_get_tfhar (void);
90 unsigned long __builtin_get_tfiar (void);
91
92 void __builtin_set_texasr (unsigned long);
93 void __builtin_set_texasru (unsigned long);
94 void __builtin_set_tfhar (unsigned long);
95 void __builtin_set_tfiar (unsigned long);
96
97Example usage of these low level built-in functions may look like:
98
99.. code-block:: c++
100
101 #include <htmintrin.h>
102
103 int num_retries = 10;
104
105 while (1)
106 {
107 if (__builtin_tbegin (0))
108 {
109 /* Transaction State Initiated. */
110 if (is_locked (lock))
111 __builtin_tabort (0);
112 ... transaction code...
113 __builtin_tend (0);
114 break;
115 }
116 else
117 {
118 /* Transaction State Failed. Use locks if the transaction
119 failure is "persistent" or we've tried too many times. */
120 if (num_retries-- <= 0
121 || _TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ()))
122 {
123 acquire_lock (lock);
124 ... non transactional fallback path...
125 release_lock (lock);
126 break;
127 }
128 }
129 }
130
131One final built-in function has been added that returns the value of
132the 2-bit Transaction State field of the Machine Status Register (MSR)
133as stored in ``CR0``.
134
135.. code-block:: c++
136
137 unsigned long __builtin_ttest (void)
138
139This built-in can be used to determine the current transaction state
140using the following code example:
141
142.. code-block:: c++
143
144 #include <htmintrin.h>
145
146 unsigned char tx_state = _HTM_STATE (__builtin_ttest ());
147
148 if (tx_state == _HTM_TRANSACTIONAL)
149 {
150 /* Code to use in transactional state. */
151 }
152 else if (tx_state == _HTM_NONTRANSACTIONAL)
153 {
154 /* Code to use in non-transactional state. */
155 }
156 else if (tx_state == _HTM_SUSPENDED)
157 {
158 /* Code to use in transaction suspended state. */
159 }
160
161PowerPC HTM High Level Inline Functions
162~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163
164The following high level HTM interface is made available by including
165``<htmxlintrin.h>`` and using :option:`-mhtm` or :option:`-mcpu=CPU`
166where CPU is 'power8' or later. This interface is common between PowerPC
167and S/390, allowing users to write one HTM source implementation that
168can be compiled and executed on either system.
169
170.. code-block:: c++
171
172 long __TM_simple_begin (void);
173 long __TM_begin (void* const TM_buff);
174 long __TM_end (void);
175 void __TM_abort (void);
176 void __TM_named_abort (unsigned char const code);
177 void __TM_resume (void);
178 void __TM_suspend (void);
179
180 long __TM_is_user_abort (void* const TM_buff);
181 long __TM_is_named_user_abort (void* const TM_buff, unsigned char *code);
182 long __TM_is_illegal (void* const TM_buff);
183 long __TM_is_footprint_exceeded (void* const TM_buff);
184 long __TM_nesting_depth (void* const TM_buff);
185 long __TM_is_nested_too_deep(void* const TM_buff);
186 long __TM_is_conflict(void* const TM_buff);
187 long __TM_is_failure_persistent(void* const TM_buff);
188 long __TM_failure_address(void* const TM_buff);
189 long long __TM_failure_code(void* const TM_buff);
190
191Using these common set of HTM inline functions, we can create
192a more portable version of the HTM example in the previous
193section that will work on either PowerPC or S/390:
194
195.. code-block:: c++
196
197 #include <htmxlintrin.h>
198
199 int num_retries = 10;
200 TM_buff_type TM_buff;
201
202 while (1)
203 {
204 if (__TM_begin (TM_buff) == _HTM_TBEGIN_STARTED)
205 {
206 /* Transaction State Initiated. */
207 if (is_locked (lock))
208 __TM_abort ();
209 ... transaction code...
210 __TM_end ();
211 break;
212 }
213 else
214 {
215 /* Transaction State Failed. Use locks if the transaction
216 failure is "persistent" or we've tried too many times. */
217 if (num_retries-- <= 0
218 || __TM_is_failure_persistent (TM_buff))
219 {
220 acquire_lock (lock);
221 ... non transactional fallback path...
222 release_lock (lock);
223 break;
224 }
225 }
3ed1b4ce 226 }