diff --git a/libitm/ChangeLog b/libitm/ChangeLog index 1b5966ecdbe..ea535faedd7 100644 --- a/libitm/ChangeLog +++ b/libitm/ChangeLog @@ -1,3 +1,17 @@ +2011-12-14 Richard Henderson + + * config/arm/hwcap.h, config/arm/hwcap.cc: New files. + * config/arm/sjlj.S, config/arm/target.h: New files. + * config/generic/asmcfi.h (cfi_adjust_cfa_offset): New. + (cfi_rel_offset): New. + * config/linux/futex_bits.h: New file. + * config/linux/futex.cc: Include futex_bits.h here... + * config/linux/futex.h: ... not here. + * Makefile.am (libitm_la_SOURCES) : Add hwcap.cc. + * configure.ac (ARCH_AM): New conditional. + * Makefile.in, configure: Rebuild. + * configure.tgt: Handle ARM. + 2011-12-13 Richard Henderson * config/posix/rwlock.cc (gtm_rwlock::write_lock_generic): Fix diff --git a/libitm/Makefile.am b/libitm/Makefile.am index 26e1ebc632c..d41702614fd 100644 --- a/libitm/Makefile.am +++ b/libitm/Makefile.am @@ -62,6 +62,9 @@ libitm_la_SOURCES = \ query.cc retry.cc rwlock.cc useraction.cc util.cc \ sjlj.S tls.cc method-serial.cc method-gl.cc +if ARCH_ARM +libitm_la_SOURCES += hwcap.cc +endif if ARCH_X86 libitm_la_SOURCES += x86_sse.cc x86_avx.cc x86_sse.lo : XCFLAGS += -msse diff --git a/libitm/Makefile.in b/libitm/Makefile.in index dc7738275e8..5305f4ce8c5 100644 --- a/libitm/Makefile.in +++ b/libitm/Makefile.in @@ -36,8 +36,9 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -@ARCH_X86_TRUE@am__append_1 = x86_sse.cc x86_avx.cc -@ARCH_FUTEX_TRUE@am__append_2 = futex.cc +@ARCH_ARM_TRUE@am__append_1 = hwcap.cc +@ARCH_X86_TRUE@am__append_2 = x86_sse.cc x86_avx.cc +@ARCH_FUTEX_TRUE@am__append_3 = futex.cc subdir = . DIST_COMMON = $(am__configure_deps) $(srcdir)/../config.guess \ $(srcdir)/../config.sub $(srcdir)/../depcomp \ @@ -99,15 +100,16 @@ libitm_la_LIBADD = am__libitm_la_SOURCES_DIST = aatree.cc alloc.cc alloc_c.cc \ alloc_cpp.cc barrier.cc beginend.cc clone.cc eh_cpp.cc \ local.cc query.cc retry.cc rwlock.cc useraction.cc util.cc \ - sjlj.S tls.cc method-serial.cc method-gl.cc x86_sse.cc \ - x86_avx.cc futex.cc -@ARCH_X86_TRUE@am__objects_1 = x86_sse.lo x86_avx.lo -@ARCH_FUTEX_TRUE@am__objects_2 = futex.lo + sjlj.S tls.cc method-serial.cc method-gl.cc hwcap.cc \ + x86_sse.cc x86_avx.cc futex.cc +@ARCH_ARM_TRUE@am__objects_1 = hwcap.lo +@ARCH_X86_TRUE@am__objects_2 = x86_sse.lo x86_avx.lo +@ARCH_FUTEX_TRUE@am__objects_3 = futex.lo am_libitm_la_OBJECTS = aatree.lo alloc.lo alloc_c.lo alloc_cpp.lo \ barrier.lo beginend.lo clone.lo eh_cpp.lo local.lo query.lo \ retry.lo rwlock.lo useraction.lo util.lo sjlj.lo tls.lo \ method-serial.lo method-gl.lo $(am__objects_1) \ - $(am__objects_2) + $(am__objects_2) $(am__objects_3) libitm_la_OBJECTS = $(am_libitm_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/../depcomp @@ -376,7 +378,8 @@ libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) libitm_la_SOURCES = aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc \ barrier.cc beginend.cc clone.cc eh_cpp.cc local.cc query.cc \ retry.cc rwlock.cc useraction.cc util.cc sjlj.S tls.cc \ - method-serial.cc method-gl.cc $(am__append_1) $(am__append_2) + method-serial.cc method-gl.cc $(am__append_1) $(am__append_2) \ + $(am__append_3) # Automake Documentation: # If your package has Texinfo files in many directories, you can use the @@ -505,6 +508,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clone.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eh_cpp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/futex.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwcap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/local.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/method-gl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/method-serial.Plo@am__quote@ diff --git a/libitm/config/arm/hwcap.cc b/libitm/config/arm/hwcap.cc new file mode 100644 index 00000000000..007c10e7a4e --- /dev/null +++ b/libitm/config/arm/hwcap.cc @@ -0,0 +1,67 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson . + + 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 + . */ + +/* 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 +#include +#include + +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/libitm/config/arm/hwcap.h b/libitm/config/arm/hwcap.h new file mode 100644 index 00000000000..16e4034767c --- /dev/null +++ b/libitm/config/arm/hwcap.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson . + + 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 + . */ + +/* The following must match the kernel's . */ +#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/libitm/config/arm/sjlj.S b/libitm/config/arm/sjlj.S new file mode 100644 index 00000000000..2c9fb02c501 --- /dev/null +++ b/libitm/config/arm/sjlj.S @@ -0,0 +1,164 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson . + + 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 + . */ + +#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/libitm/config/arm/target.h b/libitm/config/arm/target.h new file mode 100644 index 00000000000..758d449428e --- /dev/null +++ b/libitm/config/arm/target.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson . + + 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 + . */ + +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/libitm/config/generic/asmcfi.h b/libitm/config/generic/asmcfi.h index 4344d6f8f97..c9d4edf6e69 100644 --- a/libitm/config/generic/asmcfi.h +++ b/libitm/config/generic/asmcfi.h @@ -27,18 +27,22 @@ #ifdef HAVE_AS_CFI_PSEUDO_OP -#define cfi_startproc .cfi_startproc -#define cfi_endproc .cfi_endproc -#define cfi_def_cfa_offset(n) .cfi_def_cfa_offset n -#define cfi_def_cfa(r,n) .cfi_def_cfa r, n -#define cfi_register(o,n) .cfi_register o, n +#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 #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) #endif /* HAVE_AS_CFI_PSEUDO_OP */ diff --git a/libitm/config/linux/futex.cc b/libitm/config/linux/futex.cc index 45c9db62dbb..0889ee5dfec 100644 --- a/libitm/config/linux/futex.cc +++ b/libitm/config/linux/futex.cc @@ -26,6 +26,7 @@ #include "libitm_i.h" #include "futex.h" +#include #include namespace GTM HIDDEN { diff --git a/libitm/config/linux/futex.h b/libitm/config/linux/futex.h index 326c0f56eed..00161b47431 100644 --- a/libitm/config/linux/futex.h +++ b/libitm/config/linux/futex.h @@ -29,8 +29,6 @@ namespace GTM HIDDEN { -#include "futex_bits.h" - extern void futex_wait (int *addr, int val); extern long futex_wake (int *addr, int count); diff --git a/libitm/config/linux/futex_bits.h b/libitm/config/linux/futex_bits.h new file mode 100644 index 00000000000..bbc336604e9 --- /dev/null +++ b/libitm/config/linux/futex_bits.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2011 Free Software Foundation, Inc. + Contributed by Richard Henderson . + + 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 + . */ + +/* 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 +#include + +static inline long +sys_futex0 (int *addr, long op, long val) +{ + return syscall (SYS_futex, addr, op, val, 0); +} diff --git a/libitm/configure b/libitm/configure index 9b063594111..3abc7930e20 100644 --- a/libitm/configure +++ b/libitm/configure @@ -607,6 +607,8 @@ ARCH_X86_AVX_FALSE ARCH_X86_AVX_TRUE ARCH_X86_FALSE ARCH_X86_TRUE +ARCH_ARM_FALSE +ARCH_ARM_TRUE link_itm XLDFLAGS XCFLAGS @@ -11720,7 +11722,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11723 "configure" +#line 11725 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11826,7 +11828,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11829 "configure" +#line 11831 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -17369,6 +17371,14 @@ else fi + if test "$ARCH" = arm; then + ARCH_ARM_TRUE= + ARCH_ARM_FALSE='#' +else + ARCH_ARM_TRUE='#' + ARCH_ARM_FALSE= +fi + if test "$ARCH" = x86; then ARCH_X86_TRUE= ARCH_X86_FALSE='#' @@ -17542,6 +17552,10 @@ if test -z "${LIBITM_BUILD_VERSIONED_SHLIB_SUN_TRUE}" && test -z "${LIBITM_BUILD as_fn_error "conditional \"LIBITM_BUILD_VERSIONED_SHLIB_SUN\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${ARCH_ARM_TRUE}" && test -z "${ARCH_ARM_FALSE}"; then + as_fn_error "conditional \"ARCH_ARM\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${ARCH_X86_TRUE}" && test -z "${ARCH_X86_FALSE}"; then as_fn_error "conditional \"ARCH_X86\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/libitm/configure.ac b/libitm/configure.ac index 45ee8701e38..ab2a90b7cf9 100644 --- a/libitm/configure.ac +++ b/libitm/configure.ac @@ -273,6 +273,7 @@ else fi AC_SUBST(link_itm) +AM_CONDITIONAL([ARCH_ARM], [test "$ARCH" = arm]) AM_CONDITIONAL([ARCH_X86], [test "$ARCH" = x86]) AM_CONDITIONAL([ARCH_X86_AVX], [test "$libitm_cv_as_avx" = yes]) AM_CONDITIONAL([ARCH_FUTEX], [test $enable_linux_futex = yes]) diff --git a/libitm/configure.tgt b/libitm/configure.tgt index eac6f504433..a17f3fc7b90 100644 --- a/libitm/configure.tgt +++ b/libitm/configure.tgt @@ -48,6 +48,8 @@ fi case "${target_cpu}" in alpha*) ARCH=alpha ;; + arm*) ARCH=arm ;; + i[3456]86) case " ${CC} ${CFLAGS} " in *" -m64 "*)