]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/doc/gcc/extensions-to-the-c-language-family/target-builtins/powerpc-hardware-transactional-memory-built-in-functions.rst
4b104a242987db498ce1f3f7b2c1ebe9e0323466
[thirdparty/gcc.git] / gcc / doc / gcc / extensions-to-the-c-language-family / target-builtins / powerpc-hardware-transactional-memory-built-in-functions.rst
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
8 PowerPC Hardware Transactional Memory Built-in Functions
9 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10
11 GCC provides two interfaces for accessing the Hardware Transactional
12 Memory (HTM) instructions available on some of the PowerPC family
13 of processors (eg, POWER8). The two interfaces come in a low level
14 interface, consisting of built-in functions specific to PowerPC and a
15 higher level interface consisting of inline functions that are common
16 between PowerPC and S/390.
17
18 PowerPC HTM Low Level Built-in Functions
19 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
20
21 The following low level built-in functions are available with
22 :option:`-mhtm` or :option:`-mcpu=CPU` where CPU is 'power8' or later.
23 They all generate the machine instruction that is part of the name.
24
25 The HTM builtins (with the exception of ``__builtin_tbegin``) return
26 the full 4-bit condition register value set by their associated hardware
27 instruction. The header file ``htmintrin.h`` defines some macros that can
28 be used to decipher the return value. The ``__builtin_tbegin`` builtin
29 returns a simple ``true`` or ``false`` value depending on whether a transaction was
30 successfully started or not. The arguments of the builtins match exactly the
31 type and order of the associated hardware instruction's operands, except for
32 the ``__builtin_tcheck`` builtin, which does not take any input arguments.
33 Refer 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
51 In addition to the above HTM built-ins, we have added built-ins for
52 some 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
60 Note that the semantics of the above HTM builtins are required to mimic
61 the locking semantics used for critical sections. Builtins that are used
62 to create a new transaction or restart a suspended transaction must have
63 lock acquisition like semantics while those builtins that end or suspend a
64 transaction must have lock release like semantics. Specifically, this must
65 mimic lock semantics as specified by C++11, for example: Lock acquisition is
66 as-if an execution of __atomic_exchange_n(&globallock,1,__ATOMIC_ACQUIRE)
67 that returns 0, and lock release is as-if an execution of
68 __atomic_store(&globallock,0,__ATOMIC_RELEASE), with globallock being an
69 implicit implementation-defined lock used for all transactions. The HTM
70 instructions associated with with the builtins inherently provide the
71 correct acquisition and release hardware barriers required. However,
72 the compiler must also be prohibited from moving loads and stores across
73 the builtins in a way that would violate their semantics. This has been
74 accomplished by adding memory barriers to the associated HTM instructions
75 (which is a conservative approach to provide acquire and release semantics).
76 Earlier versions of the compiler did not treat the HTM instructions as
77 memory barriers. A ``__TM_FENCE__`` macro has been added, which can
78 be used to determine whether the current compiler treats HTM instructions
79 as memory barriers or not. This allows the user to explicitly add memory
80 barriers to their code when using an older version of the compiler.
81
82 The following set of built-in functions are available to gain access
83 to 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
97 Example 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
131 One final built-in function has been added that returns the value of
132 the 2-bit Transaction State field of the Machine Status Register (MSR)
133 as stored in ``CR0``.
134
135 .. code-block:: c++
136
137 unsigned long __builtin_ttest (void)
138
139 This built-in can be used to determine the current transaction state
140 using 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
161 PowerPC HTM High Level Inline Functions
162 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163
164 The following high level HTM interface is made available by including
165 ``<htmxlintrin.h>`` and using :option:`-mhtm` or :option:`-mcpu=CPU`
166 where CPU is 'power8' or later. This interface is common between PowerPC
167 and S/390, allowing users to write one HTM source implementation that
168 can 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
191 Using these common set of HTM inline functions, we can create
192 a more portable version of the HTM example in the previous
193 section 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 }
226 }