1 /* Copyright (C) 2008-2017 Free Software Foundation, Inc.
2 Contributed by Richard Henderson <rth@redhat.com>.
4 This file is part of the GNU Transactional Memory Library (libitm).
6 Libitm is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
29 #define CONCAT1(a, b) CONCAT2(a, b)
30 #define CONCAT2(a, b) a ## b
32 #ifdef __USER_LABEL_PREFIX__
33 # define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
39 # define TYPE(x) .type SYM(x), @function
40 # define SIZE(x) .size SYM(x), . - SYM(x)
41 # ifdef HAVE_ATTRIBUTE_VISIBILITY
42 # define HIDDEN(x) .hidden SYM(x)
50 # define HIDDEN(x) .private_extern SYM(x)
56 /* These are duplicates of the canonical definitions in libitm.h. Note that
57 the code relies on pr_uninstrumentedCode == a_runUninstrumentedCode. */
58 #define pr_uninstrumentedCode 0x02
59 #define pr_hasNoAbort 0x08
60 #define pr_HTMRetryableAbort 0x800000
61 #define pr_HTMRetriedAfterAbort 0x1000000
62 #define a_runInstrumentedCode 0x01
63 #define a_runUninstrumentedCode 0x02
64 #define a_tryHTMFastPath 0x20
66 #define _XABORT_EXPLICIT (1 << 0)
67 #define _XABORT_RETRY (1 << 1)
72 .globl SYM(_ITM_beginTransaction)
74 SYM(_ITM_beginTransaction):
78 /* Custom HTM fast path. We start the HW transaction here and let
79 gtm_thread::begin_transaction (aka GTM_begin_transaction) decide
80 how to proceed on aborts: We either retry the fast path, or fall
81 back to another execution method. RTM restores all registers after
82 a HW transaction abort, so we can do the SW setjmp after aborts,
83 and we have to because we might choose a SW fall back. However,
84 we have to explicitly save/restore the first argument (edi).
85 The htm_fastpath field is the second int in gtm_rwlock. */
86 cmpl $0, (SYM(gtm_serial_lock)+4)(%rip)
88 testl $pr_hasNoAbort, %edi
92 /* Monitor the serial lock (specifically, the 32b writer/summary field
93 at its start), and only continue if there is no serial-mode
94 transaction. Note that we might be just a nested transaction and
95 our outermost transaction might be in serial mode; we check for
96 this case in the retry policy implementation. */
97 cmpl $0, SYM(gtm_serial_lock)(%rip)
99 /* Now also check that HW transactions are still allowed to run (see
100 gtm_thread::begin_transaction for why this is necessary). */
101 cmpl $0, (SYM(gtm_serial_lock)+4)(%rip)
103 /* Everything is good. Run the transaction, preferably using the
104 uninstrumented code path. Note that the following works because
105 pr_uninstrumentedCode == a_runUninstrumentedCode. */
106 andl $pr_uninstrumentedCode, %edi
107 mov $a_runInstrumentedCode, %eax
110 /* There is a serial-mode transaction or HW transactions are not
111 allowed anymore, so abort (see htm_abort() regarding the abort
115 /* If it might make sense to retry the HTM fast path, let the C++
117 testl $(_XABORT_RETRY|_XABORT_EXPLICIT), %eax
119 orl $pr_HTMRetryableAbort, %edi
120 /* Let the C++ code handle the retry policy. */
125 cfi_adjust_cfa_offset(72)
126 /* Store edi for future HTM fast path retries. We use a stack slot
127 lower than the jmpbuf so that the jmpbuf's rip field will overlap
128 with the proper return address on the stack. */
130 /* Save the jmpbuf for any non-HTM-fastpath execution method.
131 Because rsp-based addressing is 1 byte larger and we've got rax
141 call SYM(GTM_begin_transaction)
144 cfi_adjust_cfa_offset(-72)
146 /* If a_tryHTMFastPath was returned, then we need to retry the
147 fast path. We also restore edi and set pr_HTMRetriedAfterAbort
148 to state that we have retried the fast path already (it's harmless
149 if this bit is set even if we don't retry the fast path because it
150 is checked iff pr_HTMRetryableAbort is set). We clear
151 pr_HTMRetryableAbort because it applies to a previous HW
152 transaction attempt. */
153 cmpl $a_tryHTMFastPath, %eax
155 andl $(0xffffffff-pr_HTMRetryableAbort), %edi
156 orl $pr_HTMRetriedAfterAbort, %edi
164 cfi_def_cfa_offset(32)
171 #if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__
172 call SYM(GTM_begin_transaction)
173 #elif defined __ELF__
176 addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx
177 call SYM(GTM_begin_transaction)@PLT
180 # error "Unsupported PIC sequence"
183 cfi_def_cfa_offset(4)
188 TYPE(_ITM_beginTransaction)
189 SIZE(_ITM_beginTransaction)
192 .globl SYM(GTM_longjmp)
207 cfi_register(%rsp, %rcx)
218 cfi_register(%esp, %ecx)
229 .section .note.GNU-stack, "", @progbits