diff options
Diffstat (limited to 'gcc-4.8.3/libitm/config')
39 files changed, 3837 insertions, 0 deletions
diff --git a/gcc-4.8.3/libitm/config/alpha/cacheline.h b/gcc-4.8.3/libitm/config/alpha/cacheline.h new file mode 100644 index 000000000..5d77bba28 --- /dev/null +++ b/gcc-4.8.3/libitm/config/alpha/cacheline.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2009-2013 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_ALPHA_CACHELINE_H +#define LIBITM_ALPHA_CACHELINE_H 1 + +// A cacheline is the smallest unit with which locks are associated. +// The current implementation of the _ITM_[RW] barriers assumes that +// all data types can fit (aligned) within a cachline, which means +// in practice sizeof(complex long double) is the smallest cacheline size. +// It ought to be small enough for efficient manipulation of the +// modification mask, below. +#define CACHELINE_SIZE 64 + +#include "config/generic/cacheline.h" + +#endif // LIBITM_ALPHA_CACHELINE_H diff --git a/gcc-4.8.3/libitm/config/alpha/sjlj.S b/gcc-4.8.3/libitm/config/alpha/sjlj.S new file mode 100644 index 000000000..0e51b971f --- /dev/null +++ b/gcc-4.8.3/libitm/config/alpha/sjlj.S @@ -0,0 +1,112 @@ +/* Copyright (C) 2009-2013 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/>. */ + + .text + .align 4 + .globl _ITM_beginTransaction + .ent _ITM_beginTransaction + +#define FRAME 144 + +_ITM_beginTransaction: + ldgp $29, 0($27) + subq $30, FRAME, $30 + .frame $30, FRAME, $26, 0 + .mask 0x04000000, 0 + stq $26, 0($30) + .prologue 1 + + stq $9, 8($30) + stq $10, 16($30) + addq $30, FRAME, $0 + stq $11, 24($30) + + stq $12, 32($30) + stq $13, 40($30) + stq $14, 48($30) + stq $15, 56($30) + + stq $0, 64($30) + stt $f2, 72($30) + stt $f3, 80($30) + stt $f4, 88($30) + + stt $f5, 96($30) + stt $f6, 104($30) + stt $f7, 112($30) + stt $f8, 120($30) + + stt $f9, 128($30) + mov $30, $17 +#ifdef __PIC__ + unop + bsr $26, GTM_begin_transaction !samegp +#else + jsr $26, GTM_begin_transaction + ldgp $29, 0($26) +#endif + + ldq $26, 0($30) + addq $30, FRAME, $30 + ret +.end _ITM_beginTransaction + + .align 4 + .globl GTM_longjmp +#ifdef __ELF__ + .hidden GTM_longjmp +#endif + .ent GTM_longjmp + +GTM_longjmp: + .prologue 0 + ldq $26, 0($17) + ldq $9, 8($17) + ldq $10, 16($17) + ldq $11, 24($17) + + ldq $12, 32($17) + ldq $13, 40($17) + ldq $14, 48($17) + ldq $15, 56($17) + + ldq $1, 64($17) + ldt $f2, 72($17) + ldt $f3, 80($17) + ldt $f4, 88($17) + + ldt $f5, 96($17) + ldt $f6, 104($17) + ldt $f7, 112($17) + ldt $f8, 120($17) + + ldt $f9, 128($17) + mov $16, $0 + mov $1, $30 + ret +.end GTM_longjmp + +#ifdef __linux__ +.section .note.GNU-stack, "", @progbits +#endif diff --git a/gcc-4.8.3/libitm/config/alpha/target.h b/gcc-4.8.3/libitm/config/alpha/target.h new file mode 100644 index 000000000..434a4d712 --- /dev/null +++ b/gcc-4.8.3/libitm/config/alpha/target.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2009-2013 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/>. */ + +namespace GTM HIDDEN { + +typedef struct gtm_jmpbuf +{ + unsigned long pc; + unsigned long s[7]; + void *cfa; + unsigned long f[8]; +} gtm_jmpbuf; + +/* Alpha generally uses a fixed page size of 8K. */ +#define PAGE_SIZE 8192 +#define FIXED_PAGE_SIZE 1 + +/* The size of one line in hardware caches (in bytes). */ +#define HW_CACHELINE_SIZE 64 + +static inline void +cpu_relax (void) +{ + __asm volatile ("" : : : "memory"); +} + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/arm/hwcap.cc b/gcc-4.8.3/libitm/config/arm/hwcap.cc new file mode 100644 index 000000000..d064917b6 --- /dev/null +++ b/gcc-4.8.3/libitm/config/arm/hwcap.cc @@ -0,0 +1,67 @@ +/* Copyright (C) 2011-2013 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/>. */ + +/* This file initializes GTM_hwcap in some os-specific way to indicate + what ISA extensions are present for ARM. */ + +#include "libitm_i.h" +#include "hwcap.h" + +/* Begin by defaulting to whatever options were given to the compiler. */ +int GTM_hwcap HIDDEN = 0 +#ifdef __VFP_FP__ + | HWCAP_ARM_VFP +#endif +#ifdef __IWMMXT__ + | HWCAP_ARM_IWMMXT +#endif + ; + +#ifdef __linux__ +#include <unistd.h> +#include <sys/fcntl.h> +#include <elf.h> + +static void __attribute__((constructor)) +init_gtm_hwcap(void) +{ + int fd = open ("/proc/self/auxv", O_RDONLY); + if (fd < 0) + return; + + Elf32_auxv_t pairs[512]; + ssize_t rlen = read (fd, pairs, sizeof(pairs)); + close (fd); + if (rlen < 0) + return; + + size_t n = (size_t)rlen / sizeof(pairs[0]); + for (size_t i = 0; i < n; ++i) + if (pairs[i].a_type == AT_HWCAP) + { + GTM_hwcap = pairs[i].a_un.a_val; + return; + } +} +#endif diff --git a/gcc-4.8.3/libitm/config/arm/hwcap.h b/gcc-4.8.3/libitm/config/arm/hwcap.h new file mode 100644 index 000000000..556b88dda --- /dev/null +++ b/gcc-4.8.3/libitm/config/arm/hwcap.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2011-2013 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/>. */ + +/* The following must match the kernel's <asm/procinfo.h>. */ +#define HWCAP_ARM_SWP 1 +#define HWCAP_ARM_HALF 2 +#define HWCAP_ARM_THUMB 4 +#define HWCAP_ARM_26BIT 8 +#define HWCAP_ARM_FAST_MULT 16 +#define HWCAP_ARM_FPA 32 +#define HWCAP_ARM_VFP 64 +#define HWCAP_ARM_EDSP 128 +#define HWCAP_ARM_JAVA 256 +#define HWCAP_ARM_IWMMXT 512 +#define HWCAP_ARM_CRUNCH 1024 +#define HWCAP_ARM_THUMBEE 2048 +#define HWCAP_ARM_NEON 4096 +#define HWCAP_ARM_VFPv3 8192 +#define HWCAP_ARM_VFPv3D16 16384 + diff --git a/gcc-4.8.3/libitm/config/arm/sjlj.S b/gcc-4.8.3/libitm/config/arm/sjlj.S new file mode 100644 index 000000000..b6b6f5799 --- /dev/null +++ b/gcc-4.8.3/libitm/config/arm/sjlj.S @@ -0,0 +1,164 @@ +/* Copyright (C) 2011-2013 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 "hwcap.h" +#include "asmcfi.h" + + .syntax unified + +#if defined(__thumb2__) +# define PC_OFS 4 + .thumb + .thumb_func +#else +# define PC_OFS 8 +#endif + +#if defined (__thumb2__) && defined(__ARM_ARCH_6T2__) +# define HAVE_MOVT + .arch armv6t2 +#elif defined (__ARM_ARCH_7A__) +# define HAVE_MOVT + .arch armv7-a +#elif defined (__ARM_ARCH_7R__) +# define HAVE_MOVT + .arch armv7-r +#elif defined (__ARM_ARCH_7M__) +# define HAVE_MOVT + .arch armv7-m +#endif + +#if defined(HAVE_MOVT) && defined(PIC) +.macro ldaddr reg, addr + movw \reg, #:lower16:(\addr - (98f + PC_OFS)) + movt \reg, #:upper16:(\addr - (98f + PC_OFS)) +98: add \reg, \reg, pc +.endm +#elif defined(HAVE_MOVT) +.macro ldaddr reg, addr + movw \reg, #:lower16:\addr + movt \reg, #:upper16:\addr +.endm +#elif defined(PIC) +.macro ldaddr reg, addr + ldr \reg, 99f +98: add \reg, \reg, pc +.subsection 1 + .align 2 +99: .word \addr - (98b + PC_OFS) +.subsection 0 +.endm +#else +.macro ldaddr reg, addr + ldr \reg, =\addr +.endm +#endif + + .text + .align 2 + .global _ITM_beginTransaction + .type _ITM_beginTransaction, %function + +_ITM_beginTransaction: + .fnstart + cfi_startproc + mov ip, sp + push { r4-r11, ip, lr } + .save { lr } + .pad #(9*4) + cfi_adjust_cfa_offset(40) + cfi_rel_offset(lr, 36) + sub sp, sp, #(14*8) + .pad #(14*8) + cfi_adjust_cfa_offset(14*8) + + ldaddr r2, GTM_hwcap + ldr r2, [r2] + + /* Store the VFP registers. Don't use VFP instructions directly + because this code is used in non-VFP multilibs. */ + tst r2, #HWCAP_ARM_VFP + beq 1f + stc p11, cr8, [sp], {16} /* vstm sp, {d8-d15} */ +1: + /* Save the call-preserved iWMMXt registers. */ + tst r2, #HWCAP_ARM_IWMMXT + beq 1f + stcl p1, cr10, [sp, #64] /* wstrd wr10, [sp, #64] */ + stcl p1, cr11, [sp, #72] + stcl p1, cr12, [sp, #80] + stcl p1, cr13, [sp, #88] + stcl p1, cr14, [sp, #96] + stcl p1, cr15, [sp, #104] +1: + /* Invoke GTM_begin_transaction with the struct we just built. */ + mov r1, sp + bl GTM_begin_transaction + + /* Return; we don't need to restore any of the call-saved regs. */ + add sp, sp, #(14*8 + 9*4) + cfi_adjust_cfa_offset(-(14*8 + 9*4)) + pop { pc } + .fnend + cfi_endproc + .size _ITM_beginTransaction, . - _ITM_beginTransaction + + .align 2 + .global GTM_longjmp + .hidden GTM_longjmp + .type GTM_longjmp, %function + +GTM_longjmp: + cfi_startproc + ldaddr r2, GTM_hwcap + ldr r2, [r2] + + tst r2, #HWCAP_ARM_VFP + beq 1f + ldc p11, cr8, [r1], {16} /* vldmia r1, {d8-d15} */ +1: + tst r2, #HWCAP_ARM_IWMMXT + beq 1f + ldcl p1, cr10, [r1, #64] /* wldrd wr10, [r1, #64] */ + ldcl p1, cr11, [r1, #72] + ldcl p1, cr12, [r1, #80] + ldcl p1, cr13, [r1, #88] + ldcl p1, cr14, [r1, #96] + ldcl p1, cr15, [r1, #104] +1: + add r1, r1, #(14*8) /* Skip both VFP and iWMMXt blocks */ +#ifdef __thumb2__ + ldm r1, { r4-r11, ip, lr } + cfi_def_cfa(ip, 0) + mov sp, ip + bx lr +#else + ldm r1, { r4-r11, sp, pc } +#endif + cfi_endproc + .size GTM_longjmp, . - GTM_longjmp + +#ifdef __linux__ +.section .note.GNU-stack, "", %progbits +#endif diff --git a/gcc-4.8.3/libitm/config/arm/target.h b/gcc-4.8.3/libitm/config/arm/target.h new file mode 100644 index 000000000..54ef62691 --- /dev/null +++ b/gcc-4.8.3/libitm/config/arm/target.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2011-2013 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/>. */ + +namespace GTM HIDDEN { + +typedef struct gtm_jmpbuf +{ + unsigned long long vfp[8]; /* d8-d15 */ + unsigned long long iwmmxt[6]; /* cr10-cr15 */ + unsigned long gr[8]; /* r4-r11 */ + void *cfa; + unsigned long pc; +} gtm_jmpbuf; + +/* ARM generally uses a fixed page size of 4K. */ +#define PAGE_SIZE 4096 +#define FIXED_PAGE_SIZE 1 + +/* ??? The size of one line in hardware caches (in bytes). */ +#define HW_CACHELINE_SIZE 64 + +static inline void +cpu_relax (void) +{ + /* ??? The kernel uses the condition + #if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327) + Given that we're actually just waiting, it doesn't seem like it + hurts to simply use a full barrier all the time. */ + __sync_synchronize (); +} + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/generic/asmcfi.h b/gcc-4.8.3/libitm/config/generic/asmcfi.h new file mode 100644 index 000000000..59d73924b --- /dev/null +++ b/gcc-4.8.3/libitm/config/generic/asmcfi.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2011-2013 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 "config.h" + +#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__GCC_HAVE_DWARF2_CFI_ASM) + +#define cfi_startproc .cfi_startproc +#define cfi_endproc .cfi_endproc +#define cfi_adjust_cfa_offset(n) .cfi_adjust_cfa_offset n +#define cfi_def_cfa_offset(n) .cfi_def_cfa_offset n +#define cfi_def_cfa(r,n) .cfi_def_cfa r, n +#define cfi_rel_offset(r,o) .cfi_rel_offset r, o +#define cfi_register(o,n) .cfi_register o, n +#define cfi_offset(r,o) .cfi_offset r, o +#define cfi_restore(r) .cfi_restore r +#define cfi_undefined(r) .cfi_undefined r + +#else + +#define cfi_startproc +#define cfi_endproc +#define cfi_adjust_cfa_offset(n) +#define cfi_def_cfa_offset(n) +#define cfi_def_cfa(r,n) +#define cfi_rel_offset(r,o) +#define cfi_register(o,n) +#define cfi_offset(r,o) +#define cfi_restore(r) +#define cfi_undefined(r) + +#endif /* HAVE_AS_CFI_PSEUDO_OP && __GCC_HAVE_DWARF2_CFI_ASM */ diff --git a/gcc-4.8.3/libitm/config/generic/cacheline.h b/gcc-4.8.3/libitm/config/generic/cacheline.h new file mode 100644 index 000000000..f193e719b --- /dev/null +++ b/gcc-4.8.3/libitm/config/generic/cacheline.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2009-2013 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_CACHELINE_H +#define LIBITM_CACHELINE_H 1 + +namespace GTM HIDDEN { + +// A cacheline is the smallest unit with which locks are associated. +// The current implementation of the _ITM_[RW] barriers assumes that +// all data types can fit (aligned) within a cachline, which means +// in practice sizeof(complex long double) is the smallest cacheline size. +// It ought to be small enough for efficient manipulation of the +// modification mask, below. +#ifndef CACHELINE_SIZE +# define CACHELINE_SIZE 32 +#endif + +// A gtm_cacheline_mask stores a modified bit for every modified byte +// in the cacheline with which it is associated. +typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask; + +union gtm_cacheline +{ + // Byte access to the cacheline. + unsigned char b[CACHELINE_SIZE] __attribute__((aligned(CACHELINE_SIZE))); + + // Larger sized access to the cacheline. + uint16_t u16[CACHELINE_SIZE / sizeof(uint16_t)]; + uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)]; + uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)]; + gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)]; +}; + +} // namespace GTM + +#endif // LIBITM_CACHELINE_H diff --git a/gcc-4.8.3/libitm/config/generic/tls.cc b/gcc-4.8.3/libitm/config/generic/tls.cc new file mode 100644 index 000000000..ff7eed1ca --- /dev/null +++ b/gcc-4.8.3/libitm/config/generic/tls.cc @@ -0,0 +1,40 @@ +/* Copyright (C) 2010-2013 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 "libitm_i.h" + +namespace GTM HIDDEN { + +#if !defined(HAVE_ARCH_GTM_THREAD) || !defined(HAVE_ARCH_GTM_THREAD_DISP) +__thread gtm_thread_tls _gtm_thr_tls; +#endif + +// See tls.h for comments. +void * __attribute__((noinline)) +mask_stack_bottom(gtm_thread *tx) +{ + return (uint8_t*)__builtin_dwarf_cfa() - 256; +} + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/generic/tls.h b/gcc-4.8.3/libitm/config/generic/tls.h new file mode 100644 index 000000000..13e2b12cc --- /dev/null +++ b/gcc-4.8.3/libitm/config/generic/tls.h @@ -0,0 +1,82 @@ +/* Copyright (C) 2008-2013 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_TLS_H +#define LIBITM_TLS_H 1 + +namespace GTM HIDDEN { + +#if !defined(HAVE_ARCH_GTM_THREAD) || !defined(HAVE_ARCH_GTM_THREAD_DISP) +// Provides a single place to store all this libraries thread-local data. +struct gtm_thread_tls +{ +#ifndef HAVE_ARCH_GTM_THREAD + // The currently active transaction. Elided if the target provides + // some efficient mechanism for storing this. + gtm_thread *thr; +#endif +#ifndef HAVE_ARCH_GTM_THREAD_DISP + // The dispatch table for the STM implementation currently in use. Elided + // if the target provides some efficient mechanism for storing this. + abi_dispatch *disp; +#endif +}; + +extern __thread gtm_thread_tls _gtm_thr_tls; +#endif + +#ifndef HAVE_ARCH_GTM_THREAD +// If the target does not provide optimized access to the thread-local +// data, simply access the TLS variable defined above. +static inline gtm_thread *gtm_thr() { return _gtm_thr_tls.thr; } +static inline void set_gtm_thr(gtm_thread *x) { _gtm_thr_tls.thr = x; } +#endif + +#ifndef HAVE_ARCH_GTM_THREAD_DISP +// If the target does not provide optimized access to the currently +// active dispatch table, simply access via GTM_THR. +static inline abi_dispatch * abi_disp() { return _gtm_thr_tls.disp; } +static inline void set_abi_disp(abi_dispatch *x) { _gtm_thr_tls.disp = x; } +#endif + +#ifndef HAVE_ARCH_GTM_MASK_STACK +// To filter out any updates that overlap the libitm stack, we define +// gtm_mask_stack_top to the entry point to the library and +// gtm_mask_stack_bottom to below the calling function (enforced with the +// noinline attribute). This definition should be fine for all +// stack-grows-down architectures. +// FIXME We fake the bottom to be lower so that we are safe even if we might +// call further functions (compared to where we called gtm_mask_stack_bottom +// in the call hierarchy) to actually undo or redo writes (e.g., memcpy). +// This is a completely arbitrary value; can we instead ensure that there are +// no such calls, or can we determine a future-proof value otherwise? +static inline void * +mask_stack_top(gtm_thread *tx) { return tx->jb.cfa; } +void * __attribute__((noinline)) +mask_stack_bottom(gtm_thread *tx); +#endif + +} // namespace GTM + +#endif // LIBITM_TLS_H diff --git a/gcc-4.8.3/libitm/config/linux/alpha/futex_bits.h b/gcc-4.8.3/libitm/config/linux/alpha/futex_bits.h new file mode 100644 index 000000000..8836e4840 --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/alpha/futex_bits.h @@ -0,0 +1,56 @@ +/* Copyright (C) 2008-2013 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.8.3/libitm/config/linux/futex.cc b/gcc-4.8.3/libitm/config/linux/futex.cc new file mode 100644 index 000000000..aec13e807 --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/futex.cc @@ -0,0 +1,83 @@ +/* Copyright (C) 2008-2013 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.8.3/libitm/config/linux/futex.h b/gcc-4.8.3/libitm/config/linux/futex.h new file mode 100644 index 000000000..3e5625547 --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/futex.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2008-2013 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.8.3/libitm/config/linux/futex_bits.h b/gcc-4.8.3/libitm/config/linux/futex_bits.h new file mode 100644 index 000000000..fd79652e3 --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/futex_bits.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2011-2013 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> +#include <errno.h> + +static inline long +sys_futex0 (std::atomic<int> *addr, long op, long val) +{ + long res = syscall (SYS_futex, (int*) addr, op, val, 0); + if (__builtin_expect (res == -1, 0)) + return -errno; + return res; +} diff --git a/gcc-4.8.3/libitm/config/linux/powerpc/futex_bits.h b/gcc-4.8.3/libitm/config/linux/powerpc/futex_bits.h new file mode 100644 index 000000000..f26abf639 --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/powerpc/futex_bits.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2012-2013 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.8.3/libitm/config/linux/rwlock.cc b/gcc-4.8.3/libitm/config/linux/rwlock.cc new file mode 100644 index 000000000..47a420bda --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/rwlock.cc @@ -0,0 +1,282 @@ +/* Copyright (C) 2011-2013 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.8.3/libitm/config/linux/rwlock.h b/gcc-4.8.3/libitm/config/linux/rwlock.h new file mode 100644 index 000000000..428299f1b --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/rwlock.h @@ -0,0 +1,76 @@ +/* Copyright (C) 2011-2013 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. + +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.8.3/libitm/config/linux/sh/futex_bits.h b/gcc-4.8.3/libitm/config/linux/sh/futex_bits.h new file mode 100644 index 000000000..40dc6b693 --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/sh/futex_bits.h @@ -0,0 +1,50 @@ +/* Copyright (C) 2011-2013 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.8.3/libitm/config/linux/sparc/futex_bits.h b/gcc-4.8.3/libitm/config/linux/sparc/futex_bits.h new file mode 100644 index 000000000..2b0f5da6b --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/sparc/futex_bits.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2012-2013 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.8.3/libitm/config/linux/x86/futex_bits.h b/gcc-4.8.3/libitm/config/linux/x86/futex_bits.h new file mode 100644 index 000000000..fd513081e --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/x86/futex_bits.h @@ -0,0 +1,82 @@ +/* Copyright (C) 2008-2013 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.8.3/libitm/config/linux/x86/tls.h b/gcc-4.8.3/libitm/config/linux/x86/tls.h new file mode 100644 index 000000000..4e0115f5a --- /dev/null +++ b/gcc-4.8.3/libitm/config/linux/x86/tls.h @@ -0,0 +1,105 @@ +/* Copyright (C) 2008-2013 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 diff --git a/gcc-4.8.3/libitm/config/posix/rwlock.cc b/gcc-4.8.3/libitm/config/posix/rwlock.cc new file mode 100644 index 000000000..488e9c237 --- /dev/null +++ b/gcc-4.8.3/libitm/config/posix/rwlock.cc @@ -0,0 +1,307 @@ +/* Copyright (C) 2008-2013 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 "libitm_i.h" + +namespace GTM HIDDEN { + +// Initialize a new RW lock. +// ??? Move this back to the header file when constexpr is implemented. + +gtm_rwlock::gtm_rwlock() + : mutex (PTHREAD_MUTEX_INITIALIZER), + c_readers (PTHREAD_COND_INITIALIZER), + c_writers (PTHREAD_COND_INITIALIZER), + c_confirmed_writers (PTHREAD_COND_INITIALIZER), + summary (0), + a_readers (0), + w_readers (0), + w_writers (0) +{ } + +gtm_rwlock::~gtm_rwlock() +{ + pthread_mutex_destroy (&this->mutex); + pthread_cond_destroy (&this->c_readers); + pthread_cond_destroy (&this->c_writers); +} + +// Acquire a RW lock for reading. + +void +gtm_rwlock::read_lock (gtm_thread *tx) +{ + // Fast path: first announce our intent to read, then check for conflicting + // intents to write. The fence ensure that this happens in exactly this + // order. + tx->shared_state.store (0, memory_order_relaxed); + atomic_thread_fence (memory_order_seq_cst); + unsigned int sum = this->summary.load (memory_order_relaxed); + if (likely(!(sum & (a_writer | w_writer)))) + return; + + // There seems to be an active, waiting, or confirmed writer, so enter the + // mutex-based slow path. To try to keep the number of readers small that + // the writer will see, we clear our read flag right away before entering + // the critical section. Otherwise, the writer would have to wait for us to + // get into the critical section. (Note that for correctness, this only has + // to happen before we leave the slow path and before we wait for any + // writer). + // ??? Add a barrier to enforce early visibility of this? + tx->shared_state.store(-1, memory_order_relaxed); + + pthread_mutex_lock (&this->mutex); + + // Read summary again after acquiring the mutex because it might have + // changed during waiting for the mutex to become free. + sum = this->summary.load (memory_order_relaxed); + + // If there is a writer waiting for readers, wake it up. Only do that if we + // might be the last reader that could do the wake-up, otherwise skip the + // wake-up but decrease a_readers to show that we have entered the slow path. + // This has to happen before we wait for any writers or upgraders. + // See write_lock_generic() for further explanations. + if (this->a_readers > 0) + { + this->a_readers--; + if (this->a_readers == 0) + pthread_cond_signal(&this->c_confirmed_writers); + } + + // If there is an active or waiting writer, we must wait. + while (sum & (a_writer | w_writer)) + { + this->summary.store (sum | w_reader, memory_order_relaxed); + this->w_readers++; + pthread_cond_wait (&this->c_readers, &this->mutex); + sum = this->summary.load (memory_order_relaxed); + if (--this->w_readers == 0) + sum &= ~w_reader; + } + + // Otherwise we can acquire the lock for read. + tx->shared_state.store(0, memory_order_relaxed); + + pthread_mutex_unlock(&this->mutex); +} + + +// 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) +{ + pthread_mutex_lock (&this->mutex); + + unsigned int sum = this->summary.load (memory_order_relaxed); + + // If there is an active writer, wait. + while (sum & a_writer) + { + if (tx != 0) + { + // If this is an upgrade, we must not wait for other writers or + // upgrades that already have gone in + pthread_mutex_unlock (&this->mutex); + return false; + } + + this->summary.store (sum | w_writer, memory_order_relaxed); + this->w_writers++; + pthread_cond_wait (&this->c_writers, &this->mutex); + sum = this->summary.load (memory_order_relaxed); + if (--this->w_writers == 0) + sum &= ~w_writer; + } + + // Otherwise we can acquire the lock for write. As a writer, we have + // priority, so we don't need to take this back. + this->summary.store (sum | a_writer, memory_order_relaxed); + + // We still need to wait for active readers to finish. The barrier makes + // sure that we first set our write intent and check for active readers + // after that, in strictly this order (similar to the barrier in the fast + // path of read_lock()). + atomic_thread_fence(memory_order_seq_cst); + + // Count the number of active readers to be able to decrease the number of + // wake-ups and wait calls that are necessary. + // + // This number is an upper bound of the number of readers that actually + // are still active and which we need to wait for: + // - We set our write flag before checking the reader flags, and readers + // check our write flag after clearing their read flags in read_unlock(). + // Therefore, they will enter the slow path whenever we have seen them. + // - Readers will have cleared their read flags before leaving the slow + // path in read_lock() (prevents lost wake-ups), and before waiting for + // any writer (prevents deadlocks). + // + // However, this number is also just a lower bound of the number of readers + // that will actually enter the slow path in read_unlock() or read_lock(): + // - Because the read flag is cleared outside of a critical section, writers + // can see it as cleared while the reader still goes into the slow path. + // + // Therefore, readers can skip (lower bound - 1) wake-ups, but we do need + // the following loop to check that the readers that we wanted to wait for + // are actually those that entered the slow path so far (and either skipped + // or sent a wake-up). + // + // ??? Do we need to optimize further? (The writer could publish a list of + // readers that it suspects to be active. Readers could check this list and + // only decrement a_readers if they are in this list.) + for (;;) + { + // ??? Keep a list of active readers that we saw and update it on the + // next retry instead? This might reduce the number of cache misses that + // we get when checking reader flags. + int readers = 0; + for (gtm_thread *it = gtm_thread::list_of_threads; it != 0; + it = it->next_thread) + { + // Don't count ourself if this is an upgrade. + if (it == tx) + continue; + if (it->shared_state.load(memory_order_relaxed) != (gtm_word)-1) + readers++; + } + + // If we have not seen any readers, we will not wait. + if (readers == 0) + break; + + // We've seen a number of readers, so we publish this number and wait. + this->a_readers = readers; + pthread_cond_wait (&this->c_confirmed_writers, &this->mutex); + } + + pthread_mutex_unlock (&this->mutex); + 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); + // We need this seq_cst fence here to avoid lost wake-ups. Furthermore, + // the privatization safety implementation in gtm_thread::try_commit() + // relies on the existence of this seq_cst fence. + atomic_thread_fence (memory_order_seq_cst); + unsigned int sum = this->summary.load (memory_order_relaxed); + if (likely(!(sum & (a_writer | w_writer)))) + return; + + // There is a writer, either active or waiting for other readers or writers. + // Thus, enter the mutex-based slow path. + pthread_mutex_lock (&this->mutex); + + // If there is a writer waiting for readers, wake it up. Only do that if we + // might be the last reader that could do the wake-up, otherwise skip the + // wake-up and decrease a_readers to publish that we have entered the slow + // path but skipped the wake-up. + if (this->a_readers > 0) + { + this->a_readers--; + if (this->a_readers == 0) + pthread_cond_signal(&this->c_confirmed_writers); + } + + // We don't need to wake up any writers waiting for other writers. Active + // writers will take care of that. + + pthread_mutex_unlock (&this->mutex); +} + + +// Release a RW lock from writing. + +void +gtm_rwlock::write_unlock () +{ + pthread_mutex_lock (&this->mutex); + + unsigned int sum = this->summary.load (memory_order_relaxed); + this->summary.store (sum & ~a_writer, memory_order_relaxed); + + // If there is a waiting writer, wake it. + if (unlikely (sum & w_writer)) + pthread_cond_signal (&this->c_writers); + + // If there are waiting readers, wake them. + else if (unlikely (sum & w_reader)) + pthread_cond_broadcast (&this->c_readers); + + pthread_mutex_unlock (&this->mutex); +} + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/posix/rwlock.h b/gcc-4.8.3/libitm/config/posix/rwlock.h new file mode 100644 index 000000000..2e415286a --- /dev/null +++ b/gcc-4.8.3/libitm/config/posix/rwlock.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2009-2013 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 GTM_RWLOCK_H +#define GTM_RWLOCK_H + +#include <pthread.h> +#include "local_atomic" + +namespace GTM HIDDEN { + +struct gtm_thread; + +// This datastructure is the blocking, mutex-based side of the Dekker-style +// reader-writer lock used to provide mutual exclusion between active and +// serial transactions. It has similarities to POSIX pthread_rwlock_t except +// that we also provide for upgrading a reader->writer lock, with a +// positive indication of failure (another writer acquired the lock +// before we were able to acquire). While the writer flag (a_writer below) is +// global and protected by the mutex, there are per-transaction reader flags, +// which are stored in a transaction's shared state. +// 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. + +class gtm_rwlock +{ + pthread_mutex_t mutex; // Held if manipulating any field. + pthread_cond_t c_readers; // Readers wait here + pthread_cond_t c_writers; // Writers wait here for writers + pthread_cond_t c_confirmed_writers; // Writers wait here for readers + + static const unsigned a_writer = 1; // An active writer. + static const unsigned w_writer = 2; // The w_writers field != 0 + static const unsigned w_reader = 4; // The w_readers field != 0 + + std::atomic<unsigned int> summary; // Bitmask of the above. + unsigned int a_readers; // Nr active readers as observed by a writer + unsigned int w_readers; // Nr waiting readers + unsigned int w_writers; // Nr waiting writers + + public: + gtm_rwlock(); + ~gtm_rwlock(); + + 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 summary.load (memory_order_relaxed) & (a_writer | w_writer); + } + + protected: + bool write_lock_generic (gtm_thread *tx); +}; + +} // namespace GTM + +#endif // GTM_RWLOCK_H diff --git a/gcc-4.8.3/libitm/config/powerpc/cacheline.h b/gcc-4.8.3/libitm/config/powerpc/cacheline.h new file mode 100644 index 000000000..397adafc8 --- /dev/null +++ b/gcc-4.8.3/libitm/config/powerpc/cacheline.h @@ -0,0 +1,42 @@ +/* Copyright (C) 2012-2013 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_POWERPC_CACHELINE_H +#define LIBITM_POWERPC_CACHELINE_H 1 + +// A cacheline is the smallest unit with which locks are associated. +// The current implementation of the _ITM_[RW] barriers assumes that +// all data types can fit (aligned) within a cachline, which means +// in practice sizeof(complex long double) is the smallest cacheline size. +// It ought to be small enough for efficient manipulation of the +// modification mask, below. +#if defined (__powerpc64__) || defined (__ppc64__) +# define CACHELINE_SIZE 64 +#else +# define CACHELINE_SIZE 32 +#endif + +#include "config/generic/cacheline.h" + +#endif // LIBITM_POWERPC_CACHELINE_H diff --git a/gcc-4.8.3/libitm/config/powerpc/sjlj.S b/gcc-4.8.3/libitm/config/powerpc/sjlj.S new file mode 100644 index 000000000..4a0b43dbb --- /dev/null +++ b/gcc-4.8.3/libitm/config/powerpc/sjlj.S @@ -0,0 +1,433 @@ +/* Copyright (C) 2012-2013 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/>. */ + + .text + +#include "asmcfi.h" + +#if defined(__powerpc64__) && _CALL_ELF == 2 +.macro FUNC name + .globl \name + .type \name, @function +\name: +0: addis 2,12,(.TOC.-0b)@ha + addi 2,2,(.TOC.-0b)@l + .localentry \name, . - \name +.endm +.macro END name + .size \name, . - \name +.endm +.macro HIDDEN name + .hidden \name +.endm +.macro CALL name + bl \name + nop +.endm +#elif defined(__powerpc64__) && defined(__ELF__) +.macro FUNC name + .globl \name, .\name + .section ".opd","aw" + .align 3 +\name: + .quad .\name, .TOC.@tocbase, 0 + .size \name, 24 + .type .\name, @function + .text +.\name: +.endm +.macro END name + .size .\name, . - .\name +.endm +.macro HIDDEN name + .hidden \name, .\name +.endm +.macro CALL name + bl \name + nop +.endm +#elif defined(__ELF__) +.macro FUNC name + .globl \name + .type \name, @function +\name: +.endm +.macro END name + .size \name, . - \name +.endm +.macro HIDDEN name + .hidden \name +.endm +.macro CALL name + bl \name +.endm +#elif defined(_CALL_DARWIN) +.macro FUNC name + .globl _$0 +_$0: +.endmacro +.macro END name +.endmacro +.macro HIDDEN name + .private_extern _$0 +.endmacro +.macro CALL name + bl _$0 +.endmacro +# ifdef __ppc64__ + .machine ppc64 +# else + .machine ppc7400 +# endif +#else +#error "unsupported system" +#endif + +/* Parameterize the naming of registers. */ +#if defined(__ELF__) +# define r(N) %r##N +# define f(N) %f##N +# define v(N) %v##N +#elif defined(__MACH__) +# define r(N) r##N +# define f(N) f##N +# define v(N) v##N +#else +# define r(N) N +# define f(N) N +# define v(N) N +#endif + +/* Parameterize the code for 32-bit vs 64-bit. */ +#if defined(__powerpc64__) || defined(__ppc64__) +#define ldreg ld +#define streg std +#define stregu stdu +#define WS 8 +#else +#define ldreg lwz +#define streg stw +#define stregu stwu +#define WS 4 +#endif + +/* Parameterize the code for call frame constants. */ +#if defined(_CALL_AIXDESC) +# define BASE 6*WS +# define LR_SAVE 2*WS +#elif _CALL_ELF == 2 +# define BASE 6*WS +# define LR_SAVE 2*WS +#elif defined(_CALL_SYSV) +# define BASE 2*WS +# define LR_SAVE 1*WS +#elif defined(_CALL_DARWIN) +# define BASE (6*WS + 2*WS) +# define LR_SAVE 2*WS +#else +# error "unsupported system" +#endif + +#if defined(__ALTIVEC__) || defined(__VSX__) +# define OFS_VR 0 +# define OFS_VSCR 12*16 +# define OFS_VR_END OFS_VSCR + 8 +#else +# define OFS_VR_END 0 +#endif +#ifndef _SOFT_FLOAT +# define OFS_FR OFS_VR_END +# define OFS_FPSCR OFS_FR + 18*8 +# define OFS_FR_END OFS_FPSCR + 8 +#else +# define OFS_FR_END OFS_VR_END +#endif +#define OFS_GR OFS_FR_END +#define OFS_CFA OFS_GR + 18*WS +#define OFS_LR OFS_CFA + WS +#define OFS_TOC OFS_LR + WS +#define OFS_CR OFS_TOC + WS +#define OFS_END (((OFS_CR + WS + 15) / 16) * 16) + +#define FRAME (((BASE + OFS_END + 15) / 16) * 16) +#define VRSAVE 256 + + .align 4 +FUNC _ITM_beginTransaction + cfi_startproc + mflr r(0) + mfcr r(5) + addi r(4), r(1), -OFS_END + mr r(6), r(1) + streg r(0), LR_SAVE(r(1)) + stregu r(1), -FRAME(r(1)) + cfi_def_cfa_offset(FRAME) + cfi_offset(65, LR_SAVE) + streg r(6), OFS_CFA(r(4)) + streg r(0), OFS_LR(r(4)) +#ifdef _CALL_DARWIN + streg r(13), OFS_TOC(r(4)) +#else + streg r(2), OFS_TOC(r(4)) +#endif + streg r(5), OFS_CR(r(4)) + streg r(14), 0*WS+OFS_GR(r(4)) + streg r(15), 1*WS+OFS_GR(r(4)) + streg r(16), 2*WS+OFS_GR(r(4)) + streg r(17), 3*WS+OFS_GR(r(4)) + streg r(18), 4*WS+OFS_GR(r(4)) + streg r(19), 5*WS+OFS_GR(r(4)) + streg r(20), 6*WS+OFS_GR(r(4)) + streg r(21), 7*WS+OFS_GR(r(4)) + streg r(22), 8*WS+OFS_GR(r(4)) + streg r(23), 9*WS+OFS_GR(r(4)) + streg r(24), 10*WS+OFS_GR(r(4)) + streg r(25), 11*WS+OFS_GR(r(4)) + streg r(26), 12*WS+OFS_GR(r(4)) + streg r(27), 13*WS+OFS_GR(r(4)) + streg r(28), 14*WS+OFS_GR(r(4)) + streg r(29), 15*WS+OFS_GR(r(4)) + streg r(30), 16*WS+OFS_GR(r(4)) + streg r(31), 17*WS+OFS_GR(r(4)) + +#ifndef _SOFT_FLOAT + /* ??? Determine when FPRs not present. */ + /* ??? Test r(3) for pr_hasNoFloatUpdate and skip the fp save. + This is not yet set by the compiler. */ + mffs f(0) + stfd f(14), 0+OFS_FR(r(4)) + stfd f(15), 8+OFS_FR(r(4)) + stfd f(16), 16+OFS_FR(r(4)) + stfd f(17), 24+OFS_FR(r(4)) + stfd f(18), 32+OFS_FR(r(4)) + stfd f(19), 40+OFS_FR(r(4)) + stfd f(20), 48+OFS_FR(r(4)) + stfd f(21), 56+OFS_FR(r(4)) + stfd f(22), 64+OFS_FR(r(4)) + stfd f(23), 72+OFS_FR(r(4)) + stfd f(24), 80+OFS_FR(r(4)) + stfd f(25), 88+OFS_FR(r(4)) + stfd f(26), 96+OFS_FR(r(4)) + stfd f(27),104+OFS_FR(r(4)) + stfd f(28),112+OFS_FR(r(4)) + stfd f(29),120+OFS_FR(r(4)) + stfd f(30),128+OFS_FR(r(4)) + stfd f(31),136+OFS_FR(r(4)) + stfd f(0), OFS_FPSCR(r(4)) +#endif + +#if defined(__ALTIVEC__) + /* ??? Determine when VRs not present. */ + /* ??? Test r(3) for pr_hasNoVectorUpdate and skip the vr save. + This is not yet set by the compiler. */ + addi r(5), r(4), OFS_VR + addi r(6), r(4), OFS_VR+16 + mfspr r(0), VRSAVE + stvx v(20), 0, r(5) + addi r(5), r(5), 32 + stvx v(21), 0, r(6) + addi r(6), r(6), 32 + stvx v(22), 0, r(5) + addi r(5), r(5), 32 + stvx v(23), 0, r(6) + addi r(6), r(6), 32 + stvx v(25), 0, r(5) + addi r(5), r(5), 32 + stvx v(26), 0, r(6) + addi r(6), r(6), 32 + stvx v(26), 0, r(5) + addi r(5), r(5), 32 + stvx v(27), 0, r(6) + addi r(6), r(6), 32 + stvx v(28), 0, r(5) + addi r(5), r(5), 32 + stvx v(29), 0, r(6) + addi r(6), r(6), 32 + stvx v(30), 0, r(5) + stvx v(31), 0, r(6) + streg r(0), OFS_VSCR(r(4)) +#endif + + CALL GTM_begin_transaction + + ldreg r(0), LR_SAVE+FRAME(r(1)) + mtlr r(0) + addi r(1), r(1), FRAME + cfi_def_cfa_offset(0) + cfi_restore(65) + blr + cfi_endproc +END _ITM_beginTransaction + + .align 4 + HIDDEN GTM_longjmp +FUNC GTM_longjmp + cfi_startproc +#if defined(__ALTIVEC__) || defined(__VSX__) + /* ??? Determine when VRs not present. */ + /* ??? Test r(5) for pr_hasNoVectorUpdate and skip the vr restore. + This is not yet set by the compiler. */ + addi r(6), r(4), OFS_VR + addi r(7), r(4), OFS_VR+16 + ldreg r(0), OFS_VSCR(r(4)) + cfi_undefined(v(20)) + cfi_undefined(v(21)) + cfi_undefined(v(22)) + cfi_undefined(v(23)) + cfi_undefined(v(24)) + cfi_undefined(v(25)) + cfi_undefined(v(26)) + cfi_undefined(v(27)) + cfi_undefined(v(28)) + cfi_undefined(v(29)) + cfi_undefined(v(30)) + cfi_undefined(v(31)) + lvx v(20), 0, r(6) + addi r(6), r(6), 32 + lvx v(21), 0, r(7) + addi r(7), r(7), 32 + lvx v(22), 0, r(6) + addi r(6), r(6), 32 + lvx v(23), 0, r(7) + addi r(7), r(7), 32 + lvx v(24), 0, r(6) + addi r(6), r(6), 32 + lvx v(25), 0, r(7) + addi r(7), r(7), 32 + lvx v(26), 0, r(6) + addi r(6), r(6), 32 + lvx v(27), 0, r(7) + addi r(7), r(7), 32 + lvx v(28), 0, r(6) + addi r(6), r(6), 32 + lvx v(29), 0, r(7) + addi r(7), r(7), 32 + lvx v(30), 0, r(6) + lvx v(31), 0, r(7) + mtspr VRSAVE, r(0) +#endif + +#ifndef _SOFT_FLOAT + /* ??? Determine when FPRs not present. */ + /* ??? Test r(5) for pr_hasNoFloatUpdate and skip the fp load. + This is not yet set by the compiler. */ + lfd f(0), OFS_FPSCR(r(4)) + cfi_undefined(f(14)) + cfi_undefined(f(15)) + cfi_undefined(f(16)) + cfi_undefined(f(17)) + cfi_undefined(f(18)) + cfi_undefined(f(19)) + cfi_undefined(f(20)) + cfi_undefined(f(21)) + cfi_undefined(f(22)) + cfi_undefined(f(23)) + cfi_undefined(f(24)) + cfi_undefined(f(25)) + cfi_undefined(f(26)) + cfi_undefined(f(27)) + cfi_undefined(f(28)) + cfi_undefined(f(29)) + cfi_undefined(f(30)) + cfi_undefined(f(31)) + lfd f(14), 0+OFS_FR(r(4)) + lfd f(15), 8+OFS_FR(r(4)) + lfd f(16), 16+OFS_FR(r(4)) + lfd f(17), 24+OFS_FR(r(4)) + lfd f(18), 32+OFS_FR(r(4)) + lfd f(19), 40+OFS_FR(r(4)) + lfd f(20), 48+OFS_FR(r(4)) + lfd f(21), 56+OFS_FR(r(4)) + lfd f(22), 64+OFS_FR(r(4)) + lfd f(23), 72+OFS_FR(r(4)) + lfd f(24), 80+OFS_FR(r(4)) + lfd f(25), 88+OFS_FR(r(4)) + lfd f(26), 96+OFS_FR(r(4)) + lfd f(27),104+OFS_FR(r(4)) + lfd f(28),112+OFS_FR(r(4)) + lfd f(29),120+OFS_FR(r(4)) + lfd f(30),128+OFS_FR(r(4)) + lfd f(31),136+OFS_FR(r(4)) + mtfsf 0xff, f(0) +#endif + + ldreg r(6), OFS_CFA(r(4)) + ldreg r(0), OFS_LR(r(4)) +#ifdef _CALL_DARWIN + ldreg r(13), OFS_TOC(r(4)) +#else + ldreg r(2), OFS_TOC(r(4)) +#endif + ldreg r(7), OFS_CR(r(4)) + /* At the instant we restore the LR, the only coherent view of + the world we have is into the new stack frame. Define the + CFA in terms of the not-yet-restored stack pointer. This will + last until the end of the function. */ + mtlr r(0) + cfi_def_cfa(r(6), 0) + cfi_undefined(r(14)) + cfi_undefined(r(15)) + cfi_undefined(r(16)) + cfi_undefined(r(17)) + cfi_undefined(r(18)) + cfi_undefined(r(19)) + cfi_undefined(r(20)) + cfi_undefined(r(21)) + cfi_undefined(r(22)) + cfi_undefined(r(23)) + cfi_undefined(r(24)) + cfi_undefined(r(25)) + cfi_undefined(r(26)) + cfi_undefined(r(27)) + cfi_undefined(r(28)) + cfi_undefined(r(29)) + cfi_undefined(r(30)) + cfi_undefined(r(31)) + mtcr r(7) + ldreg r(14), 0*WS+OFS_GR(r(4)) + ldreg r(15), 1*WS+OFS_GR(r(4)) + ldreg r(16), 2*WS+OFS_GR(r(4)) + ldreg r(17), 3*WS+OFS_GR(r(4)) + ldreg r(18), 4*WS+OFS_GR(r(4)) + ldreg r(19), 5*WS+OFS_GR(r(4)) + ldreg r(20), 6*WS+OFS_GR(r(4)) + ldreg r(21), 7*WS+OFS_GR(r(4)) + ldreg r(22), 8*WS+OFS_GR(r(4)) + ldreg r(23), 9*WS+OFS_GR(r(4)) + ldreg r(24), 10*WS+OFS_GR(r(4)) + ldreg r(25), 11*WS+OFS_GR(r(4)) + ldreg r(26), 12*WS+OFS_GR(r(4)) + ldreg r(27), 13*WS+OFS_GR(r(4)) + ldreg r(28), 14*WS+OFS_GR(r(4)) + ldreg r(29), 15*WS+OFS_GR(r(4)) + ldreg r(30), 16*WS+OFS_GR(r(4)) + ldreg r(31), 17*WS+OFS_GR(r(4)) + mr r(1), r(6) + blr + cfi_endproc +END GTM_longjmp + +#ifdef __linux__ +.section .note.GNU-stack, "", @progbits +#endif diff --git a/gcc-4.8.3/libitm/config/powerpc/target.h b/gcc-4.8.3/libitm/config/powerpc/target.h new file mode 100644 index 000000000..cf01a5724 --- /dev/null +++ b/gcc-4.8.3/libitm/config/powerpc/target.h @@ -0,0 +1,140 @@ +/* Copyright (C) 2012-2013 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 HAVE_SYS_AUXV_H +#include <sys/auxv.h> +#endif + +namespace GTM HIDDEN { + +typedef int v128 __attribute__((vector_size(16), may_alias, aligned(16))); +typedef struct gtm_jmpbuf +{ +#if defined(__ALTIVEC__) || defined(__VSX__) + v128 vr[12]; /* vr20-vr31 */ + unsigned long long vscr; /* long long for padding only */ +#endif +#ifndef _SOFT_FLOAT + double fr[18]; /* f14-f31 */ + double fpscr; +#endif + unsigned long gr[18]; /* r14-r31 */ + void *cfa; + unsigned long pc; + unsigned long toc; /* r2 on aix, r13 on darwin */ + unsigned long cr; +} gtm_jmpbuf; + +/* The size of one line in hardware caches (in bytes). */ +#if defined (__powerpc64__) || defined (__ppc64__) +# define HW_CACHELINE_SIZE 128 +#else +# define HW_CACHELINE_SIZE 32 +#endif + +static inline void +cpu_relax (void) +{ + __asm volatile ("" : : : "memory"); +} + +// Use HTM if it is supported by the system. +// See gtm_thread::begin_transaction for how these functions are used. +#if defined (__linux__) \ + && defined (HAVE_AS_HTM) \ + && defined (HAVE_GETAUXVAL) \ + && defined (AT_HWCAP2) \ + && defined (PPC_FEATURE2_HAS_HTM) + +#include <htmintrin.h> + +#define USE_HTM_FASTPATH + +#define _TBEGIN_STARTED 0 +#define _TBEGIN_INDETERMINATE 1 +#define _TBEGIN_PERSISTENT 2 + +/* Number of retries for transient failures. */ +#define _HTM_RETRIES 10 + +static inline bool +htm_available (void) +{ + return (getauxval (AT_HWCAP2) & PPC_FEATURE2_HAS_HTM) ? true : false; +} + +static inline uint32_t +htm_init (void) +{ + // Maximum number of times we try to execute a transaction + // as a HW transaction. + return htm_available () ? _HTM_RETRIES : 0; +} + +static inline uint32_t +htm_begin (void) +{ + if (__builtin_expect (__builtin_tbegin (0), 1)) + return _TBEGIN_STARTED; + + if (_TEXASRU_FAILURE_PERSISTENT (__builtin_get_texasru ())) + return _TBEGIN_PERSISTENT; + + return _TBEGIN_INDETERMINATE; +} + +static inline bool +htm_begin_success (uint32_t begin_ret) +{ + return begin_ret == _TBEGIN_STARTED; +} + +static inline void +htm_commit (void) +{ + __builtin_tend (0); +} + +static inline void +htm_abort (void) +{ + __builtin_tabort (0); +} + +static inline bool +htm_abort_should_retry (uint32_t begin_ret) +{ + return begin_ret != _TBEGIN_PERSISTENT; +} + +/* Returns true iff a hardware transaction is currently being executed. */ +static inline bool +htm_transaction_active (void) +{ + return (_HTM_STATE (__builtin_ttest ()) == _HTM_TRANSACTIONAL); +} + +#endif + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/s390/sjlj.S b/gcc-4.8.3/libitm/config/s390/sjlj.S new file mode 100644 index 000000000..592d9af2c --- /dev/null +++ b/gcc-4.8.3/libitm/config/s390/sjlj.S @@ -0,0 +1,108 @@ +/* Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Andreas Krebbel <krebbel@linux.vnet.ibm.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 "asmcfi.h" + +.text + .align 4 +.globl _ITM_beginTransaction + .type _ITM_beginTransaction, @function + + /* _ITM_beginTransaction (int props); props -> r2 */ +_ITM_beginTransaction: + cfi_startproc +#ifdef __s390x__ + lgr %r3,%r15 /* backup stack pointer */ + aghi %r15,-304 /* jump buffer (144) + reg save area (160) */ + cfi_adjust_cfa_offset(304) + stmg %r6,%r14,160(%r15) + stg %r3,72+160(%r15) /* store the old stack pointer */ + std %f8,80+160(%r15) + std %f9,88+160(%r15) + std %f10,96+160(%r15) + std %f11,104+160(%r15) + std %f12,112+160(%r15) + std %f13,120+160(%r15) + std %f14,128+160(%r15) + std %f15,136+160(%r15) + la %r3,160(%r15) /* second argument to GTM_begin_transaction */ + brasl %r14,GTM_begin_transaction + lg %r1,64+160(%r15) + aghi %r15,304 + cfi_adjust_cfa_offset(-304) + br %r1 +#else + lr %r3,%r15 /* backup stack pointer */ + ahi %r15,-152 /* jump buffer (56) + reg save area (96) */ + cfi_adjust_cfa_offset(152) + stm %r6,%r14,96(%r15) + st %r3,36+96(%r15) /* store the old stack pointer */ + std %f4,40+96(%r15) + std %f6,48+96(%r15) + la %r3,96(%r15) /* second argument to GTM_begin_transaction */ + /* begin_transaction (uint32_t prop, const gtm_jmpbuf *jb) */ + brasl %r14,GTM_begin_transaction /* requires mzarch */ + l %r1,32+96(%r15) + ahi %r15,152 + cfi_adjust_cfa_offset(-152) + br %r1 +#endif + cfi_endproc + + .size _ITM_beginTransaction, .-_ITM_beginTransaction + + .align 4 +.globl GTM_longjmp + .type GTM_longjmp, @function + .hidden GTM_longjmp + + /* uint32_t GTM_longjmp (uint32_t, const gtm_jmpbuf *, uint32_t) */ +GTM_longjmp: + /* First parameter becomes the return value of + _ITM_beginTransaction (r2). + Third parameter is ignored for now. */ + cfi_startproc +#ifdef __s390x__ + ld %f8,80(%r3) + ld %f9,88(%r3) + ld %f10,96(%r3) + ld %f11,104(%r3) + ld %f12,112(%r3) + ld %f13,120(%r3) + ld %f14,128(%r3) + ld %f15,136(%r3) + lmg %r6,%r15,0(%r3) + br %r14 +#else + ld %f4,40(%r3) + ld %f6,48(%r3) + lm %r6,%r15,0(%r3) + br %r14 +#endif + cfi_endproc + + .size GTM_longjmp, .-GTM_longjmp + + .section .note.GNU-stack, "", @progbits diff --git a/gcc-4.8.3/libitm/config/s390/target.h b/gcc-4.8.3/libitm/config/s390/target.h new file mode 100644 index 000000000..cec49cf77 --- /dev/null +++ b/gcc-4.8.3/libitm/config/s390/target.h @@ -0,0 +1,127 @@ +/* Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Andreas Krebbel <krebbel@linux.vnet.ibm.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 HAVE_SYS_AUXV_H +#include <sys/auxv.h> +#endif + +namespace GTM HIDDEN { + +#define HW_CACHELINE_SIZE 256 + +typedef struct gtm_jmpbuf +{ + /* We save registers r6-r14. */ + long int __gregs[9]; + /* r15 is stored into cfa field. It needs to be named that way + since tls.h is accessing the field by name. Be aware that this + is not actually what we consider the CFA on s390 (since there is + a fix offset between sp and CFA). It is merely the saved stack + pointer. */ + void *cfa; + +#ifdef __s390x__ + /* We save fpu registers f8 - f15. */ + long __fpregs[8]; +#else + /* We save fpu registers f4 and f6. */ + long __fpregs[4]; +#endif +} gtm_jmpbuf; + +static inline void +cpu_relax (void) +{ + __asm volatile ("" : : : "memory"); +} + + +// Use HTM if it is supported by the system. +// See gtm_thread::begin_transaction for how these functions are used. +#if defined (__linux__) \ + && defined (HAVE_AS_HTM) \ + && defined (HAVE_GETAUXVAL) \ + && defined (HWCAP_S390_TE) + +#include <htmintrin.h> + +/* Number of retries for transient failures. */ +#define _HTM_ITM_RETRIES 10 +#define USE_HTM_FASTPATH + +static inline bool +htm_available () +{ + return (getauxval (AT_HWCAP) & HWCAP_S390_TE) ? true : false; +} + +static inline uint32_t +htm_init () +{ + return htm_available () ? _HTM_ITM_RETRIES : 0; +} + +static inline uint32_t +htm_begin () +{ + __asm volatile (".machine \"all\" \n\t"); + return __builtin_tbegin_nofloat (NULL); +} + +static inline bool +htm_begin_success (uint32_t begin_ret) +{ + return begin_ret == _HTM_TBEGIN_STARTED; +} + +static inline void +htm_commit () +{ + __asm volatile (".machine \"all\" \n\t"); + __builtin_tend (); +} + +static inline void +htm_abort () +{ + __asm volatile (".machine \"all\" \n\t"); + __builtin_tabort (_HTM_FIRST_USER_ABORT_CODE); +} + +static inline bool +htm_abort_should_retry (uint32_t begin_ret) +{ + return begin_ret == _HTM_TBEGIN_TRANSIENT; +} + +static inline bool +htm_transaction_active () +{ + __asm volatile (".machine \"all\" \n\t"); + return __builtin_tx_nesting_depth() != 0; +} + +#endif + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/sh/sjlj.S b/gcc-4.8.3/libitm/config/sh/sjlj.S new file mode 100644 index 000000000..bed543de9 --- /dev/null +++ b/gcc-4.8.3/libitm/config/sh/sjlj.S @@ -0,0 +1,122 @@ +/* Copyright (C) 2011-2013 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 "asmcfi.h" + + .text + .align 2 + .global _ITM_beginTransaction + .type _ITM_beginTransaction, %function + +_ITM_beginTransaction: + cfi_startproc + mov r15, r1 +#ifdef __SH_FPU_ANY__ + fmov.s fr15, @-r15 + fmov.s fr14, @-r15 + fmov.s fr13, @-r15 + fmov.s fr12, @-r15 + sts.l fpscr, @-r15 +#endif /* __SH_FPU_ANY__ */ + stc.l gbr, @-r15 + sts.l pr, @-r15 + mov.l r1, @-r15 + mov.l r14, @-r15 + mov.l r13, @-r15 + mov.l r12, @-r15 + mov.l r11, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 +#ifdef __SH_FPU_ANY__ + cfi_def_cfa_offset (4*15) +#else + cfi_def_cfa_offset (4*10) +#endif +#if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__ + mov.l .Lbegin, r1 + jsr @r1 + mov r15, r5 +#else + mova .Lgot, r0 + mov.l .Lgot, r12 + add r0, r12 + mov.l .Lbegin, r1 + bsrf r1 + mov r15, r5 +.Lbegin0: + mov.l @(4*4,r15), r12 +#endif + mov.l @(8*4,r15), r1 + lds r1, pr +#ifdef __SH_FPU_ANY__ + add #(15*4), r15 +#else + add #(10*5), r15 +#endif + cfi_def_cfa_offset (0) + rts + nop + cfi_endproc + + .align 2 +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +.Lbegin: +#if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__ + .long GTM_begin_transaction +#else + .long GTM_begin_transaction@PLT-(.Lbegin0-.) +#endif + .size _ITM_beginTransaction, . - _ITM_beginTransaction + + .global GTM_longjmp + .hidden GTM_longjmp + .type GTM_longjmp, %function + +GTM_longjmp: + mov.l @r5+, r8 + mov.l @r5+, r9 + mov.l @r5+, r10 + mov.l @r5+, r11 + mov.l @r5+, r12 + mov.l @r5+, r13 + mov.l @r5+, r14 + mov.l @r5+, r15 + lds.l @r5+, pr + ldc.l @r5+, gbr +#ifdef __SH_FPU_ANY__ + lds.l @r5+, fpscr + fmov.s @r5+, fr12 + fmov.s @r5+, fr13 + fmov.s @r5+, fr14 + fmov.s @r5+, fr15 +#endif + rts + mov r4, r0 + + .size GTM_longjmp, . - GTM_longjmp + +#ifdef __linux__ +.section .note.GNU-stack, "", %progbits +#endif diff --git a/gcc-4.8.3/libitm/config/sh/target.h b/gcc-4.8.3/libitm/config/sh/target.h new file mode 100644 index 000000000..c1d94c72b --- /dev/null +++ b/gcc-4.8.3/libitm/config/sh/target.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2011-2013 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/>. */ + +namespace GTM HIDDEN { + +typedef struct gtm_jmpbuf +{ + unsigned long s[7]; /* r8-r14 */ + void *cfa; + unsigned long pc; + unsigned long gbr; +#ifdef __SH_FPU_ANY__ + unsigned long fpscr; + unsigned long f[4]; /* fr12-fr15 */ +#endif +} gtm_jmpbuf; + +/* SH generally uses a fixed page size of 4K. */ +#define PAGE_SIZE 4096 +#define FIXED_PAGE_SIZE 1 + +/* ??? The size of one line in hardware caches (in bytes). */ +#define HW_CACHELINE_SIZE 32 + +static inline void +cpu_relax (void) +{ + __asm volatile ("" : : : "memory"); +} + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/sparc/cacheline.h b/gcc-4.8.3/libitm/config/sparc/cacheline.h new file mode 100644 index 000000000..1b135b1c9 --- /dev/null +++ b/gcc-4.8.3/libitm/config/sparc/cacheline.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2012-2013 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/>. */ + +#ifndef LIBITM_SPARC_CACHELINE_H +#define LIBITM_SPARC_CACHELINE_H 1 + +// A cacheline is the smallest unit with which locks are associated. +// The current implementation of the _ITM_[RW] barriers assumes that +// all data types can fit (aligned) within a cachline, which means +// in practice sizeof(complex long double) is the smallest cacheline size. +// It ought to be small enough for efficient manipulation of the +// modification mask, below. +#ifdef __arch64__ +# define CACHELINE_SIZE 64 +#else +# define CACHELINE_SIZE 32 +#endif + +#include "config/generic/cacheline.h" + +#endif // LIBITM_SPARC_CACHELINE_H diff --git a/gcc-4.8.3/libitm/config/sparc/sjlj.S b/gcc-4.8.3/libitm/config/sparc/sjlj.S new file mode 100644 index 000000000..cd6461a08 --- /dev/null +++ b/gcc-4.8.3/libitm/config/sparc/sjlj.S @@ -0,0 +1,97 @@ +/* Copyright (C) 2012-2013 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 "asmcfi.h" + +#ifdef __arch64__ +# define WORD_SIZE 8 +# define MIN_FRAME_SIZE 176 +# define STACK_BIAS 2047 +# define load ldx +# define store stx +#else +# define WORD_SIZE 4 +# define MIN_FRAME_SIZE 96 +# define STACK_BIAS 0 +# define load ld +# define store st +#endif + +/* Fields of the JmpBuf structure. */ +#define JB_CFA 0 +#define JB_PC 1 +#define OFFSET(FIELD) ((FIELD) * WORD_SIZE) + +/* The frame size must be a multiple of the double-word size. */ +#define FRAME_SIZE (MIN_FRAME_SIZE + 2 * WORD_SIZE) +#define JB_OFFSET (STACK_BIAS + MIN_FRAME_SIZE) + + .text + .align 4 + .globl _ITM_beginTransaction + .type _ITM_beginTransaction, #function + .proc 016 +_ITM_beginTransaction: + cfi_startproc + add %sp, STACK_BIAS, %g1 + sub %sp, FRAME_SIZE, %sp + cfi_def_cfa_offset(STACK_BIAS + FRAME_SIZE) + store %g1, [%sp + JB_OFFSET + OFFSET (JB_CFA)] + store %o7, [%sp + JB_OFFSET + OFFSET (JB_PC)] + /* ??? This triggers an internal error in GDB. */ + cfi_offset(%o7, -WORD_SIZE) + call GTM_begin_transaction + add %sp, JB_OFFSET, %o1 + load [%sp + JB_OFFSET + OFFSET (JB_PC)], %o7 + jmp %o7+8 + add %sp, FRAME_SIZE, %sp + cfi_def_cfa_offset(STACK_BIAS) + cfi_endproc + .size _ITM_beginTransaction, . - _ITM_beginTransaction + + .align 4 + .globl GTM_longjmp +#ifdef HAVE_ATTRIBUTE_VISIBILITY + .hidden GTM_longjmp +#endif + .type GTM_longjmp, #function + .proc 016 +GTM_longjmp: + cfi_startproc + flushw +#if STACK_BIAS + load [%o1 + OFFSET (JB_CFA)], %g1 + sub %g1, STACK_BIAS, %fp +#else + load [%o1 + OFFSET (JB_CFA)], %fp +#endif + cfi_def_cfa(%fp, STACK_BIAS) + load [%o1 + OFFSET (JB_PC)], %o7 + jmp %o7+8 + restore %g0, %o0, %o0 + cfi_endproc + .size GTM_longjmp, . - GTM_longjmp + +#ifdef __linux__ + .section .note.GNU-stack, "", @progbits +#endif diff --git a/gcc-4.8.3/libitm/config/sparc/target.h b/gcc-4.8.3/libitm/config/sparc/target.h new file mode 100644 index 000000000..c3853fe82 --- /dev/null +++ b/gcc-4.8.3/libitm/config/sparc/target.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2012-2013 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/>. */ + +namespace GTM HIDDEN { + +typedef struct gtm_jmpbuf +{ + void *cfa; + unsigned long pc; +} gtm_jmpbuf; + +/* UltraSPARC processors generally use a fixed page size of 8K. */ +#define PAGE_SIZE 8192 +#define FIXED_PAGE_SIZE 1 + +/* The size of one line in hardware caches (in bytes). We use the primary + cache line size documented for the UltraSPARC T1/T2. */ +#define HW_CACHELINE_SIZE 16 + +static inline void +cpu_relax (void) +{ + __asm volatile ("rd %%ccr, %%g0" : : : "memory"); +} + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/x86/cacheline.h b/gcc-4.8.3/libitm/config/x86/cacheline.h new file mode 100644 index 000000000..ae8b0bb1f --- /dev/null +++ b/gcc-4.8.3/libitm/config/x86/cacheline.h @@ -0,0 +1,125 @@ +/* Copyright (C) 2009-2013 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_CACHELINE_H +#define LIBITM_CACHELINE_H 1 + +// Minimum cacheline size is 32, due to both complex long double and __m256. +// There's no requirement that 64-bit use a 64-byte cacheline size, but do +// so for now to make sure everything is parameterized properly. +#ifdef __x86_64__ +# define CACHELINE_SIZE 64 +#else +# define CACHELINE_SIZE 32 +#endif + +namespace GTM HIDDEN { + +// A gtm_cacheline_mask stores a modified bit for every modified byte +// in the cacheline with which it is associated. +typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask; + +union gtm_cacheline +{ + // Byte access to the cacheline. + unsigned char b[CACHELINE_SIZE] __attribute__((aligned(CACHELINE_SIZE))); + + // Larger sized access to the cacheline. + uint16_t u16[CACHELINE_SIZE / sizeof(uint16_t)]; + uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)]; + uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)]; + gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)]; + +#ifdef __MMX__ + __m64 m64[CACHELINE_SIZE / sizeof(__m64)]; +#endif +#ifdef __SSE__ + __m128 m128[CACHELINE_SIZE / sizeof(__m128)]; +#endif +#ifdef __SSE2__ + __m128i m128i[CACHELINE_SIZE / sizeof(__m128i)]; +#endif +#ifdef __AVX__ + __m256 m256[CACHELINE_SIZE / sizeof(__m256)]; + __m256i m256i[CACHELINE_SIZE / sizeof(__m256i)]; +#endif + +#if defined(__SSE__) || defined(__AVX__) + // Copy S to D; only bother defining if we can do this more efficiently + // than the compiler-generated default implementation. + gtm_cacheline& operator= (const gtm_cacheline &s); +#endif // SSE, AVX +}; + +#if defined(__SSE__) || defined(__AVX__) +inline gtm_cacheline& ALWAYS_INLINE +gtm_cacheline::operator= (const gtm_cacheline & __restrict s) +{ +#ifdef __AVX__ +# define CP m256 +# define TYPE __m256 +#else +# define CP m128 +# define TYPE __m128 +#endif + + TYPE w, x, y, z; + + // ??? Wouldn't it be nice to have a pragma to tell the compiler + // to completely unroll a given loop? + switch (CACHELINE_SIZE / sizeof(TYPE)) + { + case 1: + this->CP[0] = s.CP[0]; + break; + case 2: + x = s.CP[0]; + y = s.CP[1]; + this->CP[0] = x; + this->CP[1] = y; + break; + case 4: + w = s.CP[0]; + x = s.CP[1]; + y = s.CP[2]; + z = s.CP[3]; + this->CP[0] = w; + this->CP[1] = x; + this->CP[2] = y; + this->CP[3] = z; + break; + default: + __builtin_trap (); + } + + return *this; + +#undef CP +#undef TYPE +} +#endif + +} // namespace GTM + +#endif // LIBITM_CACHELINE_H diff --git a/gcc-4.8.3/libitm/config/x86/sjlj.S b/gcc-4.8.3/libitm/config/x86/sjlj.S new file mode 100644 index 000000000..993f69865 --- /dev/null +++ b/gcc-4.8.3/libitm/config/x86/sjlj.S @@ -0,0 +1,147 @@ +/* Copyright (C) 2008-2013 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 "asmcfi.h" + +#define CONCAT1(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +#ifdef __USER_LABEL_PREFIX__ +# define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) +#else +# define SYM(x) x +#endif + +#ifdef __ELF__ +# define TYPE(x) .type SYM(x), @function +# define SIZE(x) .size SYM(x), . - SYM(x) +# ifdef HAVE_ATTRIBUTE_VISIBILITY +# define HIDDEN(x) .hidden SYM(x) +# else +# define HIDDEN(x) +# endif +#else +# define TYPE(x) +# define SIZE(x) +# ifdef __MACH__ +# define HIDDEN(x) .private_extern SYM(x) +# else +# define HIDDEN(x) +# endif +#endif + + .text + + .align 4 + .globl SYM(_ITM_beginTransaction) + +SYM(_ITM_beginTransaction): + cfi_startproc +#ifdef __x86_64__ + leaq 8(%rsp), %rax + subq $56, %rsp + cfi_def_cfa_offset(64) + movq %rax, (%rsp) + movq %rbx, 8(%rsp) + movq %rbp, 16(%rsp) + movq %r12, 24(%rsp) + movq %r13, 32(%rsp) + movq %r14, 40(%rsp) + movq %r15, 48(%rsp) + movq %rsp, %rsi + call SYM(GTM_begin_transaction) + addq $56, %rsp + cfi_def_cfa_offset(8) +#else + leal 4(%esp), %ecx + movl 4(%esp), %eax + subl $28, %esp + cfi_def_cfa_offset(32) + movl %ecx, 8(%esp) + movl %ebx, 12(%esp) + movl %esi, 16(%esp) + movl %edi, 20(%esp) + movl %ebp, 24(%esp) + leal 8(%esp), %edx +#if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__ + call SYM(GTM_begin_transaction) +#elif defined __ELF__ + call 1f +1: popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx + call SYM(GTM_begin_transaction)@PLT + movl 12(%esp), %ebx +#else +# error "Unsupported PIC sequence" +#endif + addl $28, %esp + cfi_def_cfa_offset(4) +#endif + ret + cfi_endproc + + TYPE(_ITM_beginTransaction) + SIZE(_ITM_beginTransaction) + + .align 4 + .globl SYM(GTM_longjmp) + +SYM(GTM_longjmp): + cfi_startproc +#ifdef __x86_64__ + movq (%rsi), %rcx + movq 8(%rsi), %rbx + movq 16(%rsi), %rbp + movq 24(%rsi), %r12 + movq 32(%rsi), %r13 + movq 40(%rsi), %r14 + movq 48(%rsi), %r15 + movl %edi, %eax + cfi_def_cfa(%rsi, 0) + cfi_offset(%rip, 56) + cfi_register(%rsp, %rcx) + movq %rcx, %rsp + jmp *56(%rsi) +#else + movl (%edx), %ecx + movl 4(%edx), %ebx + movl 8(%edx), %esi + movl 12(%edx), %edi + movl 16(%edx), %ebp + cfi_def_cfa(%edx, 0) + cfi_offset(%eip, 20) + cfi_register(%esp, %ecx) + movl %ecx, %esp + jmp *20(%edx) +#endif + cfi_endproc + + TYPE(GTM_longjmp) + HIDDEN(GTM_longjmp) + SIZE(GTM_longjmp) + +#ifdef __linux__ +.section .note.GNU-stack, "", @progbits +#endif diff --git a/gcc-4.8.3/libitm/config/x86/target.h b/gcc-4.8.3/libitm/config/x86/target.h new file mode 100644 index 000000000..063c09ed9 --- /dev/null +++ b/gcc-4.8.3/libitm/config/x86/target.h @@ -0,0 +1,138 @@ +/* Copyright (C) 2008-2013 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/>. */ + +// We'll be using some of the cpu builtins, and their associated types. +#include <x86intrin.h> +#include <cpuid.h> + +namespace GTM HIDDEN { + +/* ??? This doesn't work for Win64. */ +typedef struct gtm_jmpbuf +{ + void *cfa; +#ifdef __x86_64__ + unsigned long long rbx; + unsigned long long rbp; + unsigned long long r12; + unsigned long long r13; + unsigned long long r14; + unsigned long long r15; + unsigned long long rip; +#else + unsigned long ebx; + unsigned long esi; + unsigned long edi; + unsigned long ebp; + unsigned long eip; +#endif +} gtm_jmpbuf; + +/* x86 doesn't require strict alignment for the basic types. */ +#define STRICT_ALIGNMENT 0 + +/* x86 uses a fixed page size of 4K. */ +#define PAGE_SIZE 4096 +#define FIXED_PAGE_SIZE 1 + +/* The size of one line in hardware caches (in bytes). */ +#define HW_CACHELINE_SIZE 64 + + +static inline void +cpu_relax (void) +{ + __builtin_ia32_pause (); +} + +// Use Intel RTM if supported by the assembler. +// See gtm_thread::begin_transaction for how these functions are used. +#ifdef HAVE_AS_RTM +#define USE_HTM_FASTPATH + +static inline bool +htm_available () +{ + const unsigned cpuid_rtm = bit_RTM; + if (__get_cpuid_max (0, NULL) >= 7) + { + unsigned a, b, c, d; + __cpuid_count (7, 0, a, b, c, d); + if (b & cpuid_rtm) + return true; + } + return false; +} + +static inline uint32_t +htm_init () +{ + // Maximum number of times we try to execute a transaction as a HW + // transaction. + // ??? Why 2? Any offline or runtime tuning necessary? + return htm_available () ? 2 : 0; +} + +static inline uint32_t +htm_begin () +{ + return _xbegin(); +} + +static inline bool +htm_begin_success (uint32_t begin_ret) +{ + return begin_ret == _XBEGIN_STARTED; +} + +static inline void +htm_commit () +{ + _xend(); +} + +static inline void +htm_abort () +{ + // ??? According to a yet unpublished ABI rule, 0xff is reserved and + // supposed to signal a busy lock. Source: andi.kleen@intel.com + _xabort(0xff); +} + +static inline bool +htm_abort_should_retry (uint32_t begin_ret) +{ + return begin_ret & _XABORT_RETRY; +} + +/* Returns true iff a hardware transaction is currently being executed. */ +static inline bool +htm_transaction_active () +{ + return _xtest() != 0; +} +#endif + + +} // namespace GTM diff --git a/gcc-4.8.3/libitm/config/x86/x86_avx.cc b/gcc-4.8.3/libitm/config/x86/x86_avx.cc new file mode 100644 index 000000000..42a32fd1f --- /dev/null +++ b/gcc-4.8.3/libitm/config/x86/x86_avx.cc @@ -0,0 +1,91 @@ +/* Copyright (C) 2009-2013 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 "config.h" + +#include "libitm_i.h" +#include "dispatch.h" + +extern "C" { + +#ifndef HAVE_AS_AVX +// If we don't have an AVX capable assembler, we didn't set -mavx on the +// command-line either, which means that libitm.h defined neither this type +// nor the functions in this file. Define the type and unconditionally +// wrap the file in extern "C" to make up for the lack of pre-declaration. +typedef float _ITM_TYPE_M256 __attribute__((vector_size(32), may_alias)); +#endif + +// Re-define the memcpy implementations so that we can frob the +// interface to deal with possibly missing AVX instruction set support. + +#ifdef HAVE_AS_AVX +#define RETURN(X) return X +#define STORE(X,Y) X = Y +#define OUTPUT(T) _ITM_TYPE_##T +#define INPUT(T,X) , _ITM_TYPE_##T X +#else +/* Emit vmovaps (%rax),%ymm0. */ +#define RETURN(X) \ + asm volatile(".byte 0xc5,0xfc,0x28,0x00" : "=m"(X) : "a"(&X)) +/* Emit vmovaps %ymm0,(%rax); vzeroupper. */ +#define STORE(X,Y) \ + asm volatile(".byte 0xc5,0xfc,0x29,0x00,0xc5,0xf8,0x77" : "=m"(X) : "a"(&X)) +#define OUTPUT(T) void +#define INPUT(T,X) +#endif + +#undef ITM_READ_MEMCPY +#define ITM_READ_MEMCPY(T, LSMOD, TARGET, M2) \ +OUTPUT(T) ITM_REGPARM _ITM_##LSMOD##T (const _ITM_TYPE_##T *ptr) \ +{ \ + _ITM_TYPE_##T v; \ + TARGET memtransfer##M2(&v, ptr, sizeof(_ITM_TYPE_##T), false, \ + GTM::abi_dispatch::NONTXNAL, \ + GTM::abi_dispatch::LSMOD); \ + RETURN(v); \ +} + +#undef ITM_WRITE_MEMCPY +#define ITM_WRITE_MEMCPY(T, LSMOD, TARGET, M2) \ +void ITM_REGPARM _ITM_##LSMOD##T (_ITM_TYPE_##T *ptr INPUT(T,in)) \ +{ \ + _ITM_TYPE_##T v; \ + STORE(v, in); \ + TARGET memtransfer##M2(ptr, &v, sizeof(_ITM_TYPE_##T), false, \ + GTM::abi_dispatch::LSMOD, \ + GTM::abi_dispatch::NONTXNAL); \ +} + +// ??? Use memcpy for now, until we have figured out how to best instantiate +// these loads/stores. +CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M256, GTM::abi_disp()->, ) + +void ITM_REGPARM +_ITM_LM256 (const _ITM_TYPE_M256 *ptr) +{ + GTM::GTM_LB (ptr, sizeof (*ptr)); +} + +} // extern "C" diff --git a/gcc-4.8.3/libitm/config/x86/x86_sse.cc b/gcc-4.8.3/libitm/config/x86/x86_sse.cc new file mode 100644 index 000000000..0156192fd --- /dev/null +++ b/gcc-4.8.3/libitm/config/x86/x86_sse.cc @@ -0,0 +1,43 @@ +/* Copyright (C) 2009-2013 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 "libitm_i.h" +#include "dispatch.h" + +// ??? Use memcpy for now, until we have figured out how to best instantiate +// these loads/stores. +CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M64, GTM::abi_disp()->, ) +CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M128, GTM::abi_disp()->, ) + +void ITM_REGPARM +_ITM_LM64 (const _ITM_TYPE_M64 *ptr) +{ + GTM::GTM_LB (ptr, sizeof (*ptr)); +} + +void ITM_REGPARM +_ITM_LM128 (const _ITM_TYPE_M128 *ptr) +{ + GTM::GTM_LB (ptr, sizeof (*ptr)); +} |