aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/libitm/config/linux
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.9/libitm/config/linux')
-rw-r--r--gcc-4.9/libitm/config/linux/alpha/futex_bits.h56
-rw-r--r--gcc-4.9/libitm/config/linux/futex.cc83
-rw-r--r--gcc-4.9/libitm/config/linux/futex.h39
-rw-r--r--gcc-4.9/libitm/config/linux/futex_bits.h39
-rw-r--r--gcc-4.9/libitm/config/linux/powerpc/futex_bits.h54
-rw-r--r--gcc-4.9/libitm/config/linux/rwlock.cc282
-rw-r--r--gcc-4.9/libitm/config/linux/rwlock.h81
-rw-r--r--gcc-4.9/libitm/config/linux/sh/futex_bits.h50
-rw-r--r--gcc-4.9/libitm/config/linux/sparc/futex_bits.h62
-rw-r--r--gcc-4.9/libitm/config/linux/x86/futex_bits.h82
-rw-r--r--gcc-4.9/libitm/config/linux/x86/tls.h105
11 files changed, 933 insertions, 0 deletions
diff --git a/gcc-4.9/libitm/config/linux/alpha/futex_bits.h b/gcc-4.9/libitm/config/linux/alpha/futex_bits.h
new file mode 100644
index 000000000..5e234d71a
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/alpha/futex_bits.h
@@ -0,0 +1,56 @@
+/* Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Provide target-specific access to the futex system call. */
+
+#ifndef SYS_futex
+#define SYS_futex 394
+#endif
+
+static inline long
+sys_futex0 (std::atomic<int> *addr, long op, long val)
+{
+ register long sc_0 __asm__("$0");
+ register long sc_16 __asm__("$16");
+ register long sc_17 __asm__("$17");
+ register long sc_18 __asm__("$18");
+ register long sc_19 __asm__("$19");
+ long res;
+
+ sc_0 = SYS_futex;
+ sc_16 = (long) addr;
+ sc_17 = op;
+ sc_18 = val;
+ sc_19 = 0;
+ __asm volatile ("callsys"
+ : "=r" (sc_0), "=r"(sc_19)
+ : "0"(sc_0), "r" (sc_16), "r"(sc_17), "r"(sc_18), "1"(sc_19)
+ : "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",
+ "$22", "$23", "$24", "$25", "$27", "$28", "memory");
+
+ res = sc_0;
+ if (__builtin_expect (sc_19, 0))
+ res = -res;
+ return res;
+}
diff --git a/gcc-4.9/libitm/config/linux/futex.cc b/gcc-4.9/libitm/config/linux/futex.cc
new file mode 100644
index 000000000..7caff88a8
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/futex.cc
@@ -0,0 +1,83 @@
+/* Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Provide access to the futex system call. */
+
+#include "libitm_i.h"
+#include "futex.h"
+#include <futex_bits.h>
+#include <errno.h>
+
+namespace GTM HIDDEN {
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_PRIVATE_FLAG 128L
+
+
+static long int gtm_futex_wait = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;
+static long int gtm_futex_wake = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
+
+
+void
+futex_wait (std::atomic<int> *addr, int val)
+{
+ long res;
+
+ res = sys_futex0 (addr, gtm_futex_wait, val);
+ if (__builtin_expect (res == -ENOSYS, 0))
+ {
+ gtm_futex_wait = FUTEX_WAIT;
+ gtm_futex_wake = FUTEX_WAKE;
+ res = sys_futex0 (addr, FUTEX_WAIT, val);
+ }
+ if (__builtin_expect (res < 0, 0))
+ {
+ if (res == -EWOULDBLOCK || res == -ETIMEDOUT)
+ ;
+ else if (res == -EFAULT)
+ GTM_fatal ("futex failed (EFAULT %p)", addr);
+ else
+ GTM_fatal ("futex failed (%s)", strerror(-res));
+ }
+}
+
+
+long
+futex_wake (std::atomic<int> *addr, int count)
+{
+ long res = sys_futex0 (addr, gtm_futex_wake, count);
+ if (__builtin_expect (res == -ENOSYS, 0))
+ {
+ gtm_futex_wait = FUTEX_WAIT;
+ gtm_futex_wake = FUTEX_WAKE;
+ res = sys_futex0 (addr, FUTEX_WAKE, count);
+ }
+ if (__builtin_expect (res < 0, 0))
+ GTM_fatal ("futex failed (%s)", strerror(-res));
+ else
+ return res;
+}
+
+} // namespace GTM
diff --git a/gcc-4.9/libitm/config/linux/futex.h b/gcc-4.9/libitm/config/linux/futex.h
new file mode 100644
index 000000000..171d97095
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/futex.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Provide access to the futex system call. */
+
+#ifndef GTM_FUTEX_H
+#define GTM_FUTEX_H 1
+
+#include "local_atomic"
+
+namespace GTM HIDDEN {
+
+extern void futex_wait (std::atomic<int> *addr, int val);
+extern long futex_wake (std::atomic<int> *addr, int count);
+
+}
+
+#endif /* GTM_FUTEX_H */
diff --git a/gcc-4.9/libitm/config/linux/futex_bits.h b/gcc-4.9/libitm/config/linux/futex_bits.h
new file mode 100644
index 000000000..62d83d185
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/futex_bits.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Provide target-independant access to the futex system call. */
+
+/* Note for ARM:
+ There are two styles of syscall, and in the eabi style the syscall
+ number goes into the thumb frame pointer. We need to either write
+ this in pure assembler or just defer entirely to libc. */
+
+#include <unistd.h>
+#include <sys/syscall.h>
+
+static inline long
+sys_futex0 (std::atomic<int> *addr, long op, long val)
+{
+ return syscall (SYS_futex, (int*) addr, op, val, 0);
+}
diff --git a/gcc-4.9/libitm/config/linux/powerpc/futex_bits.h b/gcc-4.9/libitm/config/linux/powerpc/futex_bits.h
new file mode 100644
index 000000000..46805667f
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/powerpc/futex_bits.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/syscall.h>
+
+static inline long
+sys_futex0 (std::atomic<int> *addr, int op, int val)
+{
+ register long int r0 __asm__ ("r0");
+ register long int r3 __asm__ ("r3");
+ register long int r4 __asm__ ("r4");
+ register long int r5 __asm__ ("r5");
+ register long int r6 __asm__ ("r6");
+
+ r0 = SYS_futex;
+ r3 = (long) addr;
+ r4 = op;
+ r5 = val;
+ r6 = 0;
+
+ /* ??? The powerpc64 sysdep.h file clobbers ctr; the powerpc32 sysdep.h
+ doesn't. It doesn't much matter for us. In the interest of unity,
+ go ahead and clobber it always. */
+
+ __asm volatile ("sc; mfcr %0"
+ : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6)
+ : "r"(r0), "r"(r3), "r"(r4), "r"(r5), "r"(r6)
+ : "r7", "r8", "r9", "r10", "r11", "r12",
+ "cr0", "ctr", "memory");
+ if (__builtin_expect (r0 & (1 << 28), 0))
+ return r3;
+ return 0;
+}
diff --git a/gcc-4.9/libitm/config/linux/rwlock.cc b/gcc-4.9/libitm/config/linux/rwlock.cc
new file mode 100644
index 000000000..ed6a4b834
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/rwlock.cc
@@ -0,0 +1,282 @@
+/* Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ Contributed by Torvald Riegel <triegel@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include "libitm_i.h"
+#include "futex.h"
+#include <limits.h>
+
+namespace GTM HIDDEN {
+
+// Acquire a RW lock for reading.
+
+void
+gtm_rwlock::read_lock (gtm_thread *tx)
+{
+ for (;;)
+ {
+ // Fast path: first announce our intent to read, then check for
+ // conflicting intents to write. The fence ensures that this happens
+ // in exactly this order.
+ tx->shared_state.store (0, memory_order_relaxed);
+ atomic_thread_fence (memory_order_seq_cst);
+ if (likely (writers.load (memory_order_relaxed) == 0))
+ return;
+
+ // There seems to be an active, waiting, or confirmed writer, so enter
+ // the futex-based slow path.
+
+ // Before waiting, we clear our read intent check whether there are any
+ // writers that might potentially wait for readers. If so, wake them.
+ // We need the barrier here for the same reason that we need it in
+ // read_unlock().
+ // TODO Potentially too many wake-ups. See comments in read_unlock().
+ tx->shared_state.store (-1, memory_order_relaxed);
+ atomic_thread_fence (memory_order_seq_cst);
+ if (writer_readers.load (memory_order_relaxed) > 0)
+ {
+ writer_readers.store (0, memory_order_relaxed);
+ futex_wake(&writer_readers, 1);
+ }
+
+ // Signal that there are waiting readers and wait until there is no
+ // writer anymore.
+ // TODO Spin here on writers for a while. Consider whether we woke
+ // any writers before?
+ while (writers.load (memory_order_relaxed))
+ {
+ // An active writer. Wait until it has finished. To avoid lost
+ // wake-ups, we need to use Dekker-like synchronization.
+ // Note that we cannot reset readers to zero when we see that there
+ // are no writers anymore after the barrier because this pending
+ // store could then lead to lost wake-ups at other readers.
+ readers.store (1, memory_order_relaxed);
+ atomic_thread_fence (memory_order_seq_cst);
+ if (writers.load (memory_order_relaxed))
+ futex_wait(&readers, 1);
+ else
+ {
+ // There is no writer, actually. However, we can have enabled
+ // a futex_wait in other readers by previously setting readers
+ // to 1, so we have to wake them up because there is no writer
+ // that will do that. We don't know whether the wake-up is
+ // really necessary, but we can get lost wake-up situations
+ // otherwise.
+ // No additional barrier nor a nonrelaxed load is required due
+ // to coherency constraints. write_unlock() checks readers to
+ // see if any wake-up is necessary, but it is not possible that
+ // a reader's store prevents a required later writer wake-up;
+ // If the waking reader's store (value 0) is in modification
+ // order after the waiting readers store (value 1), then the
+ // latter will have to read 0 in the futex due to coherency
+ // constraints and the happens-before enforced by the futex
+ // (paragraph 6.10 in the standard, 6.19.4 in the Batty et al
+ // TR); second, the writer will be forced to read in
+ // modification order too due to Dekker-style synchronization
+ // with the waiting reader (see write_unlock()).
+ // ??? Can we avoid the wake-up if readers is zero (like in
+ // write_unlock())? Anyway, this might happen too infrequently
+ // to improve performance significantly.
+ readers.store (0, memory_order_relaxed);
+ futex_wake(&readers, INT_MAX);
+ }
+ }
+
+ // And we try again to acquire a read lock.
+ }
+}
+
+
+// Acquire a RW lock for writing. Generic version that also works for
+// upgrades.
+// Note that an upgrade might fail (and thus waste previous work done during
+// this transaction) if there is another thread that tried to go into serial
+// mode earlier (i.e., upgrades do not have higher priority than pure writers).
+// However, this seems rare enough to not consider it further as we need both
+// a non-upgrade writer and a writer to happen to switch to serial mode
+// concurrently. If we'd want to handle this, a writer waiting for readers
+// would have to coordinate with later arriving upgrades and hand over the
+// lock to them, including the the reader-waiting state. We can try to support
+// this if this will actually happen often enough in real workloads.
+
+bool
+gtm_rwlock::write_lock_generic (gtm_thread *tx)
+{
+ // Try to acquire the write lock.
+ int w = 0;
+ if (unlikely (!writers.compare_exchange_strong (w, 1)))
+ {
+ // If this is an upgrade, we must not wait for other writers or
+ // upgrades.
+ if (tx != 0)
+ return false;
+
+ // There is already a writer. If there are no other waiting writers,
+ // switch to contended mode. We need seq_cst memory order to make the
+ // Dekker-style synchronization work.
+ if (w != 2)
+ w = writers.exchange (2);
+ while (w != 0)
+ {
+ futex_wait(&writers, 2);
+ w = writers.exchange (2);
+ }
+ }
+
+ // We have acquired the writer side of the R/W lock. Now wait for any
+ // readers that might still be active.
+ // We don't need an extra barrier here because the CAS and the xchg
+ // operations have full barrier semantics already.
+ // TODO In the worst case, this requires one wait/wake pair for each
+ // active reader. Reduce this!
+ for (gtm_thread *it = gtm_thread::list_of_threads; it != 0;
+ it = it->next_thread)
+ {
+ if (it == tx)
+ continue;
+ // Use a loop here to check reader flags again after waiting.
+ while (it->shared_state.load (memory_order_relaxed)
+ != ~(typeof it->shared_state)0)
+ {
+ // An active reader. Wait until it has finished. To avoid lost
+ // wake-ups, we need to use Dekker-like synchronization.
+ // Note that we can reset writer_readers to zero when we see after
+ // the barrier that the reader has finished in the meantime;
+ // however, this is only possible because we are the only writer.
+ // TODO Spin for a while on this reader flag.
+ writer_readers.store (1, memory_order_relaxed);
+ atomic_thread_fence (memory_order_seq_cst);
+ if (it->shared_state.load (memory_order_relaxed)
+ != ~(typeof it->shared_state)0)
+ futex_wait(&writer_readers, 1);
+ else
+ writer_readers.store (0, memory_order_relaxed);
+ }
+ }
+
+ return true;
+}
+
+// Acquire a RW lock for writing.
+
+void
+gtm_rwlock::write_lock ()
+{
+ write_lock_generic (0);
+}
+
+
+// Upgrade a RW lock that has been locked for reading to a writing lock.
+// Do this without possibility of another writer incoming. Return false
+// if this attempt fails (i.e. another thread also upgraded).
+
+bool
+gtm_rwlock::write_upgrade (gtm_thread *tx)
+{
+ return write_lock_generic (tx);
+}
+
+
+// Has to be called iff the previous upgrade was successful and after it is
+// safe for the transaction to not be marked as a reader anymore.
+
+void
+gtm_rwlock::write_upgrade_finish (gtm_thread *tx)
+{
+ // We are not a reader anymore. This is only safe to do after we have
+ // acquired the writer lock.
+ tx->shared_state.store (-1, memory_order_release);
+}
+
+
+// Release a RW lock from reading.
+
+void
+gtm_rwlock::read_unlock (gtm_thread *tx)
+{
+ // We only need release memory order here because of privatization safety
+ // (this ensures that marking the transaction as inactive happens after
+ // any prior data accesses by this transaction, and that neither the
+ // compiler nor the hardware order this store earlier).
+ // ??? We might be able to avoid this release here if the compiler can't
+ // merge the release fence with the subsequent seq_cst fence.
+ tx->shared_state.store (-1, memory_order_release);
+
+ // If there is a writer waiting for readers, wake it up. We need the fence
+ // to avoid lost wake-ups. Furthermore, the privatization safety
+ // implementation in gtm_thread::try_commit() relies on the existence of
+ // this seq_cst fence.
+ // ??? We might not be the last active reader, so the wake-up might happen
+ // too early. How do we avoid this without slowing down readers too much?
+ // Each reader could scan the list of txns for other active readers but
+ // this can result in many cache misses. Use combining instead?
+ // TODO Sends out one wake-up for each reader in the worst case.
+ atomic_thread_fence (memory_order_seq_cst);
+ if (unlikely (writer_readers.load (memory_order_relaxed) > 0))
+ {
+ // No additional barrier needed here (see write_unlock()).
+ writer_readers.store (0, memory_order_relaxed);
+ futex_wake(&writer_readers, 1);
+ }
+}
+
+
+// Release a RW lock from writing.
+
+void
+gtm_rwlock::write_unlock ()
+{
+ // This needs to have seq_cst memory order.
+ if (writers.fetch_sub (1) == 2)
+ {
+ // There might be waiting writers, so wake them.
+ writers.store (0, memory_order_relaxed);
+ if (futex_wake(&writers, 1) == 0)
+ {
+ // If we did not wake any waiting writers, we might indeed be the
+ // last writer (this can happen because write_lock_generic()
+ // exchanges 0 or 1 to 2 and thus might go to contended mode even if
+ // no other thread holds the write lock currently). Therefore, we
+ // have to wake up readers here as well. Execute a barrier after
+ // the previous relaxed reset of writers (Dekker-style), and fall
+ // through to the normal reader wake-up code.
+ atomic_thread_fence (memory_order_seq_cst);
+ }
+ else
+ return;
+ }
+ // No waiting writers, so wake up all waiting readers.
+ // Because the fetch_and_sub is a full barrier already, we don't need
+ // another barrier here (as in read_unlock()).
+ if (readers.load (memory_order_relaxed) > 0)
+ {
+ // No additional barrier needed here. The previous load must be in
+ // modification order because of the coherency constraints. Late stores
+ // by a reader are not a problem because readers do Dekker-style
+ // synchronization on writers.
+ readers.store (0, memory_order_relaxed);
+ futex_wake(&readers, INT_MAX);
+ }
+}
+
+} // namespace GTM
diff --git a/gcc-4.9/libitm/config/linux/rwlock.h b/gcc-4.9/libitm/config/linux/rwlock.h
new file mode 100644
index 000000000..e6188890b
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/rwlock.h
@@ -0,0 +1,81 @@
+/* Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ Contributed by Torvald Riegel <triegel@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GTM_RWLOCK_H
+#define GTM_RWLOCK_H
+
+#include "local_atomic"
+#include "common.h"
+
+namespace GTM HIDDEN {
+
+struct gtm_thread;
+
+// This datastructure is the blocking, futex-based version of the Dekker-style
+// reader-writer lock used to provide mutual exclusion between active and
+// serial transactions.
+// See libitm's documentation for further details.
+//
+// In this implementation, writers are given highest priority access but
+// read-to-write upgrades do not have a higher priority than writers.
+//
+// Do not change the layout of this class; it must remain a POD type with
+// standard layout, and the WRITERS field must be first (i.e., so the
+// assembler code can assume that its address is equal to the address of the
+// respective instance of the class).
+
+class gtm_rwlock
+{
+ // TODO Put futexes on different cachelines?
+ std::atomic<int> writers; // Writers' futex.
+ std::atomic<int> writer_readers;// A confirmed writer waits here for readers.
+ std::atomic<int> readers; // Readers wait here for writers (iff true).
+
+ public:
+ gtm_rwlock() : writers(0), writer_readers(0), readers(0) {};
+
+ void read_lock (gtm_thread *tx);
+ void read_unlock (gtm_thread *tx);
+
+ void write_lock ();
+ void write_unlock ();
+
+ bool write_upgrade (gtm_thread *tx);
+ void write_upgrade_finish (gtm_thread *tx);
+
+ // Returns true iff there is a concurrent active or waiting writer.
+ // This is primarily useful for simple HyTM approaches, and the value being
+ // checked is loaded with memory_order_relaxed.
+ bool is_write_locked()
+ {
+ return writers.load (memory_order_relaxed) != 0;
+ }
+
+ protected:
+ bool write_lock_generic (gtm_thread *tx);
+};
+
+} // namespace GTM
+
+#endif // GTM_RWLOCK_H
diff --git a/gcc-4.9/libitm/config/linux/sh/futex_bits.h b/gcc-4.9/libitm/config/linux/sh/futex_bits.h
new file mode 100644
index 000000000..55b866651
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/sh/futex_bits.h
@@ -0,0 +1,50 @@
+/* Copyright (C) 2011-2014 Free Software Foundation, Inc.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Provide target-specific access to the futex system call. */
+
+#include <sys/syscall.h>
+
+/* 4 instruction cycles not accessing cache and TLB are needed after
+ trapa instruction to avoid an SH-4 silicon bug. */
+
+#define SYSCALL_WITH_INST_PAD "\
+ trapa #0x14; or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0"
+
+static inline long
+sys_futex0 (std::atomic<int> *addr, long op, long val)
+{
+ int __status;
+ register long __r3 asm ("r3") = SYS_futex;
+ register long __r4 asm ("r4") = (long) addr;
+ register long __r5 asm ("r5") = op;
+ register long __r6 asm ("r6") = val;
+ register long __r7 asm ("r7") = 0;
+
+ __asm __volatile (SYSCALL_WITH_INST_PAD
+ : "=z" (__status)
+ : "r" (__r3), "r" (__r4), "r" (__r5),
+ "r" (__r6), "r" (__r7)
+ : "memory", "t");
+ return __status;
+}
diff --git a/gcc-4.9/libitm/config/linux/sparc/futex_bits.h b/gcc-4.9/libitm/config/linux/sparc/futex_bits.h
new file mode 100644
index 000000000..7e84df13e
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/sparc/futex_bits.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2012-2014 Free Software Foundation, Inc.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <sys/syscall.h>
+
+static inline long
+sys_futex0 (std::atomic<int> *addr, int op, int val)
+{
+ register long int g1 __asm__ ("g1");
+ register long int o0 __asm__ ("o0");
+ register long int o1 __asm__ ("o1");
+ register long int o2 __asm__ ("o2");
+ register long int o3 __asm__ ("o3");
+ long res;
+
+ g1 = SYS_futex;
+ o0 = (long) addr;
+ o1 = op;
+ o2 = val;
+ o3 = 0;
+
+#ifdef __arch64__
+ __asm volatile ("ta 0x6d"
+#else
+ __asm volatile ("ta 0x10"
+#endif
+ : "=r"(g1), "=r"(o0)
+ : "0"(g1), "1"(o0), "r"(o1), "r"(o2), "r"(o3)
+ : "g2", "g3", "g4", "g5", "g6",
+ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+ "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+ "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+ "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+ "f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46",
+ "f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62",
+ "cc", "memory");
+
+ res = o0;
+ if (__builtin_expect ((unsigned long) res >= -515UL, 0))
+ res =- res;
+ return res;
+}
diff --git a/gcc-4.9/libitm/config/linux/x86/futex_bits.h b/gcc-4.9/libitm/config/linux/x86/futex_bits.h
new file mode 100644
index 000000000..69016817a
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/x86/futex_bits.h
@@ -0,0 +1,82 @@
+/* Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifdef __x86_64__
+# ifndef SYS_futex
+# define SYS_futex 202
+# endif
+
+static inline long
+sys_futex0 (std::atomic<int> *addr, long op, long val)
+{
+ register long r10 __asm__("%r10") = 0;
+ long res;
+
+ __asm volatile ("syscall"
+ : "=a" (res)
+ : "0" (SYS_futex), "D" (addr), "S" (op), "d" (val), "r" (r10)
+ : "r11", "rcx", "memory");
+
+ return res;
+}
+
+#else
+# ifndef SYS_futex
+# define SYS_futex 240
+# endif
+
+# ifdef __PIC__
+
+static inline long
+sys_futex0 (std::atomic<int> *addr, int op, int val)
+{
+ long res;
+
+ __asm volatile ("xchgl\t%%ebx, %2\n\t"
+ "int\t$0x80\n\t"
+ "xchgl\t%%ebx, %2"
+ : "=a" (res)
+ : "0"(SYS_futex), "r" (addr), "c"(op),
+ "d"(val), "S"(0)
+ : "memory");
+ return res;
+}
+
+# else
+
+static inline long
+sys_futex0 (std::atomic<int> *addr, int op, int val)
+{
+ long res;
+
+ __asm volatile ("int $0x80"
+ : "=a" (res)
+ : "0"(SYS_futex), "b" (addr), "c"(op),
+ "d"(val), "S"(0)
+ : "memory");
+ return res;
+}
+
+# endif /* __PIC__ */
+#endif /* __x86_64__ */
diff --git a/gcc-4.9/libitm/config/linux/x86/tls.h b/gcc-4.9/libitm/config/linux/x86/tls.h
new file mode 100644
index 000000000..760e6e9ca
--- /dev/null
+++ b/gcc-4.9/libitm/config/linux/x86/tls.h
@@ -0,0 +1,105 @@
+/* Copyright (C) 2008-2014 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libitm is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef LIBITM_X86_TLS_H
+#define LIBITM_X86_TLS_H 1
+
+#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10)
+/* Use slots in the TCB head rather than __thread lookups.
+ GLIBC has reserved words 10 through 13 for TM. */
+#define HAVE_ARCH_GTM_THREAD 1
+#define HAVE_ARCH_GTM_THREAD_DISP 1
+#endif
+
+#include "config/generic/tls.h"
+
+#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10)
+namespace GTM HIDDEN {
+
+#ifdef __x86_64__
+#ifdef __LP64__
+# define SEG_READ(OFS) "movq\t%%fs:(" #OFS "*8),%0"
+# define SEG_WRITE(OFS) "movq\t%0,%%fs:(" #OFS "*8)"
+# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \
+ "rorq\t$17,%0\n\t" \
+ "xorq\t%%fs:48,%0"
+# define SEG_ENCODE_WRITE(OFS) "xorq\t%%fs:48,%0\n\t" \
+ "rolq\t$17,%0\n\t" \
+ SEG_WRITE(OFS)
+#else
+// For X32.
+# define SEG_READ(OFS) "movl\t%%fs:(" #OFS "*4),%0"
+# define SEG_WRITE(OFS) "movl\t%0,%%fs:(" #OFS "*4)"
+# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \
+ "rorl\t$9,%0\n\t" \
+ "xorl\t%%fs:24,%0"
+# define SEG_ENCODE_WRITE(OFS) "xorl\t%%fs:24,%0\n\t" \
+ "roll\t$9,%0\n\t" \
+ SEG_WRITE(OFS)
+#endif
+#else
+# define SEG_READ(OFS) "movl\t%%gs:(" #OFS "*4),%0"
+# define SEG_WRITE(OFS) "movl\t%0,%%gs:(" #OFS "*4)"
+# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \
+ "rorl\t$9,%0\n\t" \
+ "xorl\t%%gs:24,%0"
+# define SEG_ENCODE_WRITE(OFS) "xorl\t%%gs:24,%0\n\t" \
+ "roll\t$9,%0\n\t" \
+ SEG_WRITE(OFS)
+#endif
+
+static inline struct gtm_thread *gtm_thr(void)
+{
+ struct gtm_thread *r;
+ asm volatile (SEG_READ(10) : "=r"(r));
+ return r;
+}
+
+static inline void set_gtm_thr(struct gtm_thread *x)
+{
+ asm volatile (SEG_WRITE(10) : : "r"(x));
+}
+
+static inline struct abi_dispatch *abi_disp(void)
+{
+ struct abi_dispatch *r;
+ asm volatile (SEG_DECODE_READ(11) : "=r"(r));
+ return r;
+}
+
+static inline void set_abi_disp(struct abi_dispatch *x)
+{
+ void *scratch;
+ asm volatile (SEG_ENCODE_WRITE(11) : "=r"(scratch) : "0"(x));
+}
+
+#undef SEG_READ
+#undef SEG_WRITE
+#undef SEG_DECODE_READ
+#undef SEG_ENCODE_WRITE
+
+} // namespace GTM
+#endif /* >= GLIBC 2.10 */
+
+#endif // LIBITM_X86_TLS_H