annotate libitm/method-serial.cc @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1 /* Copyright (C) 2008-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
2 Contributed by Richard Henderson <rth@redhat.com>.
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of the GNU Transactional Memory Library (libitm).
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 Libitm is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
7 under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
8 the Free Software Foundation; either version 3 of the License, or
kono
parents:
diff changeset
9 (at your option) any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
kono
parents:
diff changeset
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
kono
parents:
diff changeset
14 more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
17 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
18 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
21 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
23 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 #include "libitm_i.h"
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 // Avoid a dependency on libstdc++ for the pure virtuals in abi_dispatch.
kono
parents:
diff changeset
28 extern "C" void HIDDEN
kono
parents:
diff changeset
29 __cxa_pure_virtual ()
kono
parents:
diff changeset
30 {
kono
parents:
diff changeset
31 abort ();
kono
parents:
diff changeset
32 }
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 using namespace GTM;
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 namespace {
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 // This group consists of the serial, serialirr, and serialirr_onwrite
kono
parents:
diff changeset
39 // methods, which all need no global state (except what is already provided
kono
parents:
diff changeset
40 // by the serial mode implementation).
kono
parents:
diff changeset
41 struct serial_mg : public method_group
kono
parents:
diff changeset
42 {
kono
parents:
diff changeset
43 virtual void init() { }
kono
parents:
diff changeset
44 virtual void fini() { }
kono
parents:
diff changeset
45 };
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 static serial_mg o_serial_mg;
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 class serialirr_dispatch : public abi_dispatch
kono
parents:
diff changeset
51 {
kono
parents:
diff changeset
52 public:
kono
parents:
diff changeset
53 serialirr_dispatch() : abi_dispatch(false, true, true, false,
kono
parents:
diff changeset
54 gtm_thread::STATE_SERIAL | gtm_thread::STATE_IRREVOCABLE, &o_serial_mg)
kono
parents:
diff changeset
55 { }
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 protected:
kono
parents:
diff changeset
58 serialirr_dispatch(bool ro, bool wt, bool uninstrumented,
kono
parents:
diff changeset
59 bool closed_nesting, uint32_t requires_serial, method_group* mg) :
kono
parents:
diff changeset
60 abi_dispatch(ro, wt, uninstrumented, closed_nesting, requires_serial, mg)
kono
parents:
diff changeset
61 { }
kono
parents:
diff changeset
62
kono
parents:
diff changeset
63 // Transactional loads and stores simply access memory directly.
kono
parents:
diff changeset
64 // These methods are static to avoid indirect calls, and will be used by the
kono
parents:
diff changeset
65 // virtual ABI dispatch methods or by static direct-access methods created
kono
parents:
diff changeset
66 // below.
kono
parents:
diff changeset
67 template <typename V> static V load(const V* addr, ls_modifier mod)
kono
parents:
diff changeset
68 {
kono
parents:
diff changeset
69 return *addr;
kono
parents:
diff changeset
70 }
kono
parents:
diff changeset
71 template <typename V> static void store(V* addr, const V value,
kono
parents:
diff changeset
72 ls_modifier mod)
kono
parents:
diff changeset
73 {
kono
parents:
diff changeset
74 *addr = value;
kono
parents:
diff changeset
75 }
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 public:
kono
parents:
diff changeset
78 static void memtransfer_static(void *dst, const void* src, size_t size,
kono
parents:
diff changeset
79 bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
kono
parents:
diff changeset
80 {
kono
parents:
diff changeset
81 if (!may_overlap)
kono
parents:
diff changeset
82 ::memcpy(dst, src, size);
kono
parents:
diff changeset
83 else
kono
parents:
diff changeset
84 ::memmove(dst, src, size);
kono
parents:
diff changeset
85 }
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
kono
parents:
diff changeset
88 {
kono
parents:
diff changeset
89 ::memset(dst, c, size);
kono
parents:
diff changeset
90 }
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 CREATE_DISPATCH_METHODS(virtual, )
kono
parents:
diff changeset
93 CREATE_DISPATCH_METHODS_MEM()
kono
parents:
diff changeset
94
kono
parents:
diff changeset
95 virtual gtm_restart_reason begin_or_restart() { return NO_RESTART; }
kono
parents:
diff changeset
96 virtual bool trycommit(gtm_word& priv_time) { return true; }
kono
parents:
diff changeset
97 virtual void rollback(gtm_transaction_cp *cp) { abort(); }
kono
parents:
diff changeset
98 virtual bool snapshot_most_recent() { return true; }
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 virtual abi_dispatch* closed_nesting_alternative()
kono
parents:
diff changeset
101 {
kono
parents:
diff changeset
102 // For nested transactions with an instrumented code path, we can do
kono
parents:
diff changeset
103 // undo logging.
kono
parents:
diff changeset
104 return GTM::dispatch_serial();
kono
parents:
diff changeset
105 }
kono
parents:
diff changeset
106 };
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 class serial_dispatch : public abi_dispatch
kono
parents:
diff changeset
109 {
kono
parents:
diff changeset
110 protected:
kono
parents:
diff changeset
111 static void log(const void *addr, size_t len)
kono
parents:
diff changeset
112 {
kono
parents:
diff changeset
113 gtm_thread *tx = gtm_thr();
kono
parents:
diff changeset
114 tx->undolog.log(addr, len);
kono
parents:
diff changeset
115 }
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 template <typename V> static V load(const V* addr, ls_modifier mod)
kono
parents:
diff changeset
118 {
kono
parents:
diff changeset
119 return *addr;
kono
parents:
diff changeset
120 }
kono
parents:
diff changeset
121 template <typename V> static void store(V* addr, const V value,
kono
parents:
diff changeset
122 ls_modifier mod)
kono
parents:
diff changeset
123 {
kono
parents:
diff changeset
124 if (mod != WaW)
kono
parents:
diff changeset
125 log(addr, sizeof(V));
kono
parents:
diff changeset
126 *addr = value;
kono
parents:
diff changeset
127 }
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 public:
kono
parents:
diff changeset
130 static void memtransfer_static(void *dst, const void* src, size_t size,
kono
parents:
diff changeset
131 bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
kono
parents:
diff changeset
132 {
kono
parents:
diff changeset
133 if (dst_mod != WaW && dst_mod != NONTXNAL)
kono
parents:
diff changeset
134 log(dst, size);
kono
parents:
diff changeset
135 if (!may_overlap)
kono
parents:
diff changeset
136 ::memcpy(dst, src, size);
kono
parents:
diff changeset
137 else
kono
parents:
diff changeset
138 ::memmove(dst, src, size);
kono
parents:
diff changeset
139 }
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
kono
parents:
diff changeset
142 {
kono
parents:
diff changeset
143 if (mod != WaW)
kono
parents:
diff changeset
144 log(dst, size);
kono
parents:
diff changeset
145 ::memset(dst, c, size);
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147
kono
parents:
diff changeset
148 virtual gtm_restart_reason begin_or_restart() { return NO_RESTART; }
kono
parents:
diff changeset
149 virtual bool trycommit(gtm_word& priv_time) { return true; }
kono
parents:
diff changeset
150 // Local undo will handle this.
kono
parents:
diff changeset
151 // trydropreference() need not be changed either.
kono
parents:
diff changeset
152 virtual void rollback(gtm_transaction_cp *cp) { }
kono
parents:
diff changeset
153 virtual bool snapshot_most_recent() { return true; }
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 CREATE_DISPATCH_METHODS(virtual, )
kono
parents:
diff changeset
156 CREATE_DISPATCH_METHODS_MEM()
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 serial_dispatch() : abi_dispatch(false, true, false, true,
kono
parents:
diff changeset
159 gtm_thread::STATE_SERIAL, &o_serial_mg)
kono
parents:
diff changeset
160 { }
kono
parents:
diff changeset
161 };
kono
parents:
diff changeset
162
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 // Like serialirr_dispatch but does not requests serial-irrevocable mode until
kono
parents:
diff changeset
165 // the first write in the transaction. Can be useful for read-mostly workloads
kono
parents:
diff changeset
166 // and testing, but is likely too simple to be of general purpose.
kono
parents:
diff changeset
167 class serialirr_onwrite_dispatch : public serialirr_dispatch
kono
parents:
diff changeset
168 {
kono
parents:
diff changeset
169 public:
kono
parents:
diff changeset
170 serialirr_onwrite_dispatch() :
kono
parents:
diff changeset
171 serialirr_dispatch(false, true, false, false, 0, &o_serial_mg) { }
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 protected:
kono
parents:
diff changeset
174 static void pre_write()
kono
parents:
diff changeset
175 {
kono
parents:
diff changeset
176 gtm_thread *tx = gtm_thr();
kono
parents:
diff changeset
177 if (!(tx->state & (gtm_thread::STATE_SERIAL
kono
parents:
diff changeset
178 | gtm_thread::STATE_IRREVOCABLE)))
kono
parents:
diff changeset
179 tx->serialirr_mode();
kono
parents:
diff changeset
180 }
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 // Transactional loads access memory directly.
kono
parents:
diff changeset
183 // Transactional stores switch to serial mode first.
kono
parents:
diff changeset
184 template <typename V> static void store(V* addr, const V value,
kono
parents:
diff changeset
185 ls_modifier mod)
kono
parents:
diff changeset
186 {
kono
parents:
diff changeset
187 pre_write();
kono
parents:
diff changeset
188 serialirr_dispatch::store(addr, value, mod);
kono
parents:
diff changeset
189 }
kono
parents:
diff changeset
190
kono
parents:
diff changeset
191 public:
kono
parents:
diff changeset
192 static void memtransfer_static(void *dst, const void* src, size_t size,
kono
parents:
diff changeset
193 bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
kono
parents:
diff changeset
194 {
kono
parents:
diff changeset
195 pre_write();
kono
parents:
diff changeset
196 serialirr_dispatch::memtransfer_static(dst, src, size, may_overlap,
kono
parents:
diff changeset
197 dst_mod, src_mod);
kono
parents:
diff changeset
198 }
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
kono
parents:
diff changeset
201 {
kono
parents:
diff changeset
202 pre_write();
kono
parents:
diff changeset
203 serialirr_dispatch::memset_static(dst, c, size, mod);
kono
parents:
diff changeset
204 }
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 CREATE_DISPATCH_METHODS(virtual, )
kono
parents:
diff changeset
207 CREATE_DISPATCH_METHODS_MEM()
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 virtual void rollback(gtm_transaction_cp *cp)
kono
parents:
diff changeset
210 {
kono
parents:
diff changeset
211 gtm_thread *tx = gtm_thr();
kono
parents:
diff changeset
212 if (tx->state & gtm_thread::STATE_IRREVOCABLE)
kono
parents:
diff changeset
213 abort();
kono
parents:
diff changeset
214 }
kono
parents:
diff changeset
215
kono
parents:
diff changeset
216 virtual bool snapshot_most_recent() { return true; }
kono
parents:
diff changeset
217 };
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 // This group is pure HTM with serial mode as a fallback. There is no
kono
parents:
diff changeset
220 // difference to serial_mg except that we need to enable or disable the HTM
kono
parents:
diff changeset
221 // fastpath. See gtm_thread::begin_transaction.
kono
parents:
diff changeset
222 struct htm_mg : public method_group
kono
parents:
diff changeset
223 {
kono
parents:
diff changeset
224 virtual void init()
kono
parents:
diff changeset
225 {
kono
parents:
diff changeset
226 // Enable the HTM fastpath if the HW is available. The fastpath is
kono
parents:
diff changeset
227 // initially disabled.
kono
parents:
diff changeset
228 #ifdef USE_HTM_FASTPATH
kono
parents:
diff changeset
229 gtm_thread::serial_lock.set_htm_fastpath(htm_init());
kono
parents:
diff changeset
230 #endif
kono
parents:
diff changeset
231 }
kono
parents:
diff changeset
232 virtual void fini()
kono
parents:
diff changeset
233 {
kono
parents:
diff changeset
234 // Disable the HTM fastpath.
kono
parents:
diff changeset
235 gtm_thread::serial_lock.set_htm_fastpath(0);
kono
parents:
diff changeset
236 }
kono
parents:
diff changeset
237 };
kono
parents:
diff changeset
238
kono
parents:
diff changeset
239 static htm_mg o_htm_mg;
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 // We just need the subclass to associate it with the HTM method group that
kono
parents:
diff changeset
242 // sets up the HTM fast path. This will use serial_dispatch as fallback for
kono
parents:
diff changeset
243 // transactions that might get canceled; it has a different method group, but
kono
parents:
diff changeset
244 // this is harmless for serial dispatchs because they never abort.
kono
parents:
diff changeset
245 class htm_dispatch : public serialirr_dispatch
kono
parents:
diff changeset
246 {
kono
parents:
diff changeset
247 public:
kono
parents:
diff changeset
248 htm_dispatch() : serialirr_dispatch(false, true, false, false,
kono
parents:
diff changeset
249 gtm_thread::STATE_SERIAL | gtm_thread::STATE_IRREVOCABLE, &o_htm_mg)
kono
parents:
diff changeset
250 { }
kono
parents:
diff changeset
251 };
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 } // anon namespace
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 static const serialirr_dispatch o_serialirr_dispatch;
kono
parents:
diff changeset
256 static const serial_dispatch o_serial_dispatch;
kono
parents:
diff changeset
257 static const serialirr_onwrite_dispatch o_serialirr_onwrite_dispatch;
kono
parents:
diff changeset
258 static const htm_dispatch o_htm_dispatch;
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 abi_dispatch *
kono
parents:
diff changeset
261 GTM::dispatch_serialirr ()
kono
parents:
diff changeset
262 {
kono
parents:
diff changeset
263 return const_cast<serialirr_dispatch *>(&o_serialirr_dispatch);
kono
parents:
diff changeset
264 }
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 abi_dispatch *
kono
parents:
diff changeset
267 GTM::dispatch_serial ()
kono
parents:
diff changeset
268 {
kono
parents:
diff changeset
269 return const_cast<serial_dispatch *>(&o_serial_dispatch);
kono
parents:
diff changeset
270 }
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 abi_dispatch *
kono
parents:
diff changeset
273 GTM::dispatch_serialirr_onwrite ()
kono
parents:
diff changeset
274 {
kono
parents:
diff changeset
275 return
kono
parents:
diff changeset
276 const_cast<serialirr_onwrite_dispatch *>(&o_serialirr_onwrite_dispatch);
kono
parents:
diff changeset
277 }
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 abi_dispatch *
kono
parents:
diff changeset
280 GTM::dispatch_htm ()
kono
parents:
diff changeset
281 {
kono
parents:
diff changeset
282 return const_cast<htm_dispatch *>(&o_htm_dispatch);
kono
parents:
diff changeset
283 }
kono
parents:
diff changeset
284
kono
parents:
diff changeset
285 // Put the transaction into serial-irrevocable mode.
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 void
kono
parents:
diff changeset
288 GTM::gtm_thread::serialirr_mode ()
kono
parents:
diff changeset
289 {
kono
parents:
diff changeset
290 struct abi_dispatch *disp = abi_disp ();
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 #if defined(USE_HTM_FASTPATH)
kono
parents:
diff changeset
293 // HTM fastpath. If we are executing a HW transaction, don't go serial but
kono
parents:
diff changeset
294 // continue. See gtm_thread::begin_transaction.
kono
parents:
diff changeset
295 if (likely(!gtm_thread::serial_lock.htm_fastpath_disabled()))
kono
parents:
diff changeset
296 return;
kono
parents:
diff changeset
297 #endif
kono
parents:
diff changeset
298
kono
parents:
diff changeset
299 if (this->state & STATE_SERIAL)
kono
parents:
diff changeset
300 {
kono
parents:
diff changeset
301 if (this->state & STATE_IRREVOCABLE)
kono
parents:
diff changeset
302 return;
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 // Try to commit the dispatch-specific part of the transaction, as we
kono
parents:
diff changeset
305 // would do for an outermost commit.
kono
parents:
diff changeset
306 // We're already serial, so we don't need to ensure privatization safety
kono
parents:
diff changeset
307 // for other transactions here.
kono
parents:
diff changeset
308 gtm_word priv_time = 0;
kono
parents:
diff changeset
309 bool ok = disp->trycommit (priv_time);
kono
parents:
diff changeset
310 // Given that we're already serial, the trycommit better work.
kono
parents:
diff changeset
311 assert (ok);
kono
parents:
diff changeset
312 }
kono
parents:
diff changeset
313 else if (serial_lock.write_upgrade (this))
kono
parents:
diff changeset
314 {
kono
parents:
diff changeset
315 this->state |= STATE_SERIAL;
kono
parents:
diff changeset
316 // Try to commit the dispatch-specific part of the transaction, as we
kono
parents:
diff changeset
317 // would do for an outermost commit.
kono
parents:
diff changeset
318 // We have successfully upgraded to serial mode, so we don't need to
kono
parents:
diff changeset
319 // ensure privatization safety for other transactions here.
kono
parents:
diff changeset
320 // However, we are still a reader (wrt. privatization safety) until we
kono
parents:
diff changeset
321 // have either committed or restarted, so finish the upgrade after that.
kono
parents:
diff changeset
322 gtm_word priv_time = 0;
kono
parents:
diff changeset
323 if (!disp->trycommit (priv_time))
kono
parents:
diff changeset
324 restart (RESTART_SERIAL_IRR, true);
kono
parents:
diff changeset
325 gtm_thread::serial_lock.write_upgrade_finish(this);
kono
parents:
diff changeset
326 }
kono
parents:
diff changeset
327 else
kono
parents:
diff changeset
328 restart (RESTART_SERIAL_IRR, false);
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330 this->state |= (STATE_SERIAL | STATE_IRREVOCABLE);
kono
parents:
diff changeset
331 set_abi_disp (dispatch_serialirr ());
kono
parents:
diff changeset
332 }
kono
parents:
diff changeset
333
kono
parents:
diff changeset
334 void ITM_REGPARM
kono
parents:
diff changeset
335 _ITM_changeTransactionMode (_ITM_transactionState state)
kono
parents:
diff changeset
336 {
kono
parents:
diff changeset
337 assert (state == modeSerialIrrevocable);
kono
parents:
diff changeset
338 gtm_thr()->serialirr_mode ();
kono
parents:
diff changeset
339 }