diff options
Diffstat (limited to 'gcc-4.9/libitm/config/linux')
-rw-r--r-- | gcc-4.9/libitm/config/linux/alpha/futex_bits.h | 56 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/futex.cc | 83 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/futex.h | 39 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/futex_bits.h | 39 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/powerpc/futex_bits.h | 54 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/rwlock.cc | 282 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/rwlock.h | 81 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/sh/futex_bits.h | 50 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/sparc/futex_bits.h | 62 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/x86/futex_bits.h | 82 | ||||
-rw-r--r-- | gcc-4.9/libitm/config/linux/x86/tls.h | 105 |
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 |