summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-12 22:44:25 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-12 22:44:25 +0000
commit71557f40388d63f90772e131647e3945acae850a (patch)
treeabfdf21b9b9e181b7c87659d760cf46b5478d42c
parentf0f80a6fb019976c280ff8587fbc7ba36a51625f (diff)
downloadgcc-71557f40388d63f90772e131647e3945acae850a.tar.gz
Merge branch 'libitm-cpp'
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/transactional-memory@154130 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--libitm/ChangeLog4
-rw-r--r--libitm/Makefile.am23
-rw-r--r--libitm/Makefile.in105
-rw-r--r--libitm/aatree.c298
-rw-r--r--libitm/aatree.cc222
-rw-r--r--libitm/aatree.h187
-rw-r--r--libitm/alloc.cc (renamed from libitm/alloc.c)45
-rw-r--r--libitm/alloc_c.cc (renamed from libitm/alloc_c.c)22
-rw-r--r--libitm/alloc_cpp.cc (renamed from libitm/alloc_cpp.c)22
-rw-r--r--libitm/barrier.c107
-rw-r--r--libitm/barrier.cc (renamed from libitm/config/alpha/target_i.h)33
-rw-r--r--libitm/barrier.tpl137
-rw-r--r--libitm/beginend.cc (renamed from libitm/beginend.c)164
-rw-r--r--libitm/clone.cc (renamed from libitm/clone.c)55
-rw-r--r--libitm/config.h.in19
-rw-r--r--libitm/config/alpha/cacheline.h122
-rw-r--r--libitm/config/alpha/copymask.c90
-rw-r--r--libitm/config/alpha/target.h31
-rw-r--r--libitm/config/alpha/unaligned.h118
-rw-r--r--libitm/config/generic/cacheline.cc (renamed from libitm/retry.c)40
-rw-r--r--libitm/config/generic/cacheline.h107
-rw-r--r--libitm/config/generic/cachepage.h77
-rw-r--r--libitm/config/generic/tls.h90
-rw-r--r--libitm/config/generic/unaligned.h228
-rw-r--r--libitm/config/linux/futex.cc (renamed from libitm/config/linux/futex.c)18
-rw-r--r--libitm/config/linux/futex.h8
-rw-r--r--libitm/config/linux/rwlock.c257
-rw-r--r--libitm/config/linux/rwlock.cc246
-rw-r--r--libitm/config/linux/rwlock.h52
-rw-r--r--libitm/config/linux/x86/tls.h84
-rw-r--r--libitm/config/posix/cachepage.cc (renamed from libitm/config/posix/page.c)35
-rw-r--r--libitm/config/posix/rwlock.cc189
-rw-r--r--libitm/config/posix/rwlock.h73
-rw-r--r--libitm/config/x86/cacheline.cc73
-rw-r--r--libitm/config/x86/cacheline.h242
-rw-r--r--libitm/config/x86/copymask.c187
-rw-r--r--libitm/config/x86/target.h50
-rw-r--r--libitm/config/x86/target_i.h155
-rw-r--r--libitm/config/x86/unaligned.h241
-rw-r--r--libitm/config/x86/x86_avx.c88
-rw-r--r--libitm/config/x86/x86_avx.cc93
-rw-r--r--libitm/config/x86/x86_sse.c166
-rw-r--r--libitm/config/x86/x86_sse.cc120
-rwxr-xr-xlibitm/configure4752
-rw-r--r--libitm/configure.ac19
-rw-r--r--libitm/configure.tgt8
-rw-r--r--libitm/copymask.c195
-rw-r--r--libitm/eh_cpp.cc (renamed from libitm/eh_cpp.c)22
-rw-r--r--libitm/libitm.h20
-rw-r--r--libitm/libitm_i.h529
-rw-r--r--libitm/local.cc (renamed from libitm/local.c)40
-rw-r--r--libitm/memcpy.cc (renamed from libitm/memcpy.c)199
-rw-r--r--libitm/memset.cc (renamed from libitm/memset.c)27
-rw-r--r--libitm/method-readonly.c115
-rw-r--r--libitm/method-readonly.cc123
-rw-r--r--libitm/method-wbetl.c527
-rw-r--r--libitm/method-wbetl.cc530
-rw-r--r--libitm/query.cc (renamed from libitm/query.c)3
-rw-r--r--libitm/retry.cc80
-rw-r--r--libitm/serial.c126
-rw-r--r--libitm/serial.cc122
-rw-r--r--libitm/stmlock.h123
-rw-r--r--libitm/testsuite/Makefile.in5
-rw-r--r--libitm/useraction.cc (renamed from libitm/useraction.c)16
-rw-r--r--libitm/util.cc79
65 files changed, 9068 insertions, 3315 deletions
diff --git a/libitm/ChangeLog b/libitm/ChangeLog
index 67c918ca1e7..0e74790323f 100644
--- a/libitm/ChangeLog
+++ b/libitm/ChangeLog
@@ -1,3 +1,7 @@
+2009-11-12 Richard Henderson <rth@redhat.com>
+
+ * Rewrite everything in C++.
+
2009-11-03 Richard Henderson <rth@redhat.com>
* config/x86/x86_sse.c, config/x86/x86_avx.c: New files.
diff --git a/libitm/Makefile.am b/libitm/Makefile.am
index 8a9ae5c5a2e..5dbefb01fcd 100644
--- a/libitm/Makefile.am
+++ b/libitm/Makefile.am
@@ -16,6 +16,7 @@ vpath % $(strip $(search_path))
AM_CPPFLAGS = $(addprefix -I, $(search_path))
AM_CFLAGS = $(XCFLAGS)
+AM_CXXFLAGS = -std=gnu++0x -fno-rtti $(XCFLAGS)
AM_CCASFLAGS = $(XCFLAGS)
AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS)
@@ -28,17 +29,25 @@ else
libitm_version_script =
endif
libitm_version_info = -version-info $(libtool_VERSION)
+
+## Force link with C, not C++. For now, while we're using C++ we don't
+## want or need libstdc++.
+libitm_la_LINK = $(LINK)
libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \
-no-undefined
libitm_la_SOURCES = \
- aatree.c alloc.c alloc_c.c alloc_cpp.c barrier.c beginend.c \
- clone.c copymask.c eh_cpp.c local.c memcpy.c memset.c page.c \
- query.c retry.c rwlock.c serial.c useraction.c sjlj.S futex.c \
- method-readonly.c method-wbetl.c
+ aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc barrier.cc beginend.cc \
+ clone.cc cacheline.cc cachepage.cc eh_cpp.cc local.cc memcpy.cc \
+ memset.cc query.cc retry.cc rwlock.cc serial.cc useraction.cc util.cc \
+ sjlj.S method-readonly.cc method-wbetl.cc
if ARCH_X86
-libitm_la_SOURCES += x86_sse.c x86_avx.c
-x86_sse.lo : AM_CFLAGS += -msse
-x86_avx.lo : AM_CFLAGS += -mavx
+libitm_la_SOURCES += x86_sse.cc x86_avx.cc
+x86_sse.lo : XCFLAGS += -msse
+x86_avx.lo : XCFLAGS += -mavx
+endif
+
+if ARCH_FUTEX
+libitm_la_SOURCES += futex.cc
endif
diff --git a/libitm/Makefile.in b/libitm/Makefile.in
index d19215da759..f46c1725cef 100644
--- a/libitm/Makefile.in
+++ b/libitm/Makefile.in
@@ -36,7 +36,8 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
-@ARCH_X86_TRUE@am__append_1 = x86_sse.c x86_avx.c
+@ARCH_X86_TRUE@am__append_1 = x86_sse.cc x86_avx.cc
+@ARCH_FUTEX_TRUE@am__append_2 = futex.cc
subdir = .
DIST_COMMON = $(am__configure_deps) $(srcdir)/../config.guess \
$(srcdir)/../config.sub $(srcdir)/../depcomp \
@@ -92,21 +93,21 @@ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" \
"$(DESTDIR)$(toolexeclibdir)"
LTLIBRARIES = $(toolexeclib_LTLIBRARIES)
libitm_la_LIBADD =
-am__libitm_la_SOURCES_DIST = aatree.c alloc.c alloc_c.c alloc_cpp.c \
- barrier.c beginend.c clone.c copymask.c eh_cpp.c local.c \
- memcpy.c memset.c page.c query.c retry.c rwlock.c serial.c \
- useraction.c sjlj.S futex.c method-readonly.c method-wbetl.c \
- x86_sse.c x86_avx.c
+am__libitm_la_SOURCES_DIST = aatree.cc alloc.cc alloc_c.cc \
+ alloc_cpp.cc barrier.cc beginend.cc clone.cc cacheline.cc \
+ cachepage.cc eh_cpp.cc local.cc memcpy.cc memset.cc query.cc \
+ retry.cc rwlock.cc serial.cc useraction.cc util.cc sjlj.S \
+ method-readonly.cc method-wbetl.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
am_libitm_la_OBJECTS = aatree.lo alloc.lo alloc_c.lo alloc_cpp.lo \
- barrier.lo beginend.lo clone.lo copymask.lo eh_cpp.lo local.lo \
- memcpy.lo memset.lo page.lo query.lo retry.lo rwlock.lo \
- serial.lo useraction.lo sjlj.lo futex.lo method-readonly.lo \
- method-wbetl.lo $(am__objects_1)
+ barrier.lo beginend.lo clone.lo cacheline.lo cachepage.lo \
+ eh_cpp.lo local.lo memcpy.lo memset.lo query.lo retry.lo \
+ rwlock.lo serial.lo useraction.lo util.lo sjlj.lo \
+ method-readonly.lo method-wbetl.lo $(am__objects_1) \
+ $(am__objects_2)
libitm_la_OBJECTS = $(am_libitm_la_OBJECTS)
-libitm_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
- $(libitm_la_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/../depcomp
am__depfiles_maybe = depfiles
@@ -116,6 +117,15 @@ CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
LTCPPASCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS)
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
@@ -200,6 +210,10 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@@ -260,6 +274,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_ct_FC = @ac_ct_FC@
am__include = @am__include@
@@ -328,6 +343,7 @@ fincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/finclude
libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
AM_CPPFLAGS = $(addprefix -I, $(search_path))
AM_CFLAGS = $(XCFLAGS)
+AM_CXXFLAGS = -std=gnu++0x -fno-rtti $(XCFLAGS)
AM_CCASFLAGS = $(XCFLAGS)
AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS)
toolexeclib_LTLIBRARIES = libitm.la
@@ -335,19 +351,21 @@ nodist_toolexeclib_HEADERS = libitm.spec
@LIBITM_BUILD_VERSIONED_SHLIB_FALSE@libitm_version_script =
@LIBITM_BUILD_VERSIONED_SHLIB_TRUE@libitm_version_script = -Wl,--version-script,$(top_srcdir)/libitm.map
libitm_version_info = -version-info $(libtool_VERSION)
+libitm_la_LINK = $(LINK)
libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \
-no-undefined
-libitm_la_SOURCES = aatree.c alloc.c alloc_c.c alloc_cpp.c barrier.c \
- beginend.c clone.c copymask.c eh_cpp.c local.c memcpy.c \
- memset.c page.c query.c retry.c rwlock.c serial.c useraction.c \
- sjlj.S futex.c method-readonly.c method-wbetl.c \
- $(am__append_1)
+libitm_la_SOURCES = aatree.cc alloc.cc alloc_c.cc alloc_cpp.cc \
+ barrier.cc beginend.cc clone.cc cacheline.cc cachepage.cc \
+ eh_cpp.cc local.cc memcpy.cc memset.cc query.cc retry.cc \
+ rwlock.cc serial.cc useraction.cc util.cc sjlj.S \
+ method-readonly.cc method-wbetl.cc $(am__append_1) \
+ $(am__append_2)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
-.SUFFIXES: .S .c .lo .o .obj
+.SUFFIXES: .S .cc .lo .o .obj
am--refresh:
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@@ -447,8 +465,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alloc_cpp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/barrier.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/beginend.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cacheline.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cachepage.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clone.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/copymask.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)/local.Plo@am__quote@
@@ -456,13 +475,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memset.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/method-readonly.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/method-wbetl.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/page.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/query.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/retry.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rwlock.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/serial.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sjlj.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/useraction.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x86_avx.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/x86_sse.Plo@am__quote@
@@ -487,26 +506,26 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCCAS_FALSE@ $(LTCPPASCOMPILE) -c -o $@ $<
-.c.o:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c $<
-
-.c.obj:
-@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
-
-.c.lo:
-@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+.cc.o:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cc.obj:
+@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cc.lo:
+@am__fastdepCXX_TRUE@ $(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
@@ -1001,8 +1020,8 @@ uninstall-am: uninstall-nodist_toolexeclibHEADERS \
vpath % $(strip $(search_path))
-@ARCH_X86_TRUE@x86_sse.lo : AM_CFLAGS += -msse
-@ARCH_X86_TRUE@x86_avx.lo : AM_CFLAGS += -mavx
+@ARCH_X86_TRUE@x86_sse.lo : XCFLAGS += -msse
+@ARCH_X86_TRUE@x86_avx.lo : XCFLAGS += -mavx
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/libitm/aatree.c b/libitm/aatree.c
deleted file mode 100644
index 88164ac4662..00000000000
--- a/libitm/aatree.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/* Copyright (C) 2009 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/>. */
-
-/* Implements an AA tree (http://en.wikipedia.org/wiki/AA_tree) with an
- integer key, and data attached to the node via flexible array member. */
-
-#include "libitm_i.h"
-
-
-typedef unsigned int aa_level;
-
-typedef struct aa_node
-{
- struct aa_node *link[2];
- aa_key key;
- aa_level level;
- char data[] __attribute__((aligned));
-} aa_node;
-
-#define L 0
-#define R 1
-#define NIL ((aa_tree)&aa_nil)
-
-/* The code for rebalancing the tree is greatly simplified by never
- having to check for null pointers. Instead, leaf node links point
- to this node, NIL, which points to itself. */
-static const aa_node aa_nil = { { NIL, NIL }, 0, 0 };
-
-/* Remove left horizontal links. Swap the pointers of
- horizontal left links. */
-
-static aa_tree
-skew (aa_tree t)
-{
- aa_tree l = t->link[L];
- if (t->level != 0 && l->level == t->level)
- {
- t->link[L] = l->link[R];
- l->link[R] = t;
- return l;
- }
- return t;
-}
-
-/* Remove consecutive horizontal links. Take the middle node,
- elevate it, and return it. */
-
-static aa_tree
-split (aa_tree t)
-{
- aa_tree r = t->link[R];
- if (t->level != 0 && r->link[R]->level == t->level)
- {
- t->link[R] = r->link[L];
- r->link[L] = t;
- r->level += 1;
- return r;
- }
- return t;
-}
-
-/* Decrease the level of T to be one more than the level of its children. */
-
-static void
-decrease_level (aa_tree t)
-{
- aa_tree l = t->link[L];
- aa_tree r = t->link[R];
- aa_level llev = l->level;
- aa_level rlev = r->level;
- aa_level should_be = (llev < rlev ? llev : rlev) + 1;
-
- if (should_be < t->level)
- {
- t->level = should_be;
- if (should_be < rlev)
- r->level = should_be;
- }
-}
-
-/* Allocate a new node for KEY, with extra memory SIZE. */
-
-static aa_tree
-aa_new (uintptr_t key, size_t size)
-{
- aa_tree n = malloc (sizeof (*n) + size);
-
- n->link[0] = NIL;
- n->link[1] = NIL;
- n->key = key;
- n->level = 1;
-
- return n;
-}
-
-/* Find the node within T that has KEY. If found, return the data
- associated with the key. */
-
-void *
-aa_find (aa_tree t, aa_key key)
-{
- if (t != NULL)
- while (t != NIL)
- {
- if (t->key == key)
- return t->data;
- t = t->link[key > t->key];
- }
-
- return NULL;
-}
-
-/* Insert N into T and rebalance. Return the new balanced tree. */
-
-static aa_tree
-aa_insert_1 (aa_tree t, aa_tree n)
-{
- int dir = n->key > t->key;
- aa_tree c = t->link[dir];
-
- /* Insert the node, recursively. */
- if (c == NIL)
- c = n;
- else
- c = aa_insert_1 (c, n);
- t->link[dir] = c;
-
- /* Rebalance the tree, as needed. */
- t = skew (t);
- t = split (t);
-
- return t;
-}
-
-/* Insert a new node with KEY into the tree rooted at *PTREE. Create
- the new node with extra memory SIZE. Return a pointer to the extra
- memory associated with the new node. It is invalid to insert a
- duplicate key. */
-
-void *
-aa_insert (aa_tree *ptree, aa_key key, size_t size)
-{
- aa_tree n = aa_new (key, size);
- aa_tree t = *ptree;
-
- if (t == NULL)
- t = n;
- else
- t = aa_insert_1 (t, n);
- *ptree = t;
-
- return n->data;
-}
-
-/* Delete KEY from T and rebalance. Return the new balanced tree. */
-
-static aa_tree
-aa_delete_1 (aa_tree t, aa_key key, bool do_free)
-{
- aa_tree r;
- int dir;
-
- /* If this is the node we're looking for, delete it. Else recurse. */
- if (key == t->key)
- {
- aa_tree l, sub, end;
-
- l = t->link[L];
- r = t->link[R];
-
- if (do_free)
- free (t);
-
- /* If this is a leaf node, simply remove the node. Otherwise,
- we have to find either a predecessor or a successor node to
- replace this one. */
- if (l == NIL)
- {
- if (r == NIL)
- return NIL;
- sub = r, dir = L;
- }
- else
- sub = l, dir = R;
-
- /* Find the successor or predecessor. */
- for (end = sub; end->link[dir] != NIL; end = end->link[dir])
- continue;
-
- /* Remove it (but don't free) from the subtree. */
- sub = aa_delete_1 (sub, end->key, false);
-
- /* Replace T with the successor we just extracted. */
- end->link[1-dir] = sub;
- t = end;
- }
- else
- {
- dir = key > t->key;
- t->link[dir] = aa_delete_1 (t->link[dir], key, do_free);
- }
-
- /* Rebalance the tree. */
- decrease_level (t);
- t = skew (t);
- t->link[R] = r = skew (t->link[R]);
- r->link[R] = skew (r->link[R]);
- t = split (t);
- t->link[R] = split (t->link[R]);
-
- return t;
-}
-
-/* Delete KEY from the tree rooted at *PTREE. */
-
-void
-aa_delete (aa_tree *ptree, aa_key key)
-{
- aa_tree t = *ptree;
-
- if (t == NULL)
- return;
-
- t = aa_delete_1 (t, key, true);
- if (t == NIL)
- t = NULL;
- *ptree = t;
-}
-
-/* Free the tree at T. */
-
-static void
-aa_free_1 (aa_tree t)
-{
- int dir;
- for (dir = 0; dir < 2; ++dir)
- {
- aa_tree c = t->link[dir];
- if (c != NIL)
- aa_free_1 (c);
- }
- free (t);
-}
-
-/* Free the tree rooted at *PTREE. */
-
-void
-aa_free (aa_tree *ptree)
-{
- aa_tree t = *ptree;
- if (t != NULL)
- aa_free_1 (t);
- *ptree = NULL;
-}
-
-/* Invoke CALLBACK on each node of T. */
-
-static void
-aa_traverse_1 (aa_tree t, void (*callback)(aa_key, void *, void *),
- void *callback_data)
-{
- if (t == NIL)
- return;
-
- callback (t->key, t->data, callback_data);
-
- aa_traverse (t->link[L], callback, callback_data);
- aa_traverse (t->link[R], callback, callback_data);
-}
-
-void
-aa_traverse (aa_tree t, void (*callback)(aa_key, void *, void *),
- void *callback_data)
-{
- if (t != NULL)
- aa_traverse_1 (t, callback, callback_data);
-}
diff --git a/libitm/aatree.cc b/libitm/aatree.cc
new file mode 100644
index 00000000000..a930e7199e9
--- /dev/null
+++ b/libitm/aatree.cc
@@ -0,0 +1,222 @@
+/* Copyright (C) 2009 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/>. */
+
+// Implements an AA tree (http://en.wikipedia.org/wiki/AA_tree) with an
+// integer key, and data attached to the node via flexible array member.
+
+#include "libitm_i.h"
+
+namespace GTM HIDDEN {
+
+// The code for rebalancing the tree is greatly simplified by never
+// having to check for null pointers. Instead, leaf node links point
+// to this node, NIL, which points to itself.
+const aa_node_base aa_node_base::s_nil(0);
+
+
+// Remove left horizontal links. Swap the pointers of horizontal left links.
+
+aa_node_base *
+aa_node_base::skew ()
+{
+ aa_node_base *l = this->link(L);
+ if (this->m_level != 0 && l->m_level == this->m_level)
+ {
+ this->set_link(L, l->link(R));
+ l->set_link(R, this);
+ return l;
+ }
+ return this;
+}
+
+
+// Remove consecutive horizontal links. Take the middle node,
+// elevate it, and return it.
+
+aa_node_base *
+aa_node_base::split ()
+{
+ aa_node_base *r = this->link(R);
+ if (this->m_level != 0 && r->link(R)->m_level == this->m_level)
+ {
+ this->set_link(R, r->link(L));
+ r->set_link(L, this);
+ r->m_level += 1;
+ return r;
+ }
+ return this;
+}
+
+// Decrease the level of THIS to be one more than the level of its children.
+
+void
+aa_node_base::decrease_level ()
+{
+ aa_node_base *l = this->link(L);
+ aa_node_base *r = this->link(R);
+ level_type llev = l->m_level;
+ level_type rlev = r->m_level;
+ level_type should_be = (llev < rlev ? llev : rlev) + 1;
+
+ if (should_be < this->m_level)
+ {
+ this->m_level = should_be;
+ if (should_be < rlev)
+ r->m_level = should_be;
+ }
+}
+
+// Find and return the node in the tree with key K.
+
+template<typename KEY>
+typename aa_tree_key<KEY>::node_ptr
+aa_tree_key<KEY>::find(KEY k) const
+{
+ node_ptr t = m_tree;
+ if (t != 0)
+ do
+ {
+ if (t->key == k)
+ return t;
+ t = t->link(k > t->key);
+ }
+ while (!t->is_nil());
+ return 0;
+}
+
+// Insert N into T and rebalance. Return the new balanced tree.
+
+template<typename KEY>
+typename aa_tree_key<KEY>::node_ptr
+aa_tree_key<KEY>::insert_1 (node_ptr t, node_ptr n)
+{
+ bool dir = n->key > t->key;
+ node_ptr c = t->link(dir);
+
+ // Insert the node, recursively.
+ if (c->is_nil())
+ c = n;
+ else
+ c = insert_1 (c, n);
+ t->set_link(dir, c);
+
+ // Rebalance the tree, as needed.
+ t = t->skew();
+ t = t->split();
+
+ return t;
+}
+
+template<typename KEY>
+void
+aa_tree_key<KEY>::insert(node_ptr n)
+{
+ if (m_tree == 0)
+ m_tree = n;
+ else
+ m_tree = insert_1 (m_tree, n);
+}
+
+// Delete K from T and rebalance. Return the new balanced tree.
+
+template<typename KEY>
+typename aa_tree_key<KEY>::node_ptr
+aa_tree_key<KEY>::erase_1 (node_ptr t, KEY k, node_ptr *pfree)
+{
+ node_ptr r;
+ bool dir;
+
+ // If this is the node we're looking for, delete it. Else recurse.
+ if (k == t->key)
+ {
+ node_ptr l, sub, end;
+
+ l = t->link(node::L);
+ r = t->link(node::R);
+
+ if (pfree)
+ *pfree = t;
+
+ // If this is a leaf node, simply remove the node. Otherwise,
+ // we have to find either a predecessor or a successor node to
+ // replace this one.
+ if (l->is_nil())
+ {
+ if (r->is_nil())
+ return r;
+ sub = r, dir = node::L;
+ }
+ else
+ sub = l, dir = node::R;
+
+ // Find the successor or predecessor.
+ for (end = sub; !end->link(dir)->is_nil(); end = end->link(dir))
+ continue;
+
+ // Remove it (but don't free) from the subtree.
+ sub = erase_1 (sub, end->key, 0);
+
+ // Replace T with the successor we just extracted.
+ end->set_link(!dir, sub);
+ t = end;
+ }
+ else
+ {
+ dir = k > t->key;
+ t->set_link(dir, erase_1 (t->link(dir), k, pfree));
+ }
+
+ // Rebalance the tree.
+ t->decrease_level();
+ t = t->skew();
+ r = t->link(node::R)->skew();
+ t->set_link(node::R, r);
+ r->set_link(node::R, r->link(node::R)->skew());
+ t = t->split ();
+ t->set_link(node::R, t->link(node::R)->split());
+
+ return t;
+}
+
+template<typename KEY>
+typename aa_tree_key<KEY>::node_ptr
+aa_tree_key<KEY>::erase (KEY k)
+{
+ node_ptr t = m_tree;
+ if (t == 0)
+ return 0;
+
+ node_ptr do_free = 0;
+ t = erase_1 (t, k, &do_free);
+ if (t->is_nil())
+ t = 0;
+ m_tree = t;
+ return do_free;
+}
+
+// Instantiate key classes.
+
+template class aa_tree_key<uintptr_t>;
+
+} // namespace GTM
diff --git a/libitm/aatree.h b/libitm/aatree.h
index 582eb652177..6d28890c7b1 100644
--- a/libitm/aatree.h
+++ b/libitm/aatree.h
@@ -25,11 +25,182 @@
/* Implements an AA tree (http://en.wikipedia.org/wiki/AA_tree) with an
integer key, and data attached to the node via flexible array member. */
-typedef uintptr_t aa_key;
-typedef struct aa_node *aa_tree;
-
-extern void *aa_find (aa_tree, aa_key);
-extern void *aa_insert (aa_tree *, aa_key, size_t);
-extern void aa_delete (aa_tree *, aa_key);
-extern void aa_free (aa_tree *);
-extern void aa_traverse (aa_tree, void (*)(aa_key, void *, void *), void *);
+#ifndef LIBITM_AATREE_H
+#define LIBITM_AATREE_H 1
+
+namespace GTM HIDDEN {
+
+template<typename KEY> class aa_tree_key;
+
+class aa_node_base
+{
+ public:
+ static const bool L = false;
+ static const bool R = true;
+
+ private:
+ typedef unsigned int level_type;
+
+ aa_node_base *m_link[2];
+ level_type m_level;
+
+ static const aa_node_base s_nil;
+
+ public:
+ aa_node_base(level_type l = 1)
+ : m_link({ const_cast<aa_node_base *>(&s_nil),
+ const_cast<aa_node_base *>(&s_nil) }),
+ m_level(l)
+ { }
+
+ bool is_nil() const { return this == &s_nil; }
+
+ aa_node_base * link(bool d) { return m_link[d]; }
+ void set_link(bool d, aa_node_base *val) { m_link[d] = val; }
+
+ aa_node_base *skew();
+ aa_node_base *split();
+ void decrease_level();
+
+ static void *operator new (size_t s) { return xmalloc (s); }
+ static void operator delete (void *p) { free (p); }
+};
+
+template<typename KEY>
+struct aa_node_key : public aa_node_base
+{
+ typedef aa_node_base base;
+
+ KEY key;
+
+ explicit aa_node_key(KEY k) : key(k) { }
+
+ aa_node_key * link(bool d)
+ {
+ return static_cast<aa_node_key *>(base::link(d));
+ }
+
+ aa_node_key *skew() { return static_cast<aa_node_key *>(base::skew()); }
+ aa_node_key *split() { return static_cast<aa_node_key *>(base::split()); }
+};
+
+template<typename KEY, typename DATA>
+struct aa_node : public aa_node_key<KEY>
+{
+ typedef aa_node_key<KEY> base;
+
+ DATA data;
+
+ explicit aa_node(KEY k) : base(k) { }
+
+ aa_node * link(bool d)
+ {
+ return static_cast<aa_node *>(base::link(d));
+ }
+};
+
+template<typename KEY>
+class aa_tree_key
+{
+ public:
+ typedef aa_node_key<KEY> node;
+ typedef node *node_ptr;
+
+ protected:
+ node_ptr m_tree;
+
+ protected:
+ aa_tree_key() : m_tree(0) { }
+
+ node_ptr find(KEY k) const;
+
+ static node_ptr insert_1 (node_ptr t, node_ptr n);
+ void insert(node_ptr n);
+
+ static node_ptr erase_1 (node_ptr t, KEY k, node_ptr *pfree);
+ node_ptr erase(KEY k);
+};
+
+extern template class aa_tree_key<uintptr_t>;
+
+template<typename KEY, typename DATA>
+class aa_tree : public aa_tree_key<KEY>
+{
+ public:
+ typedef aa_tree_key<KEY> base;
+ typedef aa_node<KEY, DATA> node;
+ typedef node *node_ptr;
+
+ typedef void (*trav_callback)(KEY, DATA *, void *);
+
+ private:
+ static void clear_1 (node_ptr);
+ static void traverse_1 (node_ptr, trav_callback, void *);
+
+ public:
+ aa_tree() = default;
+ ~aa_tree() { clear(); }
+
+ DATA *find(KEY k) const
+ {
+ node_ptr n = static_cast<node_ptr>(base::find (k));
+ return n ? &n->data : 0;
+ }
+
+ DATA *insert(KEY k)
+ {
+ node_ptr n = new node(k);
+ base::insert(n);
+ return &n->data;
+ }
+
+ void erase(KEY k)
+ {
+ node_ptr n = static_cast<node_ptr>(base::erase (k));
+ delete n;
+ }
+
+ void clear()
+ {
+ node_ptr n = static_cast<node_ptr>(this->m_tree);
+ if (n)
+ {
+ this->m_tree = 0;
+ clear_1 (n);
+ }
+ }
+
+ void traverse (trav_callback cb, void *cb_data)
+ {
+ node_ptr t = static_cast<node_ptr>(this->m_tree);
+ if (t != 0)
+ traverse_1 (t, cb, cb_data);
+ }
+};
+
+
+template<typename KEY, typename DATA>
+void
+aa_tree<KEY, DATA>::clear_1 (node_ptr t)
+{
+ if (t->is_nil())
+ return;
+ clear_1 (t->link(node::L));
+ clear_1 (t->link(node::R));
+ delete t;
+}
+
+template<typename KEY, typename DATA>
+void
+aa_tree<KEY, DATA>::traverse_1 (node_ptr t, trav_callback cb, void *cb_data)
+{
+ if (t->is_nil())
+ return;
+ cb (t->key, &t->data, cb_data);
+ traverse_1 (t->link(node::L), cb, cb_data);
+ traverse_1 (t->link(node::R), cb, cb_data);
+}
+
+} // namespace GTM
+
+#endif // LIBITM_AATREE_H
diff --git a/libitm/alloc.c b/libitm/alloc.cc
index d2bd4380454..2729760a1aa 100644
--- a/libitm/alloc.c
+++ b/libitm/alloc.cc
@@ -24,26 +24,25 @@
#include "libitm_i.h"
+namespace GTM HIDDEN {
-/* This is extra data attached to each node of an AA tree. */
-typedef struct gtm_alloc_action
+struct gtm_alloc_action
{
void (*free_fn)(void *);
size_t size;
bool allocated;
-} gtm_alloc_action;
+};
void
-GTM_record_allocation (void *ptr, size_t size, void (*free_fn)(void *))
+gtm_transaction::record_allocation (void *ptr, size_t size,
+ void (*free_fn)(void *))
{
- gtm_transaction *tx = gtm_tx ();
- gtm_alloc_action *a;
uintptr_t iptr = (uintptr_t) ptr;
- a = aa_find (tx->alloc_actions, iptr);
- if (a == NULL)
- a = aa_insert (&tx->alloc_actions, iptr, sizeof (*a));
+ gtm_alloc_action *a = this->alloc_actions.find(iptr);
+ if (a == 0)
+ a = this->alloc_actions.insert(iptr);
a->free_fn = free_fn;
a->size = size;
@@ -51,15 +50,13 @@ GTM_record_allocation (void *ptr, size_t size, void (*free_fn)(void *))
}
void
-GTM_forget_allocation (void *ptr, void (*free_fn)(void *))
+gtm_transaction::forget_allocation (void *ptr, void (*free_fn)(void *))
{
- gtm_transaction *tx = gtm_tx ();
- gtm_alloc_action *a;
uintptr_t iptr = (uintptr_t) ptr;
- a = aa_find (tx->alloc_actions, iptr);
- if (a == NULL)
- a = aa_insert (&tx->alloc_actions, iptr, sizeof (*a));
+ gtm_alloc_action *a = this->alloc_actions.find(iptr);
+ if (a == 0)
+ a = this->alloc_actions.insert(iptr);
a->free_fn = free_fn;
a->size = 0;
@@ -67,21 +64,18 @@ GTM_forget_allocation (void *ptr, void (*free_fn)(void *))
}
size_t
-GTM_get_allocation_size (void *ptr)
+gtm_transaction::get_allocation_size (void *ptr)
{
- gtm_transaction *tx = gtm_tx ();
- gtm_alloc_action *a;
uintptr_t iptr = (uintptr_t) ptr;
- a = aa_find (tx->alloc_actions, iptr);
+ gtm_alloc_action *a = this->alloc_actions.find(iptr);
return a ? a->size : 0;
}
static void
-commit_allocations_1 (aa_key key, void *node_data, void *cb_data)
+commit_allocations_1 (uintptr_t key, gtm_alloc_action *a, void *cb_data)
{
void *ptr = (void *)key;
- gtm_alloc_action *a = node_data;
uintptr_t revert_p = (uintptr_t) cb_data;
if (a->allocated == revert_p)
@@ -89,8 +83,11 @@ commit_allocations_1 (aa_key key, void *node_data, void *cb_data)
}
void
-GTM_commit_allocations (bool revert_p)
+gtm_transaction::commit_allocations (bool revert_p)
{
- aa_traverse (gtm_tx()->alloc_actions, commit_allocations_1,
- (void *)(uintptr_t)revert_p);
+ this->alloc_actions.traverse (commit_allocations_1,
+ (void *)(uintptr_t)revert_p);
+ this->alloc_actions.clear ();
}
+
+} // namespace GTM
diff --git a/libitm/alloc_c.c b/libitm/alloc_c.cc
index c66ee7900b6..641d915cfd1 100644
--- a/libitm/alloc_c.c
+++ b/libitm/alloc_c.cc
@@ -25,13 +25,16 @@
#include "libitm_i.h"
+using namespace GTM;
+
+
/* Wrap: malloc (size_t sz) */
void *
_ITM_malloc (size_t sz)
{
void *r = malloc (sz);
if (r)
- GTM_record_allocation (r, sz, free);
+ gtm_tx()->record_allocation (r, sz, free);
return r;
}
@@ -41,7 +44,7 @@ _ITM_calloc (size_t nm, size_t sz)
{
void *r = calloc (nm, sz);
if (r)
- GTM_record_allocation (r, nm*sz, free);
+ gtm_tx()->record_allocation (r, nm*sz, free);
return r;
}
@@ -49,12 +52,13 @@ _ITM_calloc (size_t nm, size_t sz)
void *
_ITM_realloc (void *ptr, size_t sz)
{
+ gtm_transaction *tx = gtm_tx();
void *r;
if (sz == 0)
{
/* If sz == 0, then realloc == free. */
if (ptr)
- GTM_forget_allocation (ptr, free);
+ tx->forget_allocation (ptr, free);
r = NULL;
}
else if (ptr == NULL)
@@ -62,17 +66,17 @@ _ITM_realloc (void *ptr, size_t sz)
/* If ptr == NULL, then realloc == malloc. */
r = malloc (sz);
if (r)
- GTM_record_allocation (r, sz, free);
+ tx->record_allocation (r, sz, free);
}
else if (ptr)
{
/* We may have recorded the size of the allocation earlier in
this transaction. If so, fine, we can reallocate. Otherwise
we're stuck and we'll have to go irrevokable. */
- size_t osz = GTM_get_allocation_size (ptr);
+ size_t osz = tx->get_allocation_size (ptr);
if (osz == 0)
{
- GTM_serialmode (false, true);
+ tx->serialirr_mode ();
return realloc (ptr, sz);
}
@@ -84,8 +88,8 @@ _ITM_realloc (void *ptr, size_t sz)
method is write-back, we have to be careful to use memory
from the cache if locks were taken. */
_ITM_memcpyRnWt (r, ptr, (sz < osz ? sz : osz));
- GTM_record_allocation (r, sz, free);
- GTM_forget_allocation (ptr, free);
+ tx->record_allocation (r, sz, free);
+ tx->forget_allocation (ptr, free);
}
}
return r;
@@ -96,5 +100,5 @@ void
_ITM_free (void *ptr)
{
if (ptr)
- GTM_forget_allocation (ptr, free);
+ gtm_tx()->forget_allocation (ptr, free);
}
diff --git a/libitm/alloc_cpp.c b/libitm/alloc_cpp.cc
index bbeb3e0d872..b5ff790b528 100644
--- a/libitm/alloc_cpp.c
+++ b/libitm/alloc_cpp.cc
@@ -24,9 +24,13 @@
#include "libitm_i.h"
+using namespace GTM;
+
/* Everything from libstdc++ is weak, to avoid requiring that library
to be linked into plain C applications using libitm.so. */
+extern "C" {
+
extern void *_Znwm (size_t) __attribute__((weak));
extern void _ZdlPv (void *) __attribute__((weak));
extern void *_Znam (size_t) __attribute__((weak));
@@ -62,7 +66,7 @@ _ZGTtnwm (size_t sz)
{
void *r = _Znwm (sz);
if (r)
- GTM_record_allocation (r, sz, _ZdlPv);
+ gtm_tx()->record_allocation (r, sz, _ZdlPv);
return r;
}
@@ -72,7 +76,7 @@ _ZGTtnwmRKSt9nothrow_t (size_t sz, c_nothrow_p nt)
{
void *r = _ZnwmRKSt9nothrow_t (sz, nt);
if (r)
- GTM_record_allocation (r, sz, del_opnt);
+ gtm_tx()->record_allocation (r, sz, del_opnt);
return r;
}
@@ -82,7 +86,7 @@ _ZGTtnam (size_t sz)
{
void *r = _Znam (sz);
if (r)
- GTM_record_allocation (r, sz, _ZdaPv);
+ gtm_tx()->record_allocation (r, sz, _ZdaPv);
return r;
}
@@ -92,7 +96,7 @@ _ZGTtnamRKSt9nothrow_t (size_t sz, c_nothrow_p nt)
{
void *r = _ZnamRKSt9nothrow_t (sz, nt);
if (r)
- GTM_record_allocation (r, sz, del_opvnt);
+ gtm_tx()->record_allocation (r, sz, del_opvnt);
return r;
}
@@ -101,7 +105,7 @@ void
_ZGTtdlPv (void *ptr)
{
if (ptr)
- GTM_forget_allocation (ptr, _ZdlPv);
+ gtm_tx()->forget_allocation (ptr, _ZdlPv);
}
/* Wrap: operator delete (void *ptr, const std::nothrow_t&) */
@@ -109,7 +113,7 @@ void
_ZGTtdlPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt UNUSED)
{
if (ptr)
- GTM_forget_allocation (ptr, del_opnt);
+ gtm_tx()->forget_allocation (ptr, del_opnt);
}
/* Wrap: operator delete[] (void *ptr) */
@@ -117,7 +121,7 @@ void
_ZGTtdaPv (void *ptr)
{
if (ptr)
- GTM_forget_allocation (ptr, _ZdaPv);
+ gtm_tx()->forget_allocation (ptr, _ZdaPv);
}
/* Wrap: operator delete[] (void *ptr, const std::nothrow_t&) */
@@ -125,5 +129,7 @@ void
_ZGTtdaPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt UNUSED)
{
if (ptr)
- GTM_forget_allocation (ptr, del_opvnt);
+ gtm_tx()->forget_allocation (ptr, del_opvnt);
}
+
+} // extern "C"
diff --git a/libitm/barrier.c b/libitm/barrier.c
deleted file mode 100644
index 805549b4461..00000000000
--- a/libitm/barrier.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright (C) 2008, 2009 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"
-
-
-#define ITM_READ(T, LOCK) \
-_ITM_TYPE_##T ITM_REGPARM _ITM_##LOCK##T(const _ITM_TYPE_##T *ptr) \
-{ \
- uintptr_t iptr = (uintptr_t) ptr; \
- uintptr_t iline = iptr & -CACHELINE_SIZE; \
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); \
- gtm_cacheline *line = gtm_disp()->LOCK (iline); \
- _ITM_TYPE_##T ret; \
- \
- if (STRICT_ALIGNMENT \
- ? (iofs & (sizeof (ret) - 1)) == 0 \
- : iofs + sizeof(ret) <= CACHELINE_SIZE) \
- { \
- return *(_ITM_TYPE_##T *)&line->b[iofs]; \
- } \
- else if (STRICT_ALIGNMENT && iofs + sizeof(ret) <= CACHELINE_SIZE) \
- { \
- memcpy (&ret, &line->b[iofs], sizeof (ret)); \
- } \
- else \
- { \
- uintptr_t ileft = CACHELINE_SIZE - iofs; \
- memcpy (&ret, &line->b[iofs], ileft); \
- line = gtm_disp()->LOCK (iline + CACHELINE_SIZE); \
- memcpy ((char *)&ret + ileft, line, sizeof(ret) - ileft); \
- } \
- return ret; \
-}
-
-#define ITM_WRITE(T, LOCK) \
-void ITM_REGPARM _ITM_##LOCK##T(_ITM_TYPE_##T *ptr, _ITM_TYPE_##T val) \
-{ \
- uintptr_t iptr = (uintptr_t) ptr; \
- uintptr_t iline = iptr & -CACHELINE_SIZE; \
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); \
- gtm_cacheline_mask m = ((gtm_cacheline_mask)1 << sizeof(val)) - 1; \
- gtm_cacheline_mask_pair pair = gtm_disp()->LOCK (iline); \
- \
- if (STRICT_ALIGNMENT \
- ? (iofs & (sizeof (val) - 1)) == 0 \
- : iofs + sizeof(val) <= CACHELINE_SIZE) \
- { \
- *(_ITM_TYPE_##T *)&pair.line->b[iofs] = val; \
- *pair.mask |= m << iofs; \
- } \
- else if (STRICT_ALIGNMENT && iofs + sizeof(val) <= CACHELINE_SIZE) \
- { \
- memcpy (&pair.line->b[iofs], &val, sizeof (val)); \
- *pair.mask |= m << iofs; \
- } \
- else \
- { \
- uintptr_t ileft = CACHELINE_SIZE - iofs; \
- memcpy (&pair.line->b[iofs], &val, ileft); \
- *pair.mask |= m << iofs; \
- pair = gtm_disp()->LOCK (iline + CACHELINE_SIZE); \
- memcpy (pair.line, (char *)&val + ileft, sizeof(val) - ileft); \
- *pair.mask |= m >> ileft; \
- } \
-}
-
-#define ITM_BARRIERS(T) \
- ITM_READ(T, R) \
- ITM_READ(T, RaR) \
- ITM_READ(T, RaW) \
- ITM_READ(T, RfW) \
- ITM_WRITE(T, W) \
- ITM_WRITE(T, WaR) \
- ITM_WRITE(T, WaW)
-
-ITM_BARRIERS(U1)
-ITM_BARRIERS(U2)
-ITM_BARRIERS(U4)
-ITM_BARRIERS(U8)
-ITM_BARRIERS(F)
-ITM_BARRIERS(D)
-ITM_BARRIERS(E)
-ITM_BARRIERS(CF)
-ITM_BARRIERS(CD)
-ITM_BARRIERS(CE)
diff --git a/libitm/config/alpha/target_i.h b/libitm/barrier.cc
index fae14007a3a..52e5a081d18 100644
--- a/libitm/config/alpha/target_i.h
+++ b/libitm/barrier.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008, 2009 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU Transactional Memory Library (libitm).
@@ -22,21 +22,16 @@
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
-
-static inline void
-cpu_relax (void)
-{
- __asm volatile ("" : : : "memory");
-}
-
-static inline void
-atomic_read_barrier (void)
-{
- __sync_synchronize ();
-}
-
-static inline void
-atomic_write_barrier (void)
-{
- __asm volatile ("wmb" : : : "memory");
-}
+#include "libitm_i.h"
+#include "barrier.tpl"
+
+ITM_BARRIERS(U1)
+ITM_BARRIERS(U2)
+ITM_BARRIERS(U4)
+ITM_BARRIERS(U8)
+ITM_BARRIERS(F)
+ITM_BARRIERS(D)
+ITM_BARRIERS(E)
+ITM_BARRIERS(CF)
+ITM_BARRIERS(CD)
+ITM_BARRIERS(CE)
diff --git a/libitm/barrier.tpl b/libitm/barrier.tpl
new file mode 100644
index 00000000000..c1b22026c6d
--- /dev/null
+++ b/libitm/barrier.tpl
@@ -0,0 +1,137 @@
+/* Copyright (C) 2008, 2009 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 "unaligned.h"
+
+namespace {
+
+using namespace GTM;
+
+template<typename T>
+T do_read (const T *ptr, gtm_dispatch::lock_type lock)
+{
+ gtm_dispatch *disp = gtm_disp();
+ uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr);
+ uintptr_t iline = iptr & -CACHELINE_SIZE;
+ uintptr_t iofs = iptr & (CACHELINE_SIZE - 1);
+ const gtm_cacheline *pline = reinterpret_cast<const gtm_cacheline *>(iline);
+ const gtm_cacheline *line = disp->read_lock(pline, lock);
+
+ ptr = reinterpret_cast<const T *>(&line->b[iofs]);
+
+ if (__builtin_expect (strict_alignment<T>::value
+ ? (iofs & (sizeof (T) - 1)) == 0
+ : iofs + sizeof(T) <= CACHELINE_SIZE, 1))
+ {
+ do_normal_load:
+ return *ptr;
+ }
+ else if (__builtin_expect (strict_alignment<T>::value
+ && iofs + sizeof(T) <= CACHELINE_SIZE, 1))
+ {
+ do_unaligned_load:
+ return unaligned_load<T>(ptr);
+ }
+ else
+ {
+ const gtm_cacheline *line2 = disp->read_lock(pline + 1, lock);
+
+ if (line2 == line + 1)
+ {
+ if (!strict_alignment<T>::value)
+ goto do_normal_load;
+ else
+ goto do_unaligned_load;
+ }
+ else
+ return unaligned_load2<T>(line, line2, iofs);
+ }
+}
+
+template<typename T>
+void do_write (T *ptr, T val, gtm_dispatch::lock_type lock)
+{
+ gtm_dispatch *disp = gtm_disp();
+ uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr);
+ uintptr_t iline = iptr & -CACHELINE_SIZE;
+ uintptr_t iofs = iptr & (CACHELINE_SIZE - 1);
+ gtm_cacheline *pline = reinterpret_cast<gtm_cacheline *>(iline);
+ gtm_cacheline_mask m = ((gtm_cacheline_mask)2 << (sizeof(T) - 1)) - 1;
+ gtm_dispatch::mask_pair pair = disp->write_lock(pline, lock);
+
+ ptr = reinterpret_cast<T *>(&pair.line->b[iofs]);
+
+ if (__builtin_expect (strict_alignment<T>::value
+ ? (iofs & (sizeof (val) - 1)) == 0
+ : iofs + sizeof(val) <= CACHELINE_SIZE, 1))
+ {
+ *pair.mask |= m << iofs;
+ do_normal_store:
+ *ptr = val;
+ }
+ else if (__builtin_expect (strict_alignment<T>::value
+ && iofs + sizeof(val) <= CACHELINE_SIZE, 1))
+ {
+ *pair.mask |= m << iofs;
+ do_unaligned_store:
+ unaligned_store<T>(ptr, val);
+ }
+ else
+ {
+ *pair.mask |= m << iofs;
+ gtm_dispatch::mask_pair pair2 = disp->write_lock(pline + 1, lock);
+
+ uintptr_t ileft = CACHELINE_SIZE - iofs;
+ *pair2.mask |= m >> ileft;
+
+ if (pair2.line == pair.line + 1)
+ {
+ if (!strict_alignment<T>::value)
+ goto do_normal_store;
+ else
+ goto do_unaligned_store;
+ }
+ else
+ unaligned_store2<T>(pair.line, pair2.line, iofs, val);
+ }
+}
+
+} /* anonymous namespace */
+
+#define ITM_READ(T, LOCK) \
+ _ITM_TYPE_##T ITM_REGPARM _ITM_##LOCK##T (const _ITM_TYPE_##T *ptr) \
+ { return do_read (ptr, gtm_dispatch::LOCK); }
+
+#define ITM_WRITE(T, LOCK) \
+ void ITM_REGPARM _ITM_##LOCK##T (_ITM_TYPE_##T *ptr, _ITM_TYPE_##T val) \
+ { do_write (ptr, val, gtm_dispatch::LOCK); }
+
+#define ITM_BARRIERS(T) \
+ ITM_READ(T, R) \
+ ITM_READ(T, RaR) \
+ ITM_READ(T, RaW) \
+ ITM_READ(T, RfW) \
+ ITM_WRITE(T, W) \
+ ITM_WRITE(T, WaR) \
+ ITM_WRITE(T, WaW)
diff --git a/libitm/beginend.c b/libitm/beginend.cc
index 3689aa02128..0ca0f6f7a25 100644
--- a/libitm/beginend.c
+++ b/libitm/beginend.cc
@@ -25,14 +25,16 @@
#include "libitm_i.h"
-__thread gtm_thread _gtm_thr;
-gtm_rwlock gtm_serial_lock;
+using namespace GTM;
-gtm_stmlock gtm_stmlock_array[LOCK_ARRAY_SIZE];
-gtm_version gtm_clock;
+__thread gtm_thread GTM::_gtm_thr;
+gtm_rwlock GTM::gtm_transaction::serial_lock;
+
+gtm_stmlock GTM::gtm_stmlock_array[LOCK_ARRAY_SIZE];
+gtm_version GTM::gtm_clock;
/* ??? Move elsewhere when we figure out library initialization. */
-uint64_t gtm_spin_count_var = 1000;
+uint64_t GTM::gtm_spin_count_var = 1000;
static _ITM_transactionId_t global_tid;
@@ -45,13 +47,14 @@ alloc_tx (void)
gtm_thread *thr = gtm_thr ();
if (thr->free_tx_count == 0)
- tx = malloc (sizeof (*tx));
+ tx = static_cast<gtm_transaction *>(xmalloc (sizeof (gtm_transaction)));
else
{
thr->free_tx_count--;
tx = thr->free_tx[thr->free_tx_idx];
- thr->free_tx_idx = (thr->free_tx_idx + 1) % MAX_FREE_TX;
+ thr->free_tx_idx = (thr->free_tx_idx + 1) % gtm_thread::MAX_FREE_TX;
}
+ memset (tx, 0, sizeof (*tx));
return tx;
}
@@ -65,11 +68,12 @@ static void
free_tx (gtm_transaction *tx)
{
gtm_thread *thr = gtm_thr ();
- unsigned idx = (thr->free_tx_idx + thr->free_tx_count) % MAX_FREE_TX;
+ unsigned idx
+ = (thr->free_tx_idx + thr->free_tx_count) % gtm_thread::MAX_FREE_TX;
- if (thr->free_tx_count == MAX_FREE_TX)
+ if (thr->free_tx_count == gtm_thread::MAX_FREE_TX)
{
- thr->free_tx_idx = (thr->free_tx_idx + 1) % MAX_FREE_TX;
+ thr->free_tx_idx = (thr->free_tx_idx + 1) % gtm_thread::MAX_FREE_TX;
free (thr->free_tx[idx]);
}
else
@@ -80,15 +84,15 @@ free_tx (gtm_transaction *tx)
uint32_t
-GTM_begin_transaction (uint32_t prop, const gtm_jmpbuf *jb)
+GTM::gtm_transaction::begin_transaction (uint32_t prop, const gtm_jmpbuf *jb)
{
gtm_transaction *tx;
- const gtm_dispatch *disp;
+ gtm_dispatch *disp;
+ uint32_t ret;
setup_gtm_thr ();
tx = alloc_tx ();
- memset (tx, 0, sizeof (*tx));
tx->prop = prop;
tx->prev = gtm_tx();
@@ -101,54 +105,63 @@ GTM_begin_transaction (uint32_t prop, const gtm_jmpbuf *jb)
if ((prop & pr_doesGoIrrevocable) || !(prop & pr_instrumentedCode))
{
- GTM_serialmode (true, true);
- return (prop & pr_uninstrumentedCode
- ? a_runUninstrumentedCode : a_runInstrumentedCode);
- }
+ serial_lock.write_lock ();
+
+ tx->state = (STATE_SERIAL | STATE_IRREVOCABLE);
+
+ disp = dispatch_serial ();
- /* ??? Probably want some environment variable to choose the default
- STM implementation once we have more than one implemented. */
- if (prop & pr_readOnly)
- disp = &dispatch_readonly;
+ ret = a_runUninstrumentedCode;
+ if ((prop & pr_multiwayCode) == pr_instrumentedCode)
+ ret = a_runInstrumentedCode;
+ }
else
- disp = &dispatch_wbetl;
- set_gtm_disp (disp);
- disp->init (true);
+ {
+ serial_lock.read_lock ();
+
+ // ??? Probably want some environment variable to choose the default
+ // STM implementation once we have more than one implemented.
+ if (prop & pr_readOnly)
+ disp = dispatch_readonly ();
+ else
+ disp = dispatch_wbetl ();
+
+ ret = a_runInstrumentedCode | a_saveLiveVariables;
+ }
- gtm_rwlock_read_lock (&gtm_serial_lock);
+ set_gtm_disp (disp);
- return a_runInstrumentedCode | a_saveLiveVariables;
+ return ret;
}
-static void
-GTM_rollback_transaction (void)
+void
+GTM::gtm_transaction::rollback ()
{
- gtm_transaction *tx;
-
gtm_disp()->rollback ();
- GTM_rollback_local ();
+ rollback_local ();
- tx = gtm_tx();
- GTM_free_actions (&tx->commit_actions);
- GTM_run_actions (&tx->undo_actions);
- GTM_commit_allocations (true);
+ free_actions (&this->commit_actions);
+ run_actions (&this->undo_actions);
+ commit_allocations (true);
+ revert_cpp_exceptions ();
- GTM_revert_cpp_exceptions ();
- if (tx->eh_in_flight)
+ if (this->eh_in_flight)
{
- _Unwind_DeleteException (tx->eh_in_flight);
- tx->eh_in_flight = NULL;
+ _Unwind_DeleteException ((_Unwind_Exception *) this->eh_in_flight);
+ this->eh_in_flight = NULL;
}
}
void ITM_REGPARM
_ITM_rollbackTransaction (void)
{
- assert ((gtm_tx()->prop & pr_hasNoAbort) == 0);
- assert ((gtm_tx()->state & STATE_ABORTING) == 0);
+ gtm_transaction *tx = gtm_tx();
+
+ assert ((tx->prop & pr_hasNoAbort) == 0);
+ assert ((tx->state & gtm_transaction::STATE_ABORTING) == 0);
- GTM_rollback_transaction ();
- gtm_tx()->state |= STATE_ABORTING;
+ tx->rollback ();
+ tx->state |= gtm_transaction::STATE_ABORTING;
}
void ITM_REGPARM
@@ -158,18 +171,18 @@ _ITM_abortTransaction (_ITM_abortReason reason)
assert (reason == userAbort);
assert ((tx->prop & pr_hasNoAbort) == 0);
- assert ((tx->state & STATE_ABORTING) == 0);
+ assert ((tx->state & gtm_transaction::STATE_ABORTING) == 0);
- if (tx->state & STATE_IRREVOKABLE)
+ if (tx->state & gtm_transaction::STATE_IRREVOCABLE)
abort ();
- GTM_rollback_transaction ();
+ tx->rollback ();
gtm_disp()->fini ();
- if (tx->state & STATE_SERIAL)
- gtm_rwlock_write_unlock (&gtm_serial_lock);
+ if (tx->state & gtm_transaction::STATE_SERIAL)
+ gtm_transaction::serial_lock.write_unlock ();
else
- gtm_rwlock_read_unlock (&gtm_serial_lock);
+ gtm_transaction::serial_lock.read_unlock ();
set_gtm_tx (tx->prev);
free_tx (tx);
@@ -177,30 +190,28 @@ _ITM_abortTransaction (_ITM_abortReason reason)
GTM_longjmp (&tx->jb, a_abortTransaction | a_restoreLiveVariables, tx->prop);
}
-static inline bool
-GTM_trycommit_transaction (void)
+bool
+GTM::gtm_transaction::trycommit ()
{
if (gtm_disp()->trycommit ())
{
- GTM_commit_local ();
- GTM_free_actions (&gtm_tx()->undo_actions);
- GTM_run_actions (&gtm_tx()->commit_actions);
- GTM_commit_allocations (false);
+ commit_local ();
+ free_actions (&this->undo_actions);
+ run_actions (&this->commit_actions);
+ commit_allocations (false);
return true;
}
return false;
}
-static bool
-GTM_trycommit_and_finalize_transaction (void)
+bool
+GTM::gtm_transaction::trycommit_and_finalize ()
{
- gtm_transaction *tx = gtm_tx();
-
- if ((tx->state & STATE_ABORTING) || GTM_trycommit_transaction ())
+ if ((this->state & gtm_transaction::STATE_ABORTING) || trycommit ())
{
gtm_disp()->fini ();
- set_gtm_tx (tx->prev);
- free_tx (tx);
+ set_gtm_tx (this->prev);
+ free_tx (this);
return true;
}
return false;
@@ -209,39 +220,42 @@ GTM_trycommit_and_finalize_transaction (void)
bool ITM_REGPARM
_ITM_tryCommitTransaction (void)
{
- assert ((gtm_tx()->state & STATE_ABORTING) == 0);
- return GTM_trycommit_transaction ();
+ gtm_transaction *tx = gtm_tx();
+ assert ((tx->state & gtm_transaction::STATE_ABORTING) == 0);
+ return tx->trycommit ();
}
void ITM_NORETURN
-GTM_restart_transaction (gtm_restart_reason r)
+GTM::gtm_transaction::restart (gtm_restart_reason r)
{
- gtm_transaction *tx = gtm_tx();
uint32_t actions;
- GTM_rollback_transaction ();
- GTM_decide_retry_strategy (r);
+ rollback ();
+ decide_retry_strategy (r);
actions = a_runInstrumentedCode | a_restoreLiveVariables;
- if ((tx->prop & pr_uninstrumentedCode) && (tx->state & STATE_IRREVOKABLE))
+ if ((this->prop & pr_uninstrumentedCode)
+ && (this->state & gtm_transaction::STATE_IRREVOCABLE))
actions = a_runUninstrumentedCode | a_restoreLiveVariables;
- GTM_longjmp (&tx->jb, actions, tx->prop);
+ GTM_longjmp (&this->jb, actions, this->prop);
}
void ITM_REGPARM
_ITM_commitTransaction(void)
{
- if (!GTM_trycommit_and_finalize_transaction ())
- GTM_restart_transaction (RESTART_VALIDATE_COMMIT);
+ gtm_transaction *tx = gtm_tx();
+ if (!tx->trycommit_and_finalize ())
+ tx->restart (RESTART_VALIDATE_COMMIT);
}
void ITM_REGPARM
_ITM_commitTransactionEH(void *exc_ptr)
{
- if (!GTM_trycommit_and_finalize_transaction ())
+ gtm_transaction *tx = gtm_tx();
+ if (!tx->trycommit_and_finalize ())
{
- gtm_tx()->eh_in_flight = exc_ptr;
- GTM_restart_transaction (RESTART_VALIDATE_COMMIT);
+ tx->eh_in_flight = exc_ptr;
+ tx->restart (RESTART_VALIDATE_COMMIT);
}
}
diff --git a/libitm/clone.c b/libitm/clone.cc
index 46e9f4f24ca..25078205d7f 100644
--- a/libitm/clone.c
+++ b/libitm/clone.cc
@@ -24,6 +24,7 @@
#include "libitm_i.h"
+using namespace GTM;
static gtm_rwlock table_lock;
@@ -34,24 +35,24 @@ struct clone_entry
struct clone_table
{
- struct clone_entry *table;
+ clone_entry *table;
size_t size;
- struct clone_table *next;
+ clone_table *next;
};
-static struct clone_table *all_tables;
+static clone_table *all_tables;
static void *
-GTM_find_clone (void *ptr)
+find_clone (void *ptr)
{
- struct clone_table *table;
+ clone_table *table;
void *ret = NULL;
- gtm_rwlock_read_lock (&table_lock);
+ table_lock.read_lock ();
for (table = all_tables; table ; table = table->next)
{
- struct clone_entry *t = table->table;
+ clone_entry *t = table->table;
size_t lo = 0, hi = table->size, i;
/* Quick test for whether PTR is present in this table. */
@@ -79,7 +80,7 @@ GTM_find_clone (void *ptr)
}
found:
- gtm_rwlock_read_unlock (&table_lock);
+ table_lock.read_unlock ();
return ret;
}
@@ -87,18 +88,18 @@ GTM_find_clone (void *ptr)
void * ITM_REGPARM
_ITM_getTMCloneOrIrrevokable (void *ptr)
{
- void *ret = GTM_find_clone (ptr);
+ void *ret = find_clone (ptr);
if (ret)
return ret;
- GTM_serialmode (false, true);
+ gtm_tx()->serialirr_mode ();
return ptr;
}
void * ITM_REGPARM
_ITM_getTMCloneSafe (void *ptr)
{
- void *ret = GTM_find_clone (ptr);
+ void *ret = find_clone (ptr);
if (ret == NULL)
abort ();
return ret;
@@ -107,8 +108,8 @@ _ITM_getTMCloneSafe (void *ptr)
static int
clone_entry_compare (const void *a, const void *b)
{
- const struct clone_entry *aa = (const struct clone_entry *)a;
- const struct clone_entry *bb = (const struct clone_entry *)b;
+ const clone_entry *aa = (const clone_entry *)a;
+ const clone_entry *bb = (const clone_entry *)b;
if (aa->orig < bb->orig)
return -1;
@@ -119,14 +120,16 @@ clone_entry_compare (const void *a, const void *b)
}
void
-_ITM_registerTMCloneTable (void *t, size_t size)
+_ITM_registerTMCloneTable (void *xent, size_t size)
{
- struct clone_table *old, *table = malloc (sizeof (*table));
+ clone_entry *ent = static_cast<clone_entry *>(xent);
+ clone_table *old, *table;
- table->table = t;
+ table = (clone_table *) xmalloc (sizeof (clone_table));
+ table->table = ent;
table->size = size;
- qsort (t, size, sizeof (struct clone_entry), clone_entry_compare);
+ qsort (ent, size, sizeof (clone_entry), clone_entry_compare);
old = all_tables;
do
@@ -138,15 +141,21 @@ _ITM_registerTMCloneTable (void *t, size_t size)
}
void
-_ITM_deregisterTMCloneTable (void *t)
+_ITM_deregisterTMCloneTable (void *xent)
{
- struct clone_table **pprev = &all_tables;
+ clone_entry *ent = static_cast<clone_entry *>(xent);
+ clone_table **pprev = &all_tables;
+ clone_table *tab;
- gtm_rwlock_write_lock (&table_lock);
+ table_lock.write_lock ();
- for (pprev = &all_tables; (*pprev)->table != t; pprev = &(*pprev)->next)
+ for (pprev = &all_tables;
+ tab = *pprev, tab->table != ent;
+ pprev = &tab->next)
continue;
- *pprev = (*pprev)->next;
+ *pprev = tab->next;
- gtm_rwlock_write_unlock (&table_lock);
+ table_lock.write_unlock ();
+
+ free (tab);
}
diff --git a/libitm/config.h.in b/libitm/config.h.in
index 24bf065483b..574b5776985 100644
--- a/libitm/config.h.in
+++ b/libitm/config.h.in
@@ -1,5 +1,8 @@
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
/* Define to 1 if the target supports __attribute__((alias(...))). */
#undef HAVE_ATTRIBUTE_ALIAS
@@ -132,3 +135,19 @@
/* Version number of package */
#undef VERSION
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
+#ifndef WORDS_BIGENDIAN
+#define WORDS_BIGENDIAN 0
+#endif
diff --git a/libitm/config/alpha/cacheline.h b/libitm/config/alpha/cacheline.h
new file mode 100644
index 00000000000..02d3a69ae5a
--- /dev/null
+++ b/libitm/config/alpha/cacheline.h
@@ -0,0 +1,122 @@
+/* Copyright (C) 2009 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
+
+#ifdef __alpha_bwx__
+# include "config/generic/cacheline.h"
+#else
+// If we don't have byte-word stores, then we'll never be able to
+// adjust *all* of the byte loads/stores to be truely atomic. So
+// only guarantee 4-byte aligned values atomicly stored, exactly
+// like the native system. Use byte zap instructions to accelerate
+// sub-word masked stores.
+
+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)];
+
+ // Store S into D, but only the bytes specified by M.
+ static void store_mask(uint32_t *d, uint32_t s, uint8_t m);
+ static void store_mask(uint64_t *d, uint64_t s, uint8_t m);
+
+ // Copy S to D, but only the bytes specified by M.
+ static void copy_mask (gtm_cacheline * __restrict d,
+ const gtm_cacheline * __restrict s,
+ gtm_cacheline_mask m);
+
+ // A write barrier to emit after (a series of) copy_mask.
+ static void copy_mask_wb () { atomic_write_barrier(); }
+};
+
+inline void ALWAYS_INLINE
+gtm_cacheline::store_mask (uint32_t *d, uint32_t s, uint8_t m)
+{
+ const uint8_t tm = (1 << sizeof(uint32_t)) - 1;
+
+ m &= tm;
+ if (__builtin_expect (m, tm))
+ {
+ if (__builtin_expect (m == tm, 1))
+ *d = s;
+ else
+ *d = __builtin_alpha_zap (*d, m) | __builtin_alpha_zapnot (s, m);
+ }
+}
+
+inline void ALWAYS_INLINE
+gtm_cacheline::store_mask (uint64_t *d, uint64_t s, uint8_t m)
+{
+ if (__builtin_expect (m, 0xff))
+ {
+ if (__builtin_expect (m == 0xff, 1))
+ *d = s;
+ else
+ {
+ typedef uint32_t *p32 __attribute__((may_alias));
+ p32 d32 = reinterpret_cast<p32>(d);
+
+ if ((m & 0x0f) == 0x0f)
+ {
+ d32[0] = s;
+ m &= 0xf0;
+ }
+ else if ((m & 0xf0) == 0xf0)
+ {
+ d32[1] = s >> 32;
+ m &= 0x0f;
+ }
+
+ if (m)
+ *d = __builtin_alpha_zap (*d, m) | __builtin_alpha_zapnot (s, m);
+ }
+ }
+}
+
+} // namespace GTM
+
+#endif // __alpha_bwx__
+#endif // LIBITM_ALPHA_CACHELINE_H
diff --git a/libitm/config/alpha/copymask.c b/libitm/config/alpha/copymask.c
deleted file mode 100644
index 179bcc38466..00000000000
--- a/libitm/config/alpha/copymask.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/* Copyright (C) 2009 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"
-
-
-#if ALLOW_UNMASKED_STORES || !defined(__alpha_bwx__)
-/* If we're allowing unmasked stores, then the ZAP/ZAPNOT instructions
- provide a builtin version of the default bit_to_byte_mask operation.
-
- If we don't allow unmasked stores, and we don't have byte-word stores,
- then we *must* implement the copymask with ll/sc instructions. However,
- these are slow enough that we'd rather implement this feature with the
- generic store avoidance algorithm if possible. */
-
-static void __attribute__((always_inline))
-copy_mask_w (gtm_word * __restrict d,
- const gtm_word * __restrict s,
- gtm_cacheline_mask m)
-{
- gtm_cacheline_mask tm = (1 << sizeof (gtm_word)) - 1;
-
- if (__builtin_expect (m & tm, tm))
- {
- if (__builtin_expect ((m & tm) == tm, 1))
- *d = *s;
- else if (ALLOW_UNMASKED_STORES)
- {
- *d = (__builtin_alpha_zap (*d, m)
- | __builtin_alpha_zapnot (*s, m));
- }
- else
- {
- gtm_word t;
- asm ("\n0:\t"
- "ldq_l %[t], %[d]\n\t"
- "zap %[t], %[m], %[t]\n\t"
- "or %[s], %[t], %[t]\n\t"
- "stq_c %[t], %[d]\n\t"
- "beq %[t], 0b"
- : [d] "+m" (*d), [t] "=&r" (t)
- : [m] "r" (m), [s] "r" (__builtin_alpha_zapnot (*s, m)));
- }
- }
-}
-
-void
-gtm_cacheline_copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m)
-{
- const size_t n = sizeof (gtm_word);
- size_t i;
-
- if (m == (gtm_cacheline_mask)-1)
- {
- gtm_cacheline_copy (d, s);
- return;
- }
- if (__builtin_expect (m == 0, 0))
- return;
-
- for (i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n)
- copy_mask_w (&d->w[i], &s->w[i], m);
-}
-
-#else
-# include "../../copymask.c"
-#endif /* ALLOW_UNMASKED_STORES || !defined(__alpha_bwx__) */
diff --git a/libitm/config/alpha/target.h b/libitm/config/alpha/target.h
index e516f3384d7..2c0f448bceb 100644
--- a/libitm/config/alpha/target.h
+++ b/libitm/config/alpha/target.h
@@ -22,6 +22,8 @@
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;
@@ -30,15 +32,26 @@ typedef struct gtm_jmpbuf
unsigned long f[8];
} gtm_jmpbuf;
-/* The "cacheline" as defined by the STM need not be the same as the
- cacheline defined by the processor. It ought to be big enough for
- any of the basic types to be stored (aligned) in one line. It ought
- to be small enough for efficient manipulation of the modification mask. */
-#define CACHELINE_SIZE 64
-
-/* Alpha requires strict alignment for the basic types. */
-#define STRICT_ALIGNMENT 1
-
/* Alpha generally uses a fixed page size of 8K. */
#define PAGE_SIZE 8192
#define FIXED_PAGE_SIZE 1
+
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("" : : : "memory");
+}
+
+static inline void
+atomic_read_barrier (void)
+{
+ __sync_synchronize ();
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+ __asm volatile ("wmb" : : : "memory");
+}
+
+} // namespace GTM
diff --git a/libitm/config/alpha/unaligned.h b/libitm/config/alpha/unaligned.h
new file mode 100644
index 00000000000..6d68f050c06
--- /dev/null
+++ b/libitm/config/alpha/unaligned.h
@@ -0,0 +1,118 @@
+/* Copyright (C) 2009 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_UNALIGNED_H
+#define LIBITM_ALPHA_UNALIGNED_H 1
+
+#define HAVE_ARCH_UNALIGNED_LOAD2_U2 1
+#define HAVE_ARCH_UNALIGNED_LOAD2_U4 1
+#define HAVE_ARCH_UNALIGNED_LOAD2_U8 1
+
+#ifndef __alpha_bwx__
+#define HAVE_ARCH_UNALIGNED_STORE2_U2 1
+#endif
+#define HAVE_ARCH_UNALIGNED_STORE2_U4 1
+#define HAVE_ARCH_UNALIGNED_STORE2_U8 1
+
+#include "config/generic/unaligned.h"
+
+namespace GTM HIDDEN {
+
+template<>
+inline uint16_t ALWAYS_INLINE
+unaligned_load2<uint16_t>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
+ uint64_t v2 = c2->u64[0];
+
+ return __builtin_alpha_extwl (v1, ofs) | __builtin_alpha_extwh (v2, ofs);
+}
+
+template<>
+inline uint32_t ALWAYS_INLINE
+unaligned_load2<uint32_t>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
+ uint64_t v2 = c2->u64[0];
+
+ return __builtin_alpha_extll (v1, ofs) + __builtin_alpha_extlh (v2, ofs);
+}
+
+template<>
+inline uint64_t ALWAYS_INLINE
+unaligned_load2<uint64_t>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
+ uint64_t v2 = c2->u64[0];
+
+ return __builtin_alpha_extql (v1, ofs) | __builtin_alpha_extqh (v2, ofs);
+}
+
+#ifndef __alpha_bwx__
+template<>
+inline void
+unaligned_store2<uint16_t>(gtm_cacheline *c1, gtm_cacheline *c2,
+ size_t ofs, uint16_t val)
+{
+ uint32_t vl = (uint32_t)val << 24, vh = val >> 8;
+
+ gtm_cacheline::store_mask (&c1->u32[CACHELINE_SIZE / 4 - 1], vl, 4);
+ gtm_cacheline::store_mask (&c2->u32[0], vh, 1);
+}
+#endif
+
+template<>
+inline void
+unaligned_store2<uint32_t>(gtm_cacheline *c1, gtm_cacheline *c2,
+ size_t ofs, uint32_t val)
+{
+ uint64_t vl = __builtin_alpha_insll (val, ofs);
+ uint64_t ml = __builtin_alpha_insll (~0u, ofs);
+ uint64_t vh = __builtin_alpha_inslh (val, ofs);
+ uint64_t mh = __builtin_alpha_inslh (~0u, ofs);
+
+ gtm_cacheline::store_mask (&c1->u64[CACHELINE_SIZE / 8 - 1], vl, ml);
+ gtm_cacheline::store_mask (&c2->u64[0], vh, mh);
+}
+
+template<>
+inline void
+unaligned_store2<uint64_t>(gtm_cacheline *c1, gtm_cacheline *c2,
+ size_t ofs, uint64_t val)
+{
+ uint64_t vl = __builtin_alpha_insql (val, ofs);
+ uint64_t ml = __builtin_alpha_insql (~0u, ofs);
+ uint64_t vh = __builtin_alpha_insqh (val, ofs);
+ uint64_t mh = __builtin_alpha_insqh (~0u, ofs);
+
+ gtm_cacheline::store_mask (&c1->u64[CACHELINE_SIZE / 8 - 1], vl, ml);
+ gtm_cacheline::store_mask (&c2->u64[0], vh, mh);
+}
+
+} // namespace GTM
+
+#endif // LIBITM_ALPHA_UNALIGNED_H
diff --git a/libitm/retry.c b/libitm/config/generic/cacheline.cc
index c89cd684a62..1fb5676fa97 100644
--- a/libitm/retry.c
+++ b/libitm/config/generic/cacheline.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2009 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU Transactional Memory Library (libitm).
@@ -25,31 +25,25 @@
#include "libitm_i.h"
+namespace GTM HIDDEN {
+
void
-GTM_decide_retry_strategy (gtm_restart_reason r)
+gtm_cacheline::copy_mask (gtm_cacheline * __restrict d,
+ const gtm_cacheline * __restrict s,
+ gtm_cacheline_mask m)
{
- struct gtm_transaction *tx = gtm_tx();
- const struct gtm_dispatch *disp;
-
- tx->restart_reason[r]++;
- tx->restart_total++;
+ const size_t n = sizeof (gtm_word);
- if (r == RESTART_NOT_READONLY)
+ if (m == (gtm_cacheline_mask) -1)
{
- assert ((tx->prop & pr_readOnly) == 0);
- disp = gtm_disp ();
- if (disp == &dispatch_readonly)
- {
- disp->fini ();
- disp = &dispatch_wbetl;
- disp->init (true);
- return;
- }
+ *d = *s;
+ return;
}
- if (tx->state & STATE_SERIAL)
- ;
- else if (tx->restart_total > 100)
- GTM_serialmode (false, false);
- else
- gtm_disp()->init (false);
+ if (__builtin_expect (m == 0, 0))
+ return;
+
+ for (size_t i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n)
+ store_mask (&d->w[i], s->w[i], m);
}
+
+} // namespace GTM
diff --git a/libitm/config/generic/cacheline.h b/libitm/config/generic/cacheline.h
new file mode 100644
index 00000000000..14c08c215d3
--- /dev/null
+++ b/libitm/config/generic/cacheline.h
@@ -0,0 +1,107 @@
+/* Copyright (C) 2009 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)];
+
+ // Store S into D, but only the bytes specified by M.
+ template<typename T> static void store_mask (T *d, T s, uint8_t m);
+
+ // Copy S to D, but only the bytes specified by M.
+ static void copy_mask (gtm_cacheline * __restrict d,
+ const gtm_cacheline * __restrict s,
+ gtm_cacheline_mask m);
+
+ // A write barrier to emit after (a series of) copy_mask.
+ // When we're emitting non-temporal stores, the normal strong
+ // ordering of the machine doesn't apply.
+ static void copy_mask_wb () { atomic_write_barrier(); }
+};
+
+template<typename T>
+inline void
+gtm_cacheline::store_mask (T *d, T s, uint8_t m)
+{
+ const uint8_t tm = (1 << sizeof(T)) - 1;
+
+ if (__builtin_expect (m & tm, tm))
+ {
+ if (__builtin_expect ((m & tm) == tm, 1))
+ *d = s;
+ else
+ {
+ const int half = sizeof(T) / 2;
+ typedef typename sized_integral<half>::type half_t;
+ half_t *dhalf = reinterpret_cast<half_t *>(d);
+ half_t s1, s2;
+
+ if (WORDS_BIGENDIAN)
+ s1 = s >> half*8, s2 = s;
+ else
+ s1 = s, s2 = s >> half*8;
+
+ store_mask (dhalf, s1, m);
+ store_mask (dhalf + 1, s2, m >> half);
+ }
+ }
+}
+
+template<>
+inline void ALWAYS_INLINE
+gtm_cacheline::store_mask<uint8_t> (uint8_t *d, uint8_t s, uint8_t m)
+{
+ if (m & 1)
+ *d = s;
+}
+
+} // namespace GTM
+
+#endif // LIBITM_CACHELINE_H
diff --git a/libitm/config/generic/cachepage.h b/libitm/config/generic/cachepage.h
new file mode 100644
index 00000000000..7febbe882c5
--- /dev/null
+++ b/libitm/config/generic/cachepage.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2009 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_CACHEPAGE_H
+#define LIBITM_CACHEPAGE_H 1
+
+namespace GTM HIDDEN {
+
+// A "page" worth of saved cachelines plus modification masks. This
+// arrangement is intended to minimize the overhead of alignment. The
+// PAGE_SIZE defined by the target must be a constant for this to work,
+// which means that this definition may not be the same as the real
+// system page size. An additional define of FIXED_PAGE_SIZE by the
+// target indicates that PAGE_SIZE exactly matches the system page size.
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE 4096
+#endif
+
+struct gtm_cacheline_page
+{
+ static const size_t LINES
+ = ((PAGE_SIZE - sizeof(gtm_cacheline_page *))
+ / (CACHELINE_SIZE + sizeof(gtm_cacheline_mask)));
+
+ gtm_cacheline lines[LINES] __attribute__((aligned(PAGE_SIZE)));
+ gtm_cacheline_mask masks[LINES];
+ gtm_cacheline_page *prev;
+
+ static gtm_cacheline_page *
+ page_for_line (gtm_cacheline *c)
+ {
+ return (gtm_cacheline_page *)((uintptr_t)c & -PAGE_SIZE);
+ }
+
+ gtm_cacheline_mask *
+ mask_for_line (gtm_cacheline *c)
+ {
+ size_t index = c - &this->lines[0];
+ return &this->masks[index];
+ }
+
+ static gtm_cacheline_mask *
+ mask_for_page_line (gtm_cacheline *c)
+ {
+ gtm_cacheline_page *p = page_for_line (c);
+ return p->mask_for_line (c);
+ }
+
+ static void *operator new (size_t);
+ static void operator delete (void *);
+};
+
+} // namespace GTM
+
+#endif // LIBITM_CACHEPAGE_H
diff --git a/libitm/config/generic/tls.h b/libitm/config/generic/tls.h
new file mode 100644
index 00000000000..d6c2bc8b0a9
--- /dev/null
+++ b/libitm/config/generic/tls.h
@@ -0,0 +1,90 @@
+/* Copyright (C) 2008, 2009 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 {
+
+// All thread-local data required by the entire library.
+struct gtm_thread
+{
+#ifndef HAVE_ARCH_GTM_THREAD_TX
+ // The currently active transaction. Elided if the target provides
+ // some efficient mechanism for storing this.
+ gtm_transaction *tx;
+#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.
+ gtm_dispatch *disp;
+#endif
+
+ // The maximum number of free gtm_transaction structs to be kept.
+ // This number must be greater than 1 in order for transaction abort
+ // to be handled properly.
+ static const unsigned MAX_FREE_TX = 8;
+
+ // A queue of free gtm_transaction structs.
+ gtm_transaction *free_tx[MAX_FREE_TX];
+ unsigned free_tx_idx, free_tx_count;
+
+ // The value returned by _ITM_getThreadnum to identify this thread.
+ // ??? At present, this is densely allocated beginning with 1 and
+ // we don't bother filling in this value until it is requested.
+ // Which means that the value returned is, as far as the user is
+ // concerned, essentially arbitrary. We wouldn't need this at all
+ // if we knew that pthread_t is integral and fits into an int.
+ // ??? Consider using gettid on Linux w/ NPTL. At least that would
+ // be a value meaningful to the user.
+ int thread_num;
+};
+
+// Don't access this variable directly; use the functions below.
+extern __thread gtm_thread _gtm_thr;
+
+#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 void setup_gtm_thr(void) { }
+static inline gtm_thread *gtm_thr(void) { return &_gtm_thr; }
+#endif
+
+#ifndef HAVE_ARCH_GTM_THREAD_TX
+// If the target does not provide optimized access to the currently
+// active transaction, simply access via GTM_THR.
+static inline gtm_transaction * gtm_tx(void) { return gtm_thr()->tx; }
+static inline void set_gtm_tx(gtm_transaction *x) { gtm_thr()->tx = 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 gtm_dispatch * gtm_disp(void) { return gtm_thr()->disp; }
+static inline void set_gtm_disp(gtm_dispatch *x) { gtm_thr()->disp = x; }
+#endif
+
+} // namespace GTM
+
+#endif // LIBITM_TLS_H
diff --git a/libitm/config/generic/unaligned.h b/libitm/config/generic/unaligned.h
new file mode 100644
index 00000000000..66295f1a08c
--- /dev/null
+++ b/libitm/config/generic/unaligned.h
@@ -0,0 +1,228 @@
+/* Copyright (C) 2009 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_UNALIGNED_H
+#define LIBITM_UNALIGNED_H 1
+
+namespace GTM HIDDEN {
+
+#ifndef STRICT_ALIGNMENT
+#define STRICT_ALIGNMENT 1
+#endif
+
+// A type trait for whether type T requires strict alignment.
+// The generic types are assumed to all be the same; specializations
+// for target-specific types should be done in config/cpu/unaligned.h.
+template<typename T>
+ struct strict_alignment
+ : public std::integral_constant<bool, STRICT_ALIGNMENT>
+ { };
+
+// A helper template for accessing an integral type the same size as T
+template<typename T>
+ struct make_integral
+ : public sized_integral<sizeof(T)>
+ { };
+
+// A helper class for accessing T as an unaligned value.
+template<typename T>
+struct __attribute__((packed)) unaligned_helper
+ { T x; };
+
+// A helper class for view-converting T as an integer.
+template<typename T>
+union view_convert_helper
+{
+ typedef T type;
+ typedef make_integral<T> itype;
+
+ type t;
+ itype i;
+};
+
+// Generate an unaligned load sequence.
+// The compiler knows how to do this for any specific type.
+template<typename T>
+inline T ALWAYS_INLINE
+unaligned_load(const void *t)
+{
+ typedef unaligned_helper<T> UT;
+ const UT *ut = reinterpret_cast<const UT *>(t);
+ return ut->x;
+}
+
+// Generate an unaligned store sequence.
+template<typename T>
+inline void ALWAYS_INLINE
+unaligned_store(void *t, T val)
+{
+ typedef unaligned_helper<T> UT;
+ UT *ut = reinterpret_cast<UT *>(t);
+ ut->x = val;
+}
+
+// Generate an unaligned load from two different cachelines.
+// It is known that OFS + SIZEOF(T) > CACHELINE_SIZE.
+template<typename T>
+inline T ALWAYS_INLINE
+unaligned_load2(const gtm_cacheline *c1, const gtm_cacheline *c2, size_t ofs)
+{
+ size_t left = CACHELINE_SIZE - ofs;
+ T ret;
+
+ memcpy (&ret, &c1->b[ofs], left);
+ memcpy ((char *)&ret + ofs, c2, sizeof(T) - left);
+
+ return ret;
+}
+
+// Generate an unaligned store into two different cachelines.
+// It is known that OFS + SIZEOF(T) > CACHELINE_SIZE.
+template<typename T>
+inline void ALWAYS_INLINE
+unaligned_store2(gtm_cacheline *c1, gtm_cacheline *c2, size_t ofs, T val)
+{
+ size_t left = CACHELINE_SIZE - ofs;
+ memcpy (&c1->b[ofs], &val, left);
+ memcpy (c2, (char *)&val + left, sizeof(T) - left);
+}
+
+#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U2
+template<>
+inline uint16_t ALWAYS_INLINE
+unaligned_load2<uint16_t>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ uint16_t v1 = c1->b[CACHELINE_SIZE - 1];
+ uint16_t v2 = c2->b[0];
+
+ if (WORDS_BIGENDIAN)
+ return v1 << 8 | v2;
+ else
+ return v2 << 8 | v1;
+}
+#endif
+
+#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U4
+template<>
+inline uint32_t ALWAYS_INLINE
+unaligned_load2<uint32_t>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ uint32_t v1 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1];
+ uint32_t v2 = c2->u32[0];
+ int s2 = (ofs & (sizeof(uint32_t) - 1)) * 8;
+ int s1 = sizeof(uint32_t) * 8 - s2;
+
+ if (WORDS_BIGENDIAN)
+ return v1 << s2 | v2 >> s1;
+ else
+ return v2 << s2 | v1 >> s1;
+}
+#endif
+
+#ifndef HAVE_ARCH_UNALIGNED_LOAD2_U8
+template<>
+inline uint64_t ALWAYS_INLINE
+unaligned_load2<uint64_t>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ uint64_t v1 = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
+ uint64_t v2 = c2->u64[0];
+ int s2 = (ofs & (sizeof(uint64_t) - 1)) * 8;
+ int s1 = sizeof(uint64_t) * 8 - s2;
+
+ if (WORDS_BIGENDIAN)
+ return v1 << s2 | v2 >> s1;
+ else
+ return v2 << s2 | v1 >> s1;
+}
+#endif
+
+template<>
+inline float ALWAYS_INLINE
+unaligned_load2<float>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ typedef view_convert_helper<float> VC; VC vc;
+ vc.i = unaligned_load2<VC::itype>(c1, c2, ofs);
+ return vc.t;
+}
+
+template<>
+inline double ALWAYS_INLINE
+unaligned_load2<double>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ typedef view_convert_helper<double> VC; VC vc;
+ vc.i = unaligned_load2<VC::itype>(c1, c2, ofs);
+ return vc.t;
+}
+
+#ifndef HAVE_ARCH_UNALIGNED_STORE2_U2
+template<>
+inline void ALWAYS_INLINE
+unaligned_store2<uint16_t>(gtm_cacheline *c1, gtm_cacheline *c2,
+ size_t ofs, uint16_t val)
+{
+ uint8_t vl = val, vh = val >> 8;
+
+ if (WORDS_BIGENDIAN)
+ {
+ c1->b[CACHELINE_SIZE - 1] = vh;
+ c2->b[0] = vl;
+ }
+ else
+ {
+ c1->b[CACHELINE_SIZE - 1] = vl;
+ c2->b[0] = vh;
+ }
+}
+#endif
+
+#if 0
+#ifndef HAVE_ARCH_UNALIGNED_STORE2_U4
+template<>
+inline void ALWAYS_INLINE
+unaligned_store2<uint32_t>(gtm_cacheline *c1, gtm_cacheline *c2,
+ size_t ofs, uint32_t val)
+{
+ // ??? We could reuse the store_mask stuff here.
+}
+#endif
+
+template<>
+inline void ALWAYS_INLINE
+unaligned_store2<float>(gtm_cacheline *c1, gtm_cacheline *c2,
+ size_t ofs, float val)
+{
+ typedef view_convert_helper<float> VC; VC vc;
+ vc.t = val;
+ unaligned_store2(c1, c2, ofs, vc.i);
+}
+#endif
+
+} // namespace GTM
+
+#endif // LIBITM_UNALIGNED_H
diff --git a/libitm/config/linux/futex.c b/libitm/config/linux/futex.cc
index 2c122ad917c..f70144996ba 100644
--- a/libitm/config/linux/futex.c
+++ b/libitm/config/linux/futex.cc
@@ -28,6 +28,7 @@
#include "futex.h"
#include <errno.h>
+namespace GTM HIDDEN {
#define FUTEX_WAIT 0
#define FUTEX_WAKE 1
@@ -55,7 +56,16 @@ futex_wait (int *addr, int val)
{
gtm_futex_wait = FUTEX_WAIT;
gtm_futex_wake = FUTEX_WAKE;
- sys_futex0 (addr, FUTEX_WAIT, val);
+ 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));
}
}
@@ -68,6 +78,10 @@ futex_wake (int *addr, int count)
{
gtm_futex_wait = FUTEX_WAIT;
gtm_futex_wake = FUTEX_WAKE;
- sys_futex0 (addr, FUTEX_WAKE, count);
+ res = sys_futex0 (addr, FUTEX_WAKE, count);
}
+ if (__builtin_expect (res < 0, 0))
+ GTM_fatal ("futex failed (%s)", strerror(-res));
}
+
+} // namespace GTM
diff --git a/libitm/config/linux/futex.h b/libitm/config/linux/futex.h
index c45c2ca1314..7275dbf5fd1 100644
--- a/libitm/config/linux/futex.h
+++ b/libitm/config/linux/futex.h
@@ -27,17 +27,13 @@
#ifndef GTM_FUTEX_H
#define GTM_FUTEX_H 1
-#ifdef HAVE_ATTRIBUTE_VISIBILITY
-# pragma GCC visibility push(hidden)
-#endif
+namespace GTM HIDDEN {
#include "futex_bits.h"
extern void futex_wait (int *addr, int val);
extern void futex_wake (int *addr, int count);
-#ifdef HAVE_ATTRIBUTE_VISIBILITY
-# pragma GCC visibility pop
-#endif
+}
#endif /* GTM_FUTEX_H */
diff --git a/libitm/config/linux/rwlock.c b/libitm/config/linux/rwlock.c
deleted file mode 100644
index 2f0b752566f..00000000000
--- a/libitm/config/linux/rwlock.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/* Copyright (C) 2008, 2009 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 <limits.h>
-#include "libitm_i.h"
-#include "futex.h"
-
-
-#define EZ(X) __builtin_expect((X), 0)
-
-
-/* Lock the summary bit on LOCK. Return the contents of the summary word
- (without the summary lock bit included). */
-
-static int
-rwlock_lock_summary (gtm_rwlock *lock)
-{
- int o;
-
- restart:
- o = __sync_fetch_and_or (&lock->summary, RWLOCK_S_LOCK);
- if (EZ (o & RWLOCK_S_LOCK))
- {
- do
- cpu_relax ();
- while (lock->summary & RWLOCK_S_LOCK);
- goto restart;
- }
-
- return o;
-}
-
-
-/* Acquire a RW lock for reading. */
-
-void
-gtm_rwlock_read_lock (gtm_rwlock *lock)
-{
- int o, n;
-
- while (1)
- {
- o = rwlock_lock_summary (lock);
-
- /* If there is an active or waiting writer, then new readers
- must wait. Increment the waiting reader count, then wait
- on the reader queue. */
- if (EZ (o & (RWLOCK_A_WRITER | RWLOCK_W_WRITER | RWLOCK_RW_UPGRADE)))
- {
- n = ++lock->w_readers;
- atomic_write_barrier ();
- lock->summary = o | RWLOCK_W_READER;
- futex_wait (&lock->w_readers, n);
- continue;
- }
-
- /* Otherwise, we may become a reader. */
- ++lock->a_readers;
- atomic_write_barrier ();
- lock->summary = o | RWLOCK_A_READER;
- return;
- }
-}
-
-
-/* Acquire a RW lock for writing. */
-
-void
-gtm_rwlock_write_lock (gtm_rwlock *lock)
-{
- int o, n;
-
- restart:
- o = lock->summary;
-
- /* If anyone is manipulating the summary lock, the rest of the
- data structure is volatile. */
- if (EZ (o & RWLOCK_S_LOCK))
- {
- cpu_relax ();
- goto restart;
- }
-
- /* If there is an active reader or active writer, then new writers
- must wait. Increment the waiting writer count, then wait
- on the writer queue. */
- if (EZ (o & (RWLOCK_A_WRITER | RWLOCK_A_READER | RWLOCK_RW_UPGRADE)))
- {
- /* Grab the summary lock. We'll need it for incrementing
- the waiting reader. */
- n = o | RWLOCK_S_LOCK;
- if (!__sync_bool_compare_and_swap (&lock->summary, o, n))
- goto restart;
-
- n = ++lock->w_writers;
- atomic_write_barrier ();
- lock->summary = o | RWLOCK_W_WRITER;
- futex_wait (&lock->w_writers, n);
- goto restart;
- }
-
- /* Otherwise, may become a writer. */
- n = o | RWLOCK_A_WRITER;
- if (EZ (!__sync_bool_compare_and_swap (&lock->summary, o, n)))
- goto restart;
-}
-
-
-/* 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. */
-
-bool
-gtm_rwlock_write_upgrade (gtm_rwlock *lock)
-{
- int o, n;
-
- restart:
- o = lock->summary;
-
- /* If anyone is manipulating the summary lock, the rest of the
- data structure is volatile. */
- if (EZ (o & RWLOCK_S_LOCK))
- {
- cpu_relax ();
- goto restart;
- }
-
- /* If there's already someone trying to upgrade, then we fail. */
- if (EZ (o & RWLOCK_RW_UPGRADE))
- return false;
-
- /* Grab the summary lock. We'll need it for manipulating the
- active reader count or the waiting writer count. */
- n = o | RWLOCK_S_LOCK;
- if (EZ (!__sync_bool_compare_and_swap (&lock->summary, o, n)))
- goto restart;
-
- /* If there are more active readers, then we have to wait. */
- if (--lock->a_readers > 0)
- {
- atomic_write_barrier ();
- o |= RWLOCK_RW_UPGRADE;
- lock->summary = o;
- do
- {
- futex_wait (&lock->summary, o);
- o = lock->summary;
- }
- while (o & RWLOCK_A_READER);
- }
-
- atomic_write_barrier ();
- o &= ~(RWLOCK_A_READER | RWLOCK_RW_UPGRADE);
- o |= RWLOCK_A_WRITER;
- lock->summary = o;
- return true;
-}
-
-
-/* Release a RW lock from reading. */
-
-void
-gtm_rwlock_read_unlock (gtm_rwlock *lock)
-{
- int o;
-
- o = rwlock_lock_summary (lock);
-
- /* If there are still active readers, nothing else to do. */
- if (--lock->a_readers > 0)
- {
- atomic_write_barrier ();
- lock->summary = o;
- return;
- }
- o &= ~RWLOCK_A_READER;
-
- /* If there is a waiting upgrade, wake it. */
- if (EZ (o & RWLOCK_RW_UPGRADE))
- {
- atomic_write_barrier ();
- lock->summary = o;
- futex_wake (&lock->summary, 1);
- return;
- }
-
- /* If there is a waiting writer, wake it. */
- if (EZ (o & RWLOCK_W_WRITER))
- {
- if (--lock->w_writers == 0)
- o &= ~RWLOCK_W_WRITER;
- atomic_write_barrier ();
- lock->summary = o;
- futex_wake (&lock->w_writers, 1);
- return;
- }
-
- atomic_write_barrier ();
- lock->summary = o;
-}
-
-
-/* Release a RW lock from writing. */
-
-void
-gtm_rwlock_write_unlock (gtm_rwlock *lock)
-{
- int o;
-
- o = rwlock_lock_summary (lock);
- o &= ~RWLOCK_A_WRITER;
-
- /* If there is a waiting writer, wake it. */
- if (EZ (o & RWLOCK_W_WRITER))
- {
- if (--lock->w_writers == 0)
- o &= ~RWLOCK_W_WRITER;
- atomic_write_barrier ();
- lock->summary = o;
- futex_wake (&lock->w_writers, 1);
- return;
- }
-
- /* If there are waiting readers, wake them. */
- if (EZ (o & RWLOCK_W_READER))
- {
- lock->w_readers = 0;
- atomic_write_barrier ();
- lock->summary = o & ~RWLOCK_W_READER;
- futex_wake (&lock->w_readers, INT_MAX);
- return;
- }
-
- lock->summary = o;
-}
diff --git a/libitm/config/linux/rwlock.cc b/libitm/config/linux/rwlock.cc
new file mode 100644
index 00000000000..d5379c864b4
--- /dev/null
+++ b/libitm/config/linux/rwlock.cc
@@ -0,0 +1,246 @@
+/* Copyright (C) 2008, 2009 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 <climits>
+#include "libitm_i.h"
+#include "futex.h"
+
+namespace GTM HIDDEN {
+
+// Lock the summary bit on LOCK. Return the contents of the summary
+// word (without the summary lock bit included).
+
+int
+gtm_rwlock::lock_summary ()
+{
+ int o;
+
+ restart:
+ o = __sync_fetch_and_or (&this->summary, s_lock);
+ if (unlikely (o & s_lock))
+ {
+ do
+ cpu_relax ();
+ while (this->summary & s_lock);
+ goto restart;
+ }
+
+ return o;
+}
+
+
+// Acquire a RW lock for reading.
+
+void
+gtm_rwlock::read_lock ()
+{
+ restart:
+ int o = lock_summary ();
+
+ // If there is an active or waiting writer, then new readers must wait.
+ // Increment the waiting reader count, then wait on the reader queue.
+ if (unlikely (o & (a_writer | w_writer | rw_upgrade)))
+ {
+ int n = ++this->w_readers;
+ atomic_write_barrier ();
+ this->summary = o | w_reader;
+ futex_wait (&this->w_readers, n);
+ goto restart;
+ }
+
+ // Otherwise, we may become a reader.
+ ++this->a_readers;
+ atomic_write_barrier ();
+ this->summary = o | a_reader;
+}
+
+
+// Acquire a RW lock for writing.
+
+void
+gtm_rwlock::write_lock ()
+{
+ int o, n;
+
+ restart:
+ o = this->summary;
+
+ // If anyone is manipulating the summary lock, the rest of the
+ // data structure is volatile.
+ if (unlikely (o & s_lock))
+ {
+ cpu_relax ();
+ goto restart;
+ }
+
+ // If there is an active reader or active writer, then new writers must wait.
+ // Increment the waiting writer count, then wait on the writer queue.
+ if (unlikely (o & (a_writer | a_reader | rw_upgrade)))
+ {
+ // Grab the summary lock. We'll need it for incrementing
+ // the waiting reader.
+ n = o | s_lock;
+ if (!__sync_bool_compare_and_swap (&this->summary, o, n))
+ goto restart;
+
+ n = ++this->w_writers;
+ atomic_write_barrier ();
+ this->summary = o | w_writer;
+ futex_wait (&this->w_writers, n);
+ goto restart;
+ }
+
+ // Otherwise, we may become a writer.
+ n = o | a_writer;
+ if (unlikely (!__sync_bool_compare_and_swap (&this->summary, o, n)))
+ goto restart;
+}
+
+
+// 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 ()
+{
+ int o, n;
+
+ restart:
+ o = this->summary;
+
+ // If anyone is manipulating the summary lock, the rest of the
+ // data structure is volatile.
+ if (unlikely (o & s_lock))
+ {
+ cpu_relax ();
+ goto restart;
+ }
+
+ // If there's already someone trying to upgrade, then we fail.
+ if (unlikely (o & rw_upgrade))
+ return false;
+
+ // Grab the summary lock. We'll need it for manipulating the
+ // active reader count or the waiting writer count.
+ n = o | s_lock;
+ if (unlikely (!__sync_bool_compare_and_swap (&this->summary, o, n)))
+ goto restart;
+
+ // If there are more active readers, then we have to wait.
+ if (--this->a_readers > 0)
+ {
+ atomic_write_barrier ();
+ o |= rw_upgrade;
+ this->summary = o;
+ do
+ {
+ futex_wait (&this->summary, o);
+ o = this->summary;
+ }
+ while (o & a_reader);
+ }
+
+ atomic_write_barrier ();
+ o &= ~(a_reader | rw_upgrade);
+ o |= a_writer;
+ this->summary = o;
+ return true;
+}
+
+
+// Release a RW lock from reading.
+
+void
+gtm_rwlock::read_unlock ()
+{
+ int o = lock_summary ();
+
+ // If there are still active readers, nothing else to do.
+ if (--this->a_readers > 0)
+ {
+ atomic_write_barrier ();
+ this->summary = o;
+ return;
+ }
+ o &= ~a_reader;
+
+ // If there is a waiting upgrade, wake it.
+ if (unlikely (o & rw_upgrade))
+ {
+ atomic_write_barrier ();
+ this->summary = o;
+ futex_wake (&this->summary, 1);
+ return;
+ }
+
+ // If there is a waiting writer, wake it.
+ if (unlikely (o & w_writer))
+ {
+ if (--this->w_writers == 0)
+ o &= ~w_writer;
+ atomic_write_barrier ();
+ this->summary = o;
+ futex_wake (&this->w_writers, 1);
+ return;
+ }
+
+ atomic_write_barrier ();
+ this->summary = o;
+}
+
+
+// Release a RW lock from writing.
+
+void
+gtm_rwlock::write_unlock ()
+{
+ int o = lock_summary ();
+ o &= ~a_writer;
+
+ // If there is a waiting writer, wake it.
+ if (unlikely (o & w_writer))
+ {
+ if (--this->w_writers == 0)
+ o &= ~w_writer;
+ atomic_write_barrier ();
+ this->summary = o;
+ futex_wake (&this->w_writers, 1);
+ return;
+ }
+
+ // If there are waiting readers, wake them.
+ if (unlikely (o & w_reader))
+ {
+ this->w_readers = 0;
+ atomic_write_barrier ();
+ this->summary = o & ~w_reader;
+ futex_wake (&this->w_readers, INT_MAX);
+ return;
+ }
+
+ this->summary = o;
+}
+
+} // namespace GTM
diff --git a/libitm/config/linux/rwlock.h b/libitm/config/linux/rwlock.h
index d969a407e6c..1a8104e78f2 100644
--- a/libitm/config/linux/rwlock.h
+++ b/libitm/config/linux/rwlock.h
@@ -25,26 +25,48 @@
#ifndef GTM_RWLOCK_H
#define GTM_RWLOCK_H
-/* The read-write summary definition. */
+namespace GTM HIDDEN {
-#define RWLOCK_S_LOCK 1
-#define RWLOCK_A_WRITER 2
-#define RWLOCK_W_WRITER 4
-#define RWLOCK_A_READER 8
-#define RWLOCK_W_READER 16
-#define RWLOCK_RW_UPGRADE 32
+// This datastructure is similar to the 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).
+//
+// In this implementation, rw upgrade is given highest priority access,
+// and writers are given priority over readers.
-typedef struct {
+class gtm_rwlock
+{
+ private:
+ // A collection of bits that may be set in SUMMARY:
+ static const int s_lock = 1; // The strucure as a whole is locked.
+ static const int a_writer = 2; // An active writer.
+ static const int w_writer = 4; // The w_writers field != 0
+ static const int a_reader = 8; // The a_readers field != 0
+ static const int w_reader = 16; // The w_readers field != 0
+ static const int rw_upgrade = 32; // A reader waiting for upgrade.
+
+ // All fields must be "int", since they're all given to the futex syscall.
int summary;
int a_readers;
int w_readers;
int w_writers;
-} gtm_rwlock;
-extern void gtm_rwlock_read_lock (gtm_rwlock *);
-extern void gtm_rwlock_write_lock (gtm_rwlock *);
-extern bool gtm_rwlock_write_upgrade (gtm_rwlock *);
-extern void gtm_rwlock_read_unlock (gtm_rwlock *);
-extern void gtm_rwlock_write_unlock (gtm_rwlock *);
+ int lock_summary ();
+
+ public:
+ // ??? Uncomment if we have non-static users or if constexpr is supported.
+ // gtm_rwlock() : summary(0), a_readers(0), w_readers(0), w_writers(0) { }
+
+ void read_lock ();
+ void read_unlock ();
+
+ void write_lock ();
+ void write_unlock ();
+
+ bool write_upgrade ();
+};
+
+} // namespace GTM
-#endif /* GTM_RWLOCK_H */
+#endif // GTM_RWLOCK_H
diff --git a/libitm/config/linux/x86/tls.h b/libitm/config/linux/x86/tls.h
new file mode 100644
index 00000000000..df0e5977c8c
--- /dev/null
+++ b/libitm/config/linux/x86/tls.h
@@ -0,0 +1,84 @@
+/* Copyright (C) 2009 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/>. */
+
+#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10)
+/* Use slots in the TCB head rather than __thread lookups.
+ GLIBC has reserved words 10 through 15 for TM. */
+# define HAVE_ARCH_GTM_THREAD 1
+# define HAVE_ARCH_GTM_THREAD_TX 1
+# define HAVE_ARCH_GTM_THREAD_DISP 1
+
+# include "config/generic/tls.h"
+
+namespace GTM HIDDEN {
+
+# ifdef __LP64__
+# define SEG_READ(OFS) "movq\t%%fs:(" #OFS "*8),%0"
+# define SEG_WRITE(OFS) "movq\t%0,%%fs:(" #OFS "*8)"
+# else
+# define SEG_READ(OFS) "movl\t%%gs:(" #OFS "*4),%0"
+# define SEG_WRITE(OFS) "movl\t%0,%%gs:(" #OFS "*4)"
+# endif
+
+static inline struct gtm_thread *gtm_thr(void)
+{
+ struct gtm_thread *r;
+ asm (SEG_READ(10) : "=r"(r));
+ return r;
+}
+
+static inline void setup_gtm_thr(void)
+{
+ if (gtm_thr() == NULL)
+ asm volatile (SEG_WRITE(10) : : "r"(&_gtm_thr));
+}
+
+static inline struct gtm_transaction * gtm_tx(void)
+{
+ struct gtm_transaction *r;
+ asm (SEG_READ(11) : "=r"(r));
+ return r;
+}
+
+static inline void set_gtm_tx(struct gtm_transaction *x)
+{
+ asm volatile (SEG_WRITE(11) : : "r"(x));
+}
+
+static inline struct gtm_dispatch *gtm_disp(void)
+{
+ struct gtm_dispatch *r;
+ asm (SEG_READ(12) : "=r"(r));
+ return r;
+}
+
+static inline void set_gtm_disp(struct gtm_dispatch *x)
+{
+ asm volatile (SEG_WRITE(12) : : "r"(x));
+}
+
+} // namespace GTM
+#else
+# include "config/generic/tls.h"
+#endif /* >= GLIBC 2.10 */
diff --git a/libitm/config/posix/page.c b/libitm/config/posix/cachepage.cc
index 43b840366c0..9888ef5028c 100644
--- a/libitm/config/posix/page.c
+++ b/libitm/config/posix/cachepage.cc
@@ -24,6 +24,10 @@
#include "libitm_i.h"
+//
+// We have three possibilities for alloction: mmap, memalign, posix_memalign
+//
+
#if defined(HAVE_MMAP_ANON) || defined(HAVE_MMAP_DEV_ZERO)
#include <sys/mman.h>
#include <fcntl.h>
@@ -32,8 +36,7 @@
#include <malloc.h>
#endif
-
-static gtm_cacheline_page *free_pages;
+namespace GTM HIDDEN {
#if defined(HAVE_MMAP_ANON)
# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
@@ -50,7 +53,8 @@ static int dev_zero = -1;
#if defined(HAVE_MMAP_ANON) || defined(HAVE_MMAP_DEV_ZERO)
/* If we get here, we've already opened /dev/zero and verified that
PAGE_SIZE is valid for the system. */
-static gtm_cacheline_page * UNUSED
+static gtm_cacheline_page * alloc_mmap (void) UNUSED;
+static gtm_cacheline_page *
alloc_mmap (void)
{
gtm_cacheline_page *r;
@@ -131,12 +135,15 @@ init_alloc_page (void)
# error "No aligned memory allocation method"
#endif
+static gtm_cacheline_page *free_pages;
-gtm_cacheline_page *
-GTM_page_alloc (void)
+void *
+gtm_cacheline_page::operator new (size_t size)
{
- gtm_cacheline_page *r = free_pages;
+ assert (size == sizeof (gtm_cacheline_page));
+ assert (size <= PAGE_SIZE);
+ gtm_cacheline_page *r = free_pages;
restart:
if (r)
{
@@ -155,12 +162,20 @@ GTM_page_alloc (void)
}
void
-GTM_page_release (gtm_cacheline_page *head, gtm_cacheline_page *tail)
+gtm_cacheline_page::operator delete (void *xhead)
{
- gtm_cacheline_page *n, *p = free_pages;
+ gtm_cacheline_page *head = static_cast<gtm_cacheline_page *>(xhead);
+ gtm_cacheline_page *tail, *n, *p;
+
+ if (head == 0)
+ return;
- /* ??? We should eventually free some of these. */
+ /* ??? We should eventually really free some of these. */
+ for (tail = head; tail->prev != 0; tail = tail->prev)
+ continue;
+
+ p = free_pages;
restart:
tail->prev = p;
n = __sync_val_compare_and_swap (&free_pages, p, head);
@@ -170,3 +185,5 @@ GTM_page_release (gtm_cacheline_page *head, gtm_cacheline_page *tail)
goto restart;
}
}
+
+} // namespace GTM
diff --git a/libitm/config/posix/rwlock.cc b/libitm/config/posix/rwlock.cc
new file mode 100644
index 00000000000..069eec257f7
--- /dev/null
+++ b/libitm/config/posix/rwlock.cc
@@ -0,0 +1,189 @@
+/* Copyright (C) 2008, 2009 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_upgrade (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);
+ pthread_cond_destroy (&this->c_upgrade);
+}
+
+// Acquire a RW lock for reading.
+
+void
+gtm_rwlock::read_lock ()
+{
+ pthread_mutex_lock (&this->mutex);
+
+ unsigned int sum = this->summary;
+
+ // If there is a waiting upgrade, or an active writer, we must wait.
+ while (sum & (w_upgrade | a_writer | w_writer))
+ {
+ this->summary = sum | w_reader;
+ this->w_readers++;
+ pthread_cond_wait (&this->c_readers, &this->mutex);
+ sum = this->summary;
+ if (--this->w_readers == 0)
+ sum &= ~w_reader;
+ }
+
+ // Otherwise we can acquire the lock for read.
+ this->summary = sum | a_reader;
+ this->a_readers++;
+
+ pthread_mutex_unlock(&this->mutex);
+}
+
+
+// Acquire a RW lock for writing.
+
+void
+gtm_rwlock::write_lock ()
+{
+ pthread_mutex_lock (&this->mutex);
+
+ unsigned int sum = this->summary;
+
+ // If there is a waiting upgrade, or an active reader or writer, wait.
+ while (sum & (w_upgrade | a_writer | a_reader))
+ {
+ this->summary = sum | w_writer;
+ this->w_writers++;
+ pthread_cond_wait (&this->c_writers, &this->mutex);
+ sum = this->summary;
+ if (--this->w_writers == 0)
+ sum &= ~w_writer;
+ }
+
+ // Otherwise we can acquire the lock for write.
+ this->summary = sum | a_writer;
+
+ pthread_mutex_unlock(&this->mutex);
+}
+
+
+// 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 ()
+{
+ pthread_mutex_lock (&this->mutex);
+
+ unsigned int sum = this->summary;
+
+ // If there's already someone trying to upgrade, then we fail.
+ if (unlikely (sum & w_upgrade))
+ {
+ pthread_mutex_unlock (&this->mutex);
+ return false;
+ }
+
+ // If there are more active readers, then we have to wait.
+ if (--this->a_readers > 0)
+ {
+ this->summary = sum | w_upgrade;
+ pthread_cond_wait (&this->c_upgrade, &this->mutex);
+ sum = this->summary & ~w_upgrade;
+ // We only return from upgrade when we've got it; don't loop.
+ assert ((sum & (a_reader | a_writer)) == 0);
+ }
+
+ // Otherwise we can upgrade to writer.
+ this->summary = sum | a_writer;
+
+ pthread_mutex_unlock (&this->mutex);
+ return true;
+}
+
+
+// Release a RW lock from reading.
+
+void
+gtm_rwlock::read_unlock ()
+{
+ pthread_mutex_lock (&this->mutex);
+
+ // If there are no more active readers, we may need to wake someone.
+ if (--this->a_readers == 0)
+ {
+ unsigned int sum = this->summary;
+ this->summary = sum & ~a_reader;
+
+ // If there is a waiting upgrade, wake it.
+ if (unlikely (sum & w_upgrade))
+ pthread_cond_signal (&this->c_upgrade);
+
+ // If there is a waiting writer, wake it.
+ else if (unlikely (sum & w_writer))
+ pthread_cond_signal (&this->c_writers);
+ }
+
+ 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;
+ this->summary = sum & ~a_writer;
+
+ // 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/libitm/config/posix/rwlock.h b/libitm/config/posix/rwlock.h
new file mode 100644
index 00000000000..85544455da8
--- /dev/null
+++ b/libitm/config/posix/rwlock.h
@@ -0,0 +1,73 @@
+/* Copyright (C) 2009 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>
+
+namespace GTM HIDDEN {
+
+// This datastructure is similar to the 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).
+//
+// In this implementation, rw upgrade is given highest priority access,
+// and writers are given priority over readers.
+
+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
+ pthread_cond_t c_upgrade; // An upgrader waits here
+
+ static const unsigned w_upgrade = 1; // A reader waiting for upgrade
+ static const unsigned a_writer = 2; // An active writer.
+ static const unsigned w_writer = 4; // The w_writers field != 0
+ static const unsigned a_reader = 8; // The a_readers field != 0
+ static const unsigned w_reader = 16; // The w_readers field != 0
+
+ unsigned int summary; // Bitmask of the above.
+ unsigned int a_readers; // Nr active readers
+ unsigned int w_readers; // Nr waiting readers
+ unsigned int w_writers; // Nr waiting writers
+
+ public:
+ gtm_rwlock();
+ ~gtm_rwlock();
+
+ void read_lock ();
+ void read_unlock ();
+
+ void write_lock ();
+ void write_unlock ();
+
+ bool write_upgrade ();
+};
+
+} // namespace GTM
+
+#endif // GTM_RWLOCK_H
diff --git a/libitm/config/x86/cacheline.cc b/libitm/config/x86/cacheline.cc
new file mode 100644
index 00000000000..631b11abefd
--- /dev/null
+++ b/libitm/config/x86/cacheline.cc
@@ -0,0 +1,73 @@
+/* Copyright (C) 2009 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 {
+
+uint32_t const gtm_bit_to_byte_mask[16] =
+{
+ 0x00000000,
+ 0x000000ff,
+ 0x0000ff00,
+ 0x0000ffff,
+ 0x00ff0000,
+ 0x00ff00ff,
+ 0x00ffff00,
+ 0x00ffffff,
+ 0xff000000,
+ 0xff0000ff,
+ 0xff00ff00,
+ 0xff00ffff,
+ 0xffff0000,
+ 0xffff00ff,
+ 0xffffff00,
+ 0xffffffff
+};
+
+#ifdef __SSE2__
+# define MEMBER m128i
+#else
+# define MEMBER w
+#endif
+
+void
+gtm_cacheline::copy_mask (gtm_cacheline * __restrict d,
+ const gtm_cacheline * __restrict s,
+ gtm_cacheline_mask m)
+{
+ if (m == (gtm_cacheline_mask)-1)
+ {
+ *d = *s;
+ return;
+ }
+ if (__builtin_expect (m == 0, 0))
+ return;
+
+ size_t n = sizeof(d->MEMBER[0]);
+ for (size_t i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n)
+ store_mask (&d->MEMBER[i], s->MEMBER[i], m);
+}
+
+} // namespace GTM
diff --git a/libitm/config/x86/cacheline.h b/libitm/config/x86/cacheline.h
new file mode 100644
index 00000000000..24902f47296
--- /dev/null
+++ b/libitm/config/x86/cacheline.h
@@ -0,0 +1,242 @@
+/* Copyright (C) 2009 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;
+
+extern uint32_t const gtm_bit_to_byte_mask[16];
+
+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
+
+ // Store S into D, but only the bytes specified by M.
+ static void store_mask (uint32_t *d, uint32_t s, uint8_t m);
+ static void store_mask (uint64_t *d, uint64_t s, uint8_t m);
+#ifdef __SSE2__
+ static void store_mask (__m128i *d, __m128i s, uint16_t m);
+#endif
+
+ // Copy S to D, but only the bytes specified by M.
+ static void copy_mask (gtm_cacheline * __restrict d,
+ const gtm_cacheline * __restrict s,
+ gtm_cacheline_mask m);
+
+ // A write barrier to emit after (a series of) copy_mask.
+ // When we're emitting non-temporal stores, the normal strong
+ // ordering of the machine doesn't apply.
+ static void copy_mask_wb ();
+
+#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
+};
+
+inline void
+gtm_cacheline::copy_mask_wb ()
+{
+#ifdef __SSE2__
+ _mm_sfence ();
+#endif
+}
+
+#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;
+}
+#endif
+
+// ??? Support masked integer stores more efficiently with an unlocked cmpxchg
+// insn. My reasoning is that while we write to locations that we do not wish
+// to modify, we do it in an uninterruptable insn, and so we either truely
+// write back the original data or the insn fails -- unlike with a
+// load/and/or/write sequence which can be interrupted either by a kernel
+// task switch or an unlucky cacheline steal by another processor. Avoiding
+// the LOCK prefix improves performance by a factor of 10, and we don't need
+// the memory barrier semantics implied by that prefix.
+
+inline void ALWAYS_INLINE
+gtm_cacheline::store_mask (uint32_t *d, uint32_t s, uint8_t m)
+{
+ gtm_cacheline_mask tm = (1 << sizeof (s)) - 1;
+ if (__builtin_expect (m & tm, tm))
+ {
+ if (__builtin_expect ((m & tm) == tm, 1))
+ *d = s;
+ else
+ {
+ gtm_cacheline_mask bm = gtm_bit_to_byte_mask[m & 15];
+ gtm_word n, o = *d;
+
+ __asm("\n0:\t"
+ "mov %[o], %[n]\n\t"
+ "and %[m], %[n]\n\t"
+ "or %[s], %[n]\n\t"
+ "cmpxchg %[n], %[d]\n\t"
+ "jnz,pn 0b"
+ : [d] "+m"(*d), [n] "=&r" (n), [o] "+a"(o)
+ : [s] "r" (s & bm), [m] "r" (~bm));
+ }
+ }
+}
+
+inline void ALWAYS_INLINE
+gtm_cacheline::store_mask (uint64_t *d, uint64_t s, uint8_t m)
+{
+ gtm_cacheline_mask tm = (1 << sizeof (s)) - 1;
+ if (__builtin_expect (m & tm, tm))
+ {
+ if (__builtin_expect ((m & tm) == tm, 1))
+ *d = s;
+ else
+ {
+#ifdef __x86_64__
+ uint32_t bl = gtm_bit_to_byte_mask[m & 15];
+ uint32_t bh = gtm_bit_to_byte_mask[(m >> 4) & 15];
+ gtm_cacheline_mask bm = bl | ((gtm_cacheline_mask)bh << 31 << 1);
+ uint64_t n, o = *d;
+ __asm("\n0:\t"
+ "mov %[o], %[n]\n\t"
+ "and %[m], %[n]\n\t"
+ "or %[s], %[n]\n\t"
+ "cmpxchg %[n], %[d]\n\t"
+ "jnz,pn 0b"
+ : [d] "+m"(*d), [n] "=&r" (n), [o] "+a"(o)
+ : [s] "r" (s & bm), [m] "r" (~bm));
+#else
+ /* ??? While it's possible to perform this operation with
+ cmpxchg8b, the sequence requires all 7 general registers
+ and thus cannot be performed with -fPIC. Don't even try. */
+ uint32_t *d32 = reinterpret_cast<uint32_t *>(d);
+ store_mask (d32, s, m);
+ store_mask (d32 + 1, s >> 32, m >> 4);
+#endif
+ }
+ }
+}
+
+#ifdef __SSE2__
+inline void ALWAYS_INLINE
+gtm_cacheline::store_mask (__m128i *d, __m128i s, uint16_t m)
+{
+ if (__builtin_expect (m == 0, 0))
+ return;
+ if (__builtin_expect (m == 0xffff, 1))
+ *d = s;
+ else
+ {
+ __m128i bm0, bm1, bm2, bm3;
+ bm0 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4;
+ bm1 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4;
+ bm2 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4;
+ bm3 = _mm_set_epi32 (0, 0, 0, gtm_bit_to_byte_mask[m & 15]); m >>= 4;
+ bm0 = _mm_unpacklo_epi32 (bm0, bm1);
+ bm2 = _mm_unpacklo_epi32 (bm2, bm3);
+ bm0 = _mm_unpacklo_epi64 (bm0, bm2);
+
+ _mm_maskmoveu_si128 (s, bm0, (char *)d);
+ }
+}
+#endif // SSE2
+
+} // namespace GTM
+
+#endif // LIBITM_CACHELINE_H
diff --git a/libitm/config/x86/copymask.c b/libitm/config/x86/copymask.c
deleted file mode 100644
index 9cabbe6a753..00000000000
--- a/libitm/config/x86/copymask.c
+++ /dev/null
@@ -1,187 +0,0 @@
-/* Copyright (C) 2009 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"
-
-
-static uint32_t const bit_to_byte_mask[16] =
-{
- 0x00000000,
- 0x000000ff,
- 0x0000ff00,
- 0x0000ffff,
- 0x00ff0000,
- 0x00ff00ff,
- 0x00ffff00,
- 0x00ffffff,
- 0xff000000,
- 0xff0000ff,
- 0xff00ff00,
- 0xff00ffff,
- 0xffff0000,
- 0xffff00ff,
- 0xffffff00,
- 0xffffffff
-};
-
-#ifdef __SSE2__
-
-void
-gtm_cacheline_copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m)
-{
- int i;
-
- if (m == (gtm_cacheline_mask)-1)
- {
- gtm_cacheline_copy (d, s);
- return;
- }
- if (__builtin_expect (m == 0, 0))
- return;
-
- for (i = 0; i < CACHELINE_SIZE / 16; ++i)
- {
- gtm_cacheline_mask m16 = m & 0xffff;
- if (__builtin_expect (m16 == 0, 0))
- goto skip16;
- if (__builtin_expect (m16 == 0xffff, 1))
- {
- d->m128i[i] = s->m128i[i];
- skip16:
- m >>= 16;
- }
- else
- {
- __m128i bm0, bm1, bm2, bm3;
- bm0 = _mm_set_epi32 (0, 0, 0, bit_to_byte_mask[m & 15]); m >>= 4;
- bm1 = _mm_set_epi32 (0, 0, 0, bit_to_byte_mask[m & 15]); m >>= 4;
- bm2 = _mm_set_epi32 (0, 0, 0, bit_to_byte_mask[m & 15]); m >>= 4;
- bm3 = _mm_set_epi32 (0, 0, 0, bit_to_byte_mask[m & 15]); m >>= 4;
- bm0 = _mm_unpacklo_epi32 (bm0, bm1);
- bm2 = _mm_unpacklo_epi32 (bm2, bm3);
- bm0 = _mm_unpacklo_epi64 (bm0, bm2);
-
- if (ALLOW_UNMASKED_STORES)
- d->m128i[i] = (d->m128i[i] & ~bm0) | (s->m128i[i] & bm0);
- else
- _mm_maskmoveu_si128 (s->m128i[i], bm0, (char *)&d->m128i[i]);
- }
- }
-}
-
-#else
-/* ??? If we don't have SSE2, I believe we can honor !ALLOW_UNMASKED_STORES
- more efficiently with an unlocked cmpxchg insn. My reasoning is that
- while we write to locations that we do not wish to modify, we do it in
- an uninterruptable insn, and so we either truely write back the original
- data or the insn fails -- unlike with a load/and/or/write sequence which
- can be interrupted either by a kernel task switch or an unlucky cacheline
- steal by another processor. Avoiding the LOCK prefix improves performance
- by a factor of 10, and we don't need the memory barrier semantics
- implied by that prefix. */
-
-static void __attribute__((always_inline))
-copy_mask_w (gtm_word * __restrict d,
- const gtm_word * __restrict s,
- gtm_cacheline_mask m)
-{
- gtm_cacheline_mask tm = (1 << sizeof (gtm_word)) - 1;
-
- if (__builtin_expect (m & tm, tm))
- {
- if (__builtin_expect ((m & tm) == tm, 1))
- *d = *s;
- else if (sizeof (gtm_word) == 4)
- {
- gtm_cacheline_mask bm = bit_to_byte_mask[m & 15];
-
- if (ALLOW_UNMASKED_STORES)
- *d = (*d & ~bm) | (*s & bm);
- else
- {
- gtm_word n, o = *d;
- asm ("\n0:\t"
- "mov %[o], %[n]\n\t"
- "and %[m], %[n]\n\t"
- "or %[s], %[n]\n\t"
- "cmpxchg %[n], %[d]\n\t"
- "jnz,pn 0b"
- : [d] "+m"(*d), [n] "=&r" (n), [o] "+a"(o)
- : [s] "r" (*s & bm), [m] "r" (~bm));
- }
- }
- else if (sizeof (gtm_word) == 8)
- {
- uint32_t bl = bit_to_byte_mask[m & 15];
- uint32_t bh = bit_to_byte_mask[(m >> 4) & 15];
- gtm_cacheline_mask bm = bl | ((gtm_cacheline_mask)bh << 31 << 1);
-
- if (ALLOW_UNMASKED_STORES)
- *d = (*d & ~bm) | (*s & bm);
- else
- {
-#ifdef __x86_64__
- gtm_word n, o = *d;
- asm ("\n0:\t"
- "mov %[o], %[n]\n\t"
- "and %[m], %[n]\n\t"
- "or %[s], %[n]\n\t"
- "cmpxchg %[n], %[d]\n\t"
- "jnz,pn 0b"
- : [d] "+m"(*d), [n] "=&r" (n), [o] "+a"(o)
- : [s] "r" (*s & bm), [m] "r" (~bm));
-#else
- /* ??? While it's possible to perform this operation with
- cmpxchg8b, the sequence requires all 7 general registers
- and thus cannot be performed with -fPIC. Don't even try. */
- __builtin_trap ();
-#endif
- }
- }
- }
-}
-
-void
-gtm_cacheline_copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m)
-{
- const size_t n = sizeof (gtm_word);
- size_t i;
-
- if (m == (gtm_cacheline_mask)-1)
- {
- gtm_cacheline_copy (d, s);
- return;
- }
- if (__builtin_expect (m == 0, 0))
- return;
-
- for (i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n)
- copy_mask_w (&d->w[i], &s->w[i], m);
-}
-
-#endif /* SSE2 */
diff --git a/libitm/config/x86/target.h b/libitm/config/x86/target.h
index 20235b10c07..375891b0ada 100644
--- a/libitm/config/x86/target.h
+++ b/libitm/config/x86/target.h
@@ -22,6 +22,8 @@
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
+namespace GTM HIDDEN {
+
#ifdef __x86_64__
/* ??? This doesn't work for Win64. */
typedef struct gtm_jmpbuf
@@ -47,18 +49,6 @@ typedef struct gtm_jmpbuf
} gtm_jmpbuf;
#endif
-/* The "cacheline" as defined by the STM need not be the same as the
- cacheline defined by the processor. It ought to be big enough for
- any of the basic types to be stored (aligned) in one line. It ought
- to be small enough for efficient manipulation of the modification
- mask. The cacheline copy routines assume that if SSE is present
- that we can use it, which implies a minimum cacheline size of 16. */
-#ifdef __x86_64__
-# define CACHELINE_SIZE 64
-#else
-# define CACHELINE_SIZE 32
-#endif
-
/* x86 doesn't require strict alignment for the basic types. */
#define STRICT_ALIGNMENT 0
@@ -66,5 +56,39 @@ typedef struct gtm_jmpbuf
#define PAGE_SIZE 4096
#define FIXED_PAGE_SIZE 1
-/* We'll be using some of the cpu builtins, and their associated types. */
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("rep; nop" : : : "memory");
+}
+
+static inline void
+atomic_read_barrier (void)
+{
+ /* x86 is a strong memory ordering machine. */
+ __asm volatile ("" : : : "memory");
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+ /* x86 is a strong memory ordering machine. */
+ __asm volatile ("" : : : "memory");
+}
+
+} // namespace GTM
+
+// We'll be using some of the cpu builtins, and their associated types.
+#ifndef __cplusplus
+/* ??? It's broken for C++. */
#include <x86intrin.h>
+#else
+# ifdef __SSE2__
+# include <emmintrin.h>
+# elif defined(__SSE__)
+# include <xmmintrin.h>
+# endif
+# ifdef __AVX__
+# include <immintrin.h>
+# endif
+#endif
diff --git a/libitm/config/x86/target_i.h b/libitm/config/x86/target_i.h
deleted file mode 100644
index be801254748..00000000000
--- a/libitm/config/x86/target_i.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/* Copyright (C) 2009 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/>. */
-
-static inline void
-cpu_relax (void)
-{
- __asm volatile ("rep; nop" : : : "memory");
-}
-
-static inline void
-atomic_read_barrier (void)
-{
- /* x86 is a strong memory ordering machine. */
- __asm volatile ("" : : : "memory");
-}
-
-static inline void
-atomic_write_barrier (void)
-{
- /* x86 is a strong memory ordering machine. */
- __asm volatile ("" : : : "memory");
-}
-
-
-/* Copy a cacheline with the widest available vector type. */
-#if defined(__SSE__) || defined(__AVX__)
-# define HAVE_ARCH_GTM_CACHELINE_COPY 1
-static inline void
-gtm_cacheline_copy (gtm_cacheline * __restrict d,
- 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(s->CP[0]))
- {
- case 1:
- d->CP[0] = s->CP[0];
- break;
- case 2:
- x = s->CP[0];
- y = s->CP[1];
- d->CP[0] = x;
- d->CP[1] = y;
- break;
- case 4:
- w = s->CP[0];
- x = s->CP[1];
- y = s->CP[2];
- z = s->CP[3];
- d->CP[0] = w;
- d->CP[1] = x;
- d->CP[2] = y;
- d->CP[3] = z;
- break;
- default:
- __builtin_trap ();
- }
-}
-#endif
-
-#if !ALLOW_UNMASKED_STORES && defined(__SSE2__)
-# define HAVE_ARCH_GTM_CCM_WRITE_BARRIER 1
-/* A write barrier to emit after (a series of) gtm_copy_cacheline_mask.
- Since we'll be emitting non-temporal stores, the normal strong ordering
- of the machine doesn't apply and we have to emit an SFENCE. */
-static inline void
-gtm_ccm_write_barrier (void)
-{
- _mm_sfence ();
-}
-#endif
-
-#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10)
-/* Use slots in the TCB head rather than __thread lookups.
- GLIBC has reserved words 10 through 15 for TM. */
-#define HAVE_ARCH_GTM_THREAD
-#define HAVE_ARCH_GTM_THREAD_TX
-#define HAVE_ARCH_GTM_THREAD_DISP
-
-#ifdef __LP64__
-# define SEG_READ(OFS) "movq\t%%fs:(" #OFS "*8),%0"
-# define SEG_WRITE(OFS) "movq\t%0,%%fs:(" #OFS "*8)"
-#else
-# define SEG_READ(OFS) "movl\t%%gs:(" #OFS "*4),%0"
-# define SEG_WRITE(OFS) "movl\t%0,%%gs:(" #OFS "*4)"
-#endif
-
-static inline struct gtm_thread *gtm_thr(void)
-{
- struct gtm_thread *r;
- asm (SEG_READ(10) : "=r"(r));
- return r;
-}
-
-static inline void setup_gtm_thr(void)
-{
- if (gtm_thr() == NULL)
- asm volatile (SEG_WRITE(10) : : "r"(&_gtm_thr));
-}
-
-static inline struct gtm_transaction * gtm_tx(void)
-{
- struct gtm_transaction *r;
- asm (SEG_READ(11) : "=r"(r));
- return r;
-}
-
-static inline void set_gtm_tx(struct gtm_transaction *x)
-{
- asm volatile (SEG_WRITE(11) : : "r"(x));
-}
-
-static inline const struct gtm_dispatch *gtm_disp(void)
-{
- const struct gtm_dispatch *r;
- asm (SEG_READ(12) : "=r"(r));
- return r;
-}
-
-static inline void set_gtm_disp(const struct gtm_dispatch *x)
-{
- asm volatile (SEG_WRITE(12) : : "r"(x));
-}
-#endif /* >= GLIBC 2.10 */
diff --git a/libitm/config/x86/unaligned.h b/libitm/config/x86/unaligned.h
new file mode 100644
index 00000000000..422cb88b2a5
--- /dev/null
+++ b/libitm/config/x86/unaligned.h
@@ -0,0 +1,241 @@
+/* Copyright (C) 2009 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_UNALIGNED_H
+#define LIBITM_X86_UNALIGNED_H 1
+
+#define HAVE_ARCH_UNALIGNED_LOAD2_U4 1
+#define HAVE_ARCH_UNALIGNED_LOAD2_U8 1
+
+#include "config/generic/unaligned.h"
+
+namespace GTM HIDDEN {
+
+// ??? C++ currently has ambiguous name mangling, with __m128 and __m256
+// mangling to the same thing. "Fix" this by forcing these inline
+// functions to be always inline.
+
+template<>
+inline uint32_t
+unaligned_load2<uint32_t>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ uint32_t r, lo, hi;
+ lo = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1];
+ hi = c2->u32[0];
+ asm("shrd %b2, %1, %0" : "=r"(r) : "r"(hi), "c"((ofs & 3) * 8), "0"(lo));
+ return r;
+}
+
+template<>
+inline uint64_t
+unaligned_load2<uint64_t>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+#ifdef __x86_64__
+ uint64_t r, lo, hi;
+ lo = c1->u64[CACHELINE_SIZE / sizeof(uint64_t) - 1];
+ hi = c2->u64[0];
+ asm("shrd %b2, %1, %0" : "=r"(r) : "r"(hi), "c"((ofs & 3) * 8), "0"(lo));
+ return r;
+#else
+ uint32_t v0, v1, v2;
+ uint64_t r;
+
+ if (ofs < CACHELINE_SIZE - 4)
+ {
+ v0 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 2];
+ v1 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1];
+ v2 = c2->u32[0];
+ }
+ else
+ {
+ v0 = c1->u32[CACHELINE_SIZE / sizeof(uint32_t) - 1];
+ v1 = c2->u32[0];
+ v2 = c2->u32[1];
+ }
+ ofs = (ofs & 3) * 8;
+ asm("shrd %%cl, %[v1], %[v0]; shrd %%cl, %[v2], %[v1]"
+ : "=A"(r) : "c"(ofs), [v0] "a"(v0), [v1] "d"(v1), [v2] "r"(v2));
+
+ return r;
+#endif
+}
+
+#if defined(__SSE2__) || defined(__MMX__)
+template<>
+inline _ITM_TYPE_M64
+unaligned_load2<_ITM_TYPE_M64>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+# ifdef __x86_64__
+ __m128i lo = _mm_movpi64_epi64 (c1->m64[CACHELINE_SIZE / 8 - 1]);
+ __m128i hi = _mm_movpi64_epi64 (c2->m64[0]);
+
+ ofs = (ofs & 7) * 8;
+ lo = _mm_srli_epi64 (lo, ofs);
+ hi = _mm_slli_epi64 (hi, 64 - ofs);
+ lo = lo | hi;
+ return _mm_movepi64_pi64 (lo);
+# else
+ // On 32-bit we're about to return the result in an MMX register, so go
+ // ahead and do the computation in that unit, even if SSE2 is available.
+ __m64 lo = c1->m64[CACHELINE_SIZE / 8 - 1];
+ __m64 hi = c2->m64[0];
+
+ ofs = (ofs & 7) * 8;
+ lo = _mm_srli_si64 (lo, ofs);
+ hi = _mm_slli_si64 (hi, 64 - ofs);
+ return lo | hi;
+# endif
+}
+#endif // SSE2 or MMX
+
+// The SSE types are strictly aligned.
+#ifdef __SSE__
+template<>
+ struct strict_alignment<_ITM_TYPE_M128>
+ : public std::true_type
+ { };
+
+// Expand the unaligned SSE move instructions.
+template<>
+inline _ITM_TYPE_M128 ALWAYS_INLINE
+unaligned_load<_ITM_TYPE_M128>(const void *t)
+{
+ return _mm_loadu_ps (static_cast<const float *>(t));
+}
+
+template<>
+inline void ALWAYS_INLINE
+unaligned_store<_ITM_TYPE_M128>(void *t, _ITM_TYPE_M128 val)
+{
+ _mm_storeu_ps (static_cast<float *>(t), val);
+}
+#endif // SSE
+
+#ifdef __AVX__
+// The AVX types are strictly aligned when it comes to vmovaps vs vmovups.
+template<>
+ struct strict_alignment<_ITM_TYPE_M256>
+ : public std::true_type
+ { };
+
+template<>
+inline _ITM_TYPE_M256 ALWAYS_INLINE
+unaligned_load<_ITM_TYPE_M256>(const void *t)
+{
+ return _mm256_loadu_ps (static_cast<const float *>(t));
+}
+
+template<>
+inline void ALWAYS_INLINE
+unaligned_store<_ITM_TYPE_M256>(void *t, _ITM_TYPE_M256 val)
+{
+ _mm256_storeu_ps (static_cast<float *>(t), val);
+}
+#endif // AVX
+
+#ifdef __XOP__
+# define HAVE_ARCH_REALIGN_M128I 1
+extern const __v16qi GTM_vpperm_shift[16];
+inline __m128i ALWAYS_INLINE
+realign_m128i (__m128i lo, __m128i hi, unsigned byte_count)
+{
+ return _mm_perm_epi8 (lo, hi, GTM_vpperm_shift[byte_count]);
+}
+#elif defined(__AVX__)
+# define HAVE_ARCH_REALIGN_M128I 1
+extern "C" const uint64_t GTM_vpalignr_table[16];
+inline __m128i ALWAYS_INLINE
+realign_m128i (__m128i lo, __m128i hi, unsigned byte_count)
+{
+ register __m128i xmm0 __asm__("xmm0") = hi;
+ register __m128i xmm1 __asm__("xmm1") = lo;
+ __asm("call *%2" : "+x"(xmm0) : "x"(xmm1),
+ "r"(&GTM_vpalignr_table[byte_count]));
+ return xmm0;
+}
+#elif defined(__SSSE3__)
+# define HAVE_ARCH_REALIGN_M128I 1
+extern "C" const uint64_t GTM_palignr_table[16];
+inline __m128i ALWAYS_INLINE
+realign_m128i (__m128i lo, __m128i hi, unsigned byte_count)
+{
+ register __m128i xmm0 __asm__("xmm0") = hi;
+ register __m128i xmm1 __asm__("xmm1") = lo;
+ __asm("call *%2" : "+x"(xmm0) : "x"(xmm1),
+ "r"(&GTM_palignr_table[byte_count]));
+ return xmm0;
+}
+#elif defined(__SSE2__)
+# define HAVE_ARCH_REALIGN_M128I 1
+extern "C" const char GTM_pshift_table[16 * 16];
+inline __m128i ALWAYS_INLINE
+realign_m128i (__m128i lo, __m128i hi, unsigned byte_count)
+{
+ register __m128i xmm0 __asm__("xmm0") = lo;
+ register __m128i xmm1 __asm__("xmm1") = hi;
+ __asm("call *%2" : "+x"(xmm0), "+x"(xmm1)
+ : "r"(GTM_pshift_table + byte_count*16));
+ return xmm0;
+}
+#endif // XOP, AVX, SSSE3, SSE2
+
+#ifdef HAVE_ARCH_REALIGN_M128I
+template<>
+inline _ITM_TYPE_M128 ALWAYS_INLINE
+unaligned_load2<_ITM_TYPE_M128>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ return (_ITM_TYPE_M128)
+ realign_m128i (c1->m128i[CACHELINE_SIZE / 16 - 1],
+ c2->m128i[0], ofs & 15);
+}
+#endif // HAVE_ARCH_REALIGN_M128I
+
+#ifdef __AVX__
+template<>
+inline _ITM_TYPE_M256 ALWAYS_INLINE
+unaligned_load2<_ITM_TYPE_M256>(const gtm_cacheline *c1,
+ const gtm_cacheline *c2, size_t ofs)
+{
+ __m128i v0, v1;
+ __m256i r;
+
+ v0 = (__m128i) unaligned_load2<_ITM_TYPE_M128>(c1, c2, ofs);
+ if (ofs < CACHELINE_SIZE - 16)
+ v1 = v0, v0 = _mm_loadu_si128 ((const __m128i *) &c1->b[ofs]);
+ else
+ v1 = _mm_loadu_si128((const __m128i *)&c2->b[ofs + 16 - CACHELINE_SIZE]);
+
+ r = _mm256_castsi128_si256 ((__m128i)v0);
+ r = _mm256_insertf128_si256 (r, (__m128i)v1, 1);
+ return (_ITM_TYPE_M256) r;
+}
+#endif // AVX
+
+} // namespace GTM
+
+#endif // LIBITM_X86_UNALIGNED_H
diff --git a/libitm/config/x86/x86_avx.c b/libitm/config/x86/x86_avx.c
deleted file mode 100644
index b2bd5e9cc40..00000000000
--- a/libitm/config/x86/x86_avx.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Copyright (C) 2009 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"
-
-#define M256_READ(LOCK) \
-_ITM_TYPE_M256 ITM_REGPARM _ITM_##LOCK##M256(const _ITM_TYPE_M256 *ptr) \
-{ \
- uintptr_t iptr = (uintptr_t) ptr; \
- uintptr_t iline = iptr & -CACHELINE_SIZE; \
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); \
- gtm_cacheline *line = gtm_disp()->LOCK (iline); \
- _ITM_TYPE_M256 ret; \
- \
- if (iofs + sizeof(ret) <= CACHELINE_SIZE) \
- { \
- return *(_ITM_TYPE_M256 *)&line->b[iofs]; \
- } \
- else \
- { \
- uintptr_t ileft = CACHELINE_SIZE - iofs; \
- memcpy (&ret, &line->b[iofs], ileft); \
- line = gtm_disp()->LOCK (iline + CACHELINE_SIZE); \
- memcpy ((char *)&ret + ileft, line, sizeof(ret) - ileft); \
- } \
- return ret; \
-}
-
-#define M256_WRITE(LOCK) \
-void ITM_REGPARM _ITM_##LOCK##M256(_ITM_TYPE_M256 *ptr, _ITM_TYPE_M256 val) \
-{ \
- uintptr_t iptr = (uintptr_t) ptr; \
- uintptr_t iline = iptr & -CACHELINE_SIZE; \
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); \
- gtm_cacheline_mask m = ((gtm_cacheline_mask)2 << (sizeof(val)-1))-1; \
- gtm_cacheline_mask_pair pair = gtm_disp()->LOCK (iline); \
- \
- if (iofs + sizeof(val) <= CACHELINE_SIZE) \
- { \
- *(_ITM_TYPE_M256 *)&pair.line->b[iofs] = val; \
- *pair.mask |= m << iofs; \
- } \
- else \
- { \
- _ITM_TYPE_M256 sval = val; \
- uintptr_t ileft = CACHELINE_SIZE - iofs; \
- memcpy (&pair.line->b[iofs], &sval, ileft); \
- *pair.mask |= m << iofs; \
- pair = gtm_disp()->LOCK (iline + CACHELINE_SIZE); \
- memcpy (pair.line, (char *)&sval + ileft, sizeof(sval) - ileft); \
- *pair.mask |= m >> ileft; \
- } \
-}
-
-M256_READ(R)
-M256_READ(RaR)
-M256_READ(RaW)
-M256_READ(RfW)
-M256_WRITE(W)
-M256_WRITE(WaR)
-M256_WRITE(WaW)
-
-void ITM_REGPARM
-_ITM_LM256 (const _ITM_TYPE_M256 *ptr)
-{
- GTM_LB (ptr, sizeof (*ptr));
-}
diff --git a/libitm/config/x86/x86_avx.cc b/libitm/config/x86/x86_avx.cc
new file mode 100644
index 00000000000..ee073d56986
--- /dev/null
+++ b/libitm/config/x86/x86_avx.cc
@@ -0,0 +1,93 @@
+/* Copyright (C) 2009 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 "barrier.tpl"
+
+ITM_BARRIERS(M256)
+
+void ITM_REGPARM
+_ITM_LM256 (const _ITM_TYPE_M256 *ptr)
+{
+ GTM_LB (ptr, sizeof (*ptr));
+}
+
+// Helpers for re-aligning two 128-bit values.
+#ifdef __XOP__
+const __v16qi GTM::GTM_vpperm_shift[16] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 },
+ { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 },
+ { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 },
+ { 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
+ { 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 },
+ { 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 },
+ { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 },
+ { 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 },
+ { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 },
+ { 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26 },
+ { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 },
+ { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 },
+ { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 },
+ { 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 },
+};
+#else
+# define INSN0 "movdqa %xmm1, %xmm0"
+# define INSN(N) "vpalignr $" #N ", %xmm0, %xmm1, %xmm0"
+# define TABLE_ENT_0 INSN0 "\n\tret\n\t"
+# define TABLE_ENT(N) ".balign 8\n\t" INSN(N) "\n\tret\n\t"
+
+asm(".pushsection .text\n\
+ .balign 16\n\
+ .globl GTM_vpalignr_table\n\
+ .hidden GTM_vpalignr_table\n\
+ .type GTM_vpalignr_table, @function\n\
+GTM_vpalignr_table:\n\t"
+ TABLE_ENT_0
+ TABLE_ENT(1)
+ TABLE_ENT(2)
+ TABLE_ENT(3)
+ TABLE_ENT(4)
+ TABLE_ENT(5)
+ TABLE_ENT(6)
+ TABLE_ENT(7)
+ TABLE_ENT(8)
+ TABLE_ENT(9)
+ TABLE_ENT(10)
+ TABLE_ENT(11)
+ TABLE_ENT(12)
+ TABLE_ENT(13)
+ TABLE_ENT(14)
+ TABLE_ENT(15)
+ ".balign 8\n\
+ .size GTM_vpalignr_table, .-GTM_vpalignr_table\n\
+ .popsection");
+
+# undef INSN0
+# undef INSN
+# undef TABLE_ENT_0
+# undef TABLE_ENT
+#endif
diff --git a/libitm/config/x86/x86_sse.c b/libitm/config/x86/x86_sse.c
deleted file mode 100644
index eaf2676ca1c..00000000000
--- a/libitm/config/x86/x86_sse.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/* Copyright (C) 2009 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"
-
-
-#define M64_READ(LOCK) \
-_ITM_TYPE_M64 ITM_REGPARM _ITM_##LOCK##M64(const _ITM_TYPE_M64 *ptr) \
-{ \
- uintptr_t iptr = (uintptr_t) ptr; \
- uintptr_t iline = iptr & -CACHELINE_SIZE; \
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); \
- gtm_cacheline *line = gtm_disp()->LOCK (iline); \
- _ITM_TYPE_M64 ret; \
- \
- if (iofs + sizeof(ret) <= CACHELINE_SIZE) \
- { \
- return *(_ITM_TYPE_M64 *)&line->b[iofs]; \
- } \
- else \
- { \
- uintptr_t ileft = CACHELINE_SIZE - iofs; \
- memcpy (&ret, &line->b[iofs], ileft); \
- line = gtm_disp()->LOCK (iline + CACHELINE_SIZE); \
- memcpy ((char *)&ret + ileft, line, sizeof(ret) - ileft); \
- } \
- return ret; \
-}
-
-#define M64_WRITE(LOCK) \
-void ITM_REGPARM _ITM_##LOCK##M64(_ITM_TYPE_M64 *ptr, _ITM_TYPE_M64 val) \
-{ \
- uintptr_t iptr = (uintptr_t) ptr; \
- uintptr_t iline = iptr & -CACHELINE_SIZE; \
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); \
- gtm_cacheline_mask m = ((gtm_cacheline_mask)1 << sizeof(val)) - 1; \
- gtm_cacheline_mask_pair pair = gtm_disp()->LOCK (iline); \
- \
- if (iofs + sizeof(val) <= CACHELINE_SIZE) \
- { \
- *(_ITM_TYPE_M64 *)&pair.line->b[iofs] = val; \
- *pair.mask |= m << iofs; \
- } \
- else \
- { \
- _ITM_TYPE_M64 sval = val; \
- uintptr_t ileft = CACHELINE_SIZE - iofs; \
- memcpy (&pair.line->b[iofs], &sval, ileft); \
- *pair.mask |= m << iofs; \
- pair = gtm_disp()->LOCK (iline + CACHELINE_SIZE); \
- memcpy (pair.line, (char *)&sval + ileft, sizeof(sval) - ileft); \
- *pair.mask |= m >> ileft; \
- } \
-}
-
-/* Note that unlike all other X86 types, the SSE vector types do
- require strict alignment by default. Use the unaligned load
- and store builtins when necessary. */
-
-#define M128_READ(LOCK) \
-_ITM_TYPE_M128 ITM_REGPARM _ITM_##LOCK##M128(const _ITM_TYPE_M128 *ptr) \
-{ \
- uintptr_t iptr = (uintptr_t) ptr; \
- uintptr_t iline = iptr & -CACHELINE_SIZE; \
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); \
- gtm_cacheline *line = gtm_disp()->LOCK (iline); \
- _ITM_TYPE_M128 ret; \
- \
- if ((iofs & (sizeof (ret) - 1)) == 0) \
- { \
- return *(_ITM_TYPE_M128 *)&line->b[iofs]; \
- } \
- else if (iofs + sizeof(ret) <= CACHELINE_SIZE) \
- { \
- return _mm_loadu_ps ((const float *) &line->b[iofs]); \
- } \
- else \
- { \
- uintptr_t ileft = CACHELINE_SIZE - iofs; \
- memcpy (&ret, &line->b[iofs], ileft); \
- line = gtm_disp()->LOCK (iline + CACHELINE_SIZE); \
- memcpy ((char *)&ret + ileft, line, sizeof(ret) - ileft); \
- } \
- return ret; \
-}
-
-#define M128_WRITE(LOCK) \
-void ITM_REGPARM _ITM_##LOCK##M128(_ITM_TYPE_M128 *ptr, _ITM_TYPE_M128 val) \
-{ \
- uintptr_t iptr = (uintptr_t) ptr; \
- uintptr_t iline = iptr & -CACHELINE_SIZE; \
- uintptr_t iofs = iptr & (CACHELINE_SIZE - 1); \
- gtm_cacheline_mask m = ((gtm_cacheline_mask)1 << sizeof(val)) - 1; \
- gtm_cacheline_mask_pair pair = gtm_disp()->LOCK (iline); \
- \
- if ((iofs & (sizeof (val) - 1)) == 0) \
- { \
- *(_ITM_TYPE_M128 *)&pair.line->b[iofs] = val; \
- *pair.mask |= m << iofs; \
- } \
- else if (iofs + sizeof(val) <= CACHELINE_SIZE) \
- { \
- _mm_storeu_ps ((float *) &pair.line->b[iofs], val); \
- *pair.mask |= m << iofs; \
- } \
- else \
- { \
- _ITM_TYPE_M128 sval = val; \
- uintptr_t ileft = CACHELINE_SIZE - iofs; \
- memcpy (&pair.line->b[iofs], &sval, ileft); \
- *pair.mask |= m << iofs; \
- pair = gtm_disp()->LOCK (iline + CACHELINE_SIZE); \
- memcpy (pair.line, (char *)&sval + ileft, sizeof(sval) - ileft); \
- *pair.mask |= m >> ileft; \
- } \
-}
-
-M64_READ(R)
-M64_READ(RaR)
-M64_READ(RaW)
-M64_READ(RfW)
-M64_WRITE(W)
-M64_WRITE(WaR)
-M64_WRITE(WaW)
-
-M128_READ(R)
-M128_READ(RaR)
-M128_READ(RaW)
-M128_READ(RfW)
-M128_WRITE(W)
-M128_WRITE(WaR)
-M128_WRITE(WaW)
-
-
-void ITM_REGPARM
-_ITM_LM64 (const _ITM_TYPE_M64 *ptr)
-{
- GTM_LB (ptr, sizeof (*ptr));
-}
-
-void ITM_REGPARM
-_ITM_LM128 (const _ITM_TYPE_M128 *ptr)
-{
- GTM_LB (ptr, sizeof (*ptr));
-}
diff --git a/libitm/config/x86/x86_sse.cc b/libitm/config/x86/x86_sse.cc
new file mode 100644
index 00000000000..5bb97664d81
--- /dev/null
+++ b/libitm/config/x86/x86_sse.cc
@@ -0,0 +1,120 @@
+/* Copyright (C) 2009 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 "barrier.tpl"
+
+ITM_BARRIERS(M64)
+ITM_BARRIERS(M128)
+
+void ITM_REGPARM
+_ITM_LM64 (const _ITM_TYPE_M64 *ptr)
+{
+ GTM_LB (ptr, sizeof (*ptr));
+}
+
+void ITM_REGPARM
+_ITM_LM128 (const _ITM_TYPE_M128 *ptr)
+{
+ GTM_LB (ptr, sizeof (*ptr));
+}
+
+// Helpers for re-aligning two 128-bit values.
+#ifdef __SSSE3__
+# define INSN0 "movdqa %xmm1, %xmm0"
+# define INSN(N) "palignr $" #N ", %xmm1, %xmm0"
+# define TABLE_ENT_0 INSN0 "\n\tret\n\t"
+# define TABLE_ENT(N) ".balign 8\n\t" INSN(N) "\n\tret\n\t"
+
+asm(".pushsection .text\n\
+ .balign 16\n\
+ .globl GTM_palignr_table\n\
+ .hidden GTM_palignr_table\n\
+ .type GTM_palignr_table, @function\n\
+GTM_palignr_table:\n\t"
+ TABLE_ENT_0
+ TABLE_ENT(1)
+ TABLE_ENT(2)
+ TABLE_ENT(3)
+ TABLE_ENT(4)
+ TABLE_ENT(5)
+ TABLE_ENT(6)
+ TABLE_ENT(7)
+ TABLE_ENT(8)
+ TABLE_ENT(9)
+ TABLE_ENT(10)
+ TABLE_ENT(11)
+ TABLE_ENT(12)
+ TABLE_ENT(13)
+ TABLE_ENT(14)
+ TABLE_ENT(15)
+ ".balign 8\n\
+ .size GTM_palignr_table, .-GTM_palignr_table\n\
+ .popsection");
+
+# undef INSN0
+# undef INSN
+# undef TABLE_ENT_0
+# undef TABLE_ENT
+#elif defined(__SSE2__)
+# define INSNS_8 "punpcklqdq %xmm1, %xmm0"
+# define INSNS(N) "psrldq $"#N", %xmm0\n\t" \
+ "pslldq $(16-"#N"), %xmm1\n\t" \
+ "por %xmm1, %xmm0"
+# define TABLE_ENT_0 "ret\n\t"
+# define TABLE_ENT_8 ".balign 16\n\t" INSNS_8 "\n\tret\n\t"
+# define TABLE_ENT(N) ".balign 16\n\t" INSNS(N) "\n\tret\n\t"
+
+asm(".pushsection .text\n\
+ .balign 16\n\
+ .globl GTM_pshift_table\n\
+ .hidden GTM_pshift_table\n\
+ .type GTM_pshift_table, @function\n\
+GTM_pshift_table:\n\t"
+ TABLE_ENT_0
+ TABLE_ENT(1)
+ TABLE_ENT(2)
+ TABLE_ENT(3)
+ TABLE_ENT(4)
+ TABLE_ENT(5)
+ TABLE_ENT(6)
+ TABLE_ENT(7)
+ TABLE_ENT_8
+ TABLE_ENT(9)
+ TABLE_ENT(10)
+ TABLE_ENT(11)
+ TABLE_ENT(12)
+ TABLE_ENT(13)
+ TABLE_ENT(14)
+ TABLE_ENT(15)
+ ".balign 8\n\
+ .size GTM_pshift_table, .-GTM_pshift_table\n\
+ .popsection");
+
+# undef INSNS_8
+# undef INSNS
+# undef TABLE_ENT_0
+# undef TABLE_ENT_8
+# undef TABLE_ENT
+#endif
diff --git a/libitm/configure b/libitm/configure
index 453f465e868..9585c11e4f4 100755
--- a/libitm/configure
+++ b/libitm/configure
@@ -740,6 +740,8 @@ ac_subst_vars='am__EXEEXT_FALSE
am__EXEEXT_TRUE
LTLIBOBJS
LIBOBJS
+ARCH_FUTEX_FALSE
+ARCH_FUTEX_TRUE
ARCH_X86_FALSE
ARCH_X86_TRUE
link_itm
@@ -759,6 +761,7 @@ MAINTAINER_MODE_FALSE
MAINTAINER_MODE_TRUE
enable_static
enable_shared
+CXXCPP
CPP
OTOOL64
OTOOL
@@ -787,6 +790,12 @@ am__fastdepCCAS_TRUE
CCASDEPMODE
CCASFLAGS
CCAS
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+ac_ct_CXX
+CXXFLAGS
+CXX
am__fastdepCC_FALSE
am__fastdepCC_TRUE
CCDEPMODE
@@ -904,10 +913,14 @@ host_alias
target_alias
CPP
CPPFLAGS
-FC
-FCFLAGS
+CXX
+CXXFLAGS
LDFLAGS
-LIBS'
+LIBS
+CCC
+CXXCPP
+FC
+FCFLAGS'
# Initialize some variables set by options.
@@ -1565,9 +1578,12 @@ Some influential environment variables:
LIBS libraries to pass to the linker, e.g. -l<library>
CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
you have headers in a nonstandard directory <include dir>
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
CCAS assembler compiler command (defaults to CC)
CCASFLAGS assembler compiler flags (defaults to CFLAGS)
CPP C preprocessor
+ CXXCPP C++ preprocessor
FC Fortran compiler command
FCFLAGS Fortran compiler flags
@@ -1691,6 +1707,44 @@ fi
} # ac_fn_c_try_compile
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_cxx_try_compile
+
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
@@ -1914,6 +1968,89 @@ $as_echo "$ac_res" >&6; }
} # ac_fn_c_check_func
+# ac_fn_cxx_try_cpp LINENO
+# ------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } >/dev/null && {
+ test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_cxx_try_cpp
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_cxx_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ $as_test_x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;}
+ return $ac_retval
+
+} # ac_fn_cxx_try_link
+
# ac_fn_fc_try_compile LINENO
# ---------------------------
# Try to compile conftest.$ac_ext, and return whether this succeeded.
@@ -4400,6 +4537,390 @@ else
fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ rm -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
# By default we simply use the C compiler to build assembly code.
test "${CCAS+set}" = set || CCAS=$CC
@@ -5486,13 +6007,13 @@ if test "${lt_cv_nm_interface+set}" = set; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:5489: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:6010: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:5492: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:6013: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:5495: output\"" >&5)
+ (eval echo "\"\$as_me:6016: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -6698,7 +7219,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 6701 "configure"' > conftest.$ac_ext
+ echo '#line 7222 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -7728,6 +8249,533 @@ done
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+ if test -n "$CCC"; then
+ CXX=$CCC
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CXX" && break
+done
+
+ if test "x$ac_ct_CXX" = x; then
+ CXX="g++"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CXX=$ac_ct_CXX
+ fi
+fi
+
+ fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ rm -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GXX=yes
+else
+ GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+ ac_cxx_werror_flag=yes
+ ac_cv_prog_cxx_g=no
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+else
+ CXXFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+ CXXFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named `D' -- because `-MD' means `put the output
+ # in D'.
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CXX_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+ # Solaris 8's {/usr,}/bin/sh.
+ touch sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with `-c' and `-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle `-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # after this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvisualcpp | msvcmsys)
+ # This compiler won't grok `-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CXX_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+ am__fastdepCXX_TRUE=
+ am__fastdepCXX_FALSE='#'
+else
+ am__fastdepCXX_TRUE='#'
+ am__fastdepCXX_FALSE=
+fi
+
+
+if test -n "$CXX" && ( test "X$CXX" != "Xno" &&
+ ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) ||
+ (test "X$CXX" != "Xg++"))) ; then
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+_lt_caught_CXX_error=yes; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+else
+ _lt_caught_CXX_error=yes
+fi
+
+
+
+
+
# Set options
@@ -8228,11 +9276,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8231: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9279: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:8235: \$? = $ac_status" >&5
+ echo "$as_me:9283: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -8567,11 +9615,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8570: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9618: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:8574: \$? = $ac_status" >&5
+ echo "$as_me:9622: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -8672,11 +9720,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8675: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9723: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:8679: \$? = $ac_status" >&5
+ echo "$as_me:9727: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -8727,11 +9775,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:8730: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:9778: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:8734: \$? = $ac_status" >&5
+ echo "$as_me:9782: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -11109,7 +12157,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11112 "configure"
+#line 12160 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11205,7 +12253,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11208 "configure"
+#line 12256 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11413,6 +12461,2853 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
CC="$lt_save_CC"
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+archive_cmds_need_lc_CXX=no
+allow_undefined_flag_CXX=
+always_export_symbols_CXX=no
+archive_expsym_cmds_CXX=
+compiler_needs_object_CXX=no
+export_dynamic_flag_spec_CXX=
+hardcode_direct_CXX=no
+hardcode_direct_absolute_CXX=no
+hardcode_libdir_flag_spec_CXX=
+hardcode_libdir_flag_spec_ld_CXX=
+hardcode_libdir_separator_CXX=
+hardcode_minus_L_CXX=no
+hardcode_shlibpath_var_CXX=unsupported
+hardcode_automatic_CXX=no
+inherit_rpath_CXX=no
+module_cmds_CXX=
+module_expsym_cmds_CXX=
+link_all_deplibs_CXX=unknown
+old_archive_cmds_CXX=$old_archive_cmds
+no_undefined_flag_CXX=
+whole_archive_flag_spec_CXX=
+enable_shared_with_static_runtimes_CXX=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+objext_CXX=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test "$_lt_caught_CXX_error" != yes; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="int some_variable = 0;"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code='int main(int, char *[]) { return(0); }'
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+ # save warnings/boilerplate of simple test code
+ ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_LD=$LD
+ lt_save_GCC=$GCC
+ GCC=$GXX
+ lt_save_with_gnu_ld=$with_gnu_ld
+ lt_save_path_LD=$lt_cv_path_LD
+ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+ $as_unset lt_cv_prog_gnu_ld
+ fi
+ if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+ else
+ $as_unset lt_cv_path_LD
+ fi
+ test -z "${LDCXX+set}" || LD=$LDCXX
+ CC=${CXX-"c++"}
+ compiler=$CC
+ compiler_CXX=$CC
+ for cc_temp in $compiler""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"`
+
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test "$GXX" = yes; then
+ lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin'
+ else
+ lt_prog_compiler_no_builtin_flag_CXX=
+ fi
+
+ if test "$GXX" = yes; then
+ # Set up default GNU C++ configuration
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+ withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if test "${lt_cv_path_LD+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$lt_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$lt_save_ifs"
+else
+ lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi
+fi
+
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if test "${lt_cv_prog_gnu_ld+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test "$with_gnu_ld" = yes; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='${wl}'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ $GREP 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ else
+ whole_archive_flag_spec_CXX=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "^ .* -L"'
+
+ else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+ fi
+
+ # PORTME: fill in a description of your system's C++ link characteristics
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+ ld_shlibs_CXX=yes
+ case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aix[4-9]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=""
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds_CXX=''
+ hardcode_direct_CXX=yes
+ hardcode_direct_absolute_CXX=yes
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+ file_list_spec_CXX='${wl}-f,'
+
+ if test "$GXX" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct_CXX=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L_CXX=yes
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ hardcode_libdir_separator_CXX=
+ fi
+ esac
+ shared_flag='-shared'
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag="$shared_flag "'${wl}-G'
+ fi
+ else
+ # not using gcc
+ if test "$host_cpu" = ia64; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test "$aix_use_runtimelinking" = yes; then
+ shared_flag='${wl}-G'
+ else
+ shared_flag='${wl}-bM:SRE'
+ fi
+ fi
+ fi
+
+ export_dynamic_flag_spec_CXX='${wl}-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to
+ # export.
+ always_export_symbols_CXX=yes
+ if test "$aix_use_runtimelinking" = yes; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag_CXX='-berok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+ archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag_CXX="-z nodefs"
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+
+lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\(.*\)$/\1/
+ p
+ }
+ }'
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag_CXX=' ${wl}-bernotok'
+ allow_undefined_flag_CXX=' ${wl}-berok'
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec_CXX='$convenience'
+ archive_cmds_need_lc_CXX=yes
+ # This is similar to how AIX traditionally builds its shared
+ # libraries.
+ archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag_CXX=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec_CXX='-L$libdir'
+ allow_undefined_flag_CXX=unsupported
+ always_export_symbols_CXX=no
+ enable_shared_with_static_runtimes_CXX=yes
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file (1st line
+ # is EXPORTS), use it as is; otherwise, prepend...
+ archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc_CXX=no
+ hardcode_direct_CXX=no
+ hardcode_automatic_CXX=yes
+ hardcode_shlibpath_var_CXX=unsupported
+ whole_archive_flag_spec_CXX=''
+ link_all_deplibs_CXX=yes
+ allow_undefined_flag_CXX="$_lt_dar_allow_undefined"
+ case $cc_basename in
+ ifort*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test "$_lt_dar_can_shared" = "yes"; then
+ output_verbose_link_cmd=echo
+ archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}"
+ module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}"
+ archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}"
+ module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}"
+ if test "$lt_cv_apple_cc_single_mod" != "yes"; then
+ archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}"
+ archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}"
+ fi
+
+ else
+ ld_shlibs_CXX=no
+ fi
+
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ freebsd[12]*)
+ # C++ shared libraries reported to be fairly broken before
+ # switch to ELF
+ ld_shlibs_CXX=no
+ ;;
+
+ freebsd-elf*)
+ archive_cmds_need_lc_CXX=no
+ ;;
+
+ freebsd* | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ ld_shlibs_CXX=yes
+ ;;
+
+ gnu*)
+ ;;
+
+ hpux9*)
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ hardcode_direct_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "^ .* -L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test $with_gnu_ld = no; then
+ hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ ;;
+ *)
+ hardcode_direct_CXX=yes
+ hardcode_direct_absolute_CXX=yes
+ hardcode_minus_L_CXX=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "^ .* -L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test $with_gnu_ld = no; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+
+ interix[3-9]*)
+ hardcode_direct_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test "$GXX" = yes; then
+ if test "$with_gnu_ld" = no; then
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ else
+ archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib'
+ fi
+ fi
+ link_all_deplibs_CXX=yes
+ ;;
+ esac
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+ inherit_rpath_CXX=yes
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc* | ecpc* )
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ archive_cmds_need_lc_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ case `$CC -V` in
+ *pgCC\ [1-5]* | *pgcpp\ [1-5]*)
+ prelink_cmds_CXX='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+ compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"'
+ old_archive_cmds_CXX='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~
+ $RANLIB $oldlib'
+ archive_cmds_CXX='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ archive_expsym_cmds_CXX='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ *) # Version 6 will use weak symbols
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib'
+ ;;
+ esac
+
+ hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ xl*)
+ # IBM XL 8.0 on PPC, with GNU ld
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ export_dynamic_flag_spec_CXX='${wl}--export-dynamic'
+ archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+ if test "x$supports_anon_versioning" = xyes; then
+ archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols'
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive'
+ compiler_needs_object_CXX=yes
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+
+ m88k*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+
+ *nto* | *qnx*)
+ ld_shlibs_CXX=yes
+ ;;
+
+ openbsd2*)
+ # C++ shared libraries are fairly broken
+ ld_shlibs_CXX=no
+ ;;
+
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct_CXX=yes
+ hardcode_shlibpath_var_CXX=no
+ hardcode_direct_absolute_CXX=yes
+ archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib'
+ export_dynamic_flag_spec_CXX='${wl}-E'
+ whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+ fi
+ output_verbose_link_cmd=echo
+ else
+ ld_shlibs_CXX=no
+ fi
+ ;;
+
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ case $host in
+ osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;;
+ *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;;
+ esac
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ cxx*)
+ case $host in
+ osf3*)
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ ;;
+ *)
+ allow_undefined_flag_CXX=' -expect_unresolved \*'
+ archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib'
+ archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~
+ $RM $lib.exp'
+ hardcode_libdir_flag_spec_CXX='-rpath $libdir'
+ ;;
+ esac
+
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed'
+ ;;
+ *)
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*'
+ case $host in
+ osf3*)
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+ ;;
+ esac
+
+ hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator_CXX=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "^ .* -L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ fi
+ ;;
+ esac
+ ;;
+
+ psos*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ archive_cmds_need_lc_CXX=yes
+ no_undefined_flag_CXX=' -zdefs'
+ archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ hardcode_libdir_flag_spec_CXX='-R$libdir'
+ hardcode_shlibpath_var_CXX=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands `-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ link_all_deplibs_CXX=yes
+
+ output_verbose_link_cmd='echo'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+ no_undefined_flag_CXX=' ${wl}-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "^ .* -L"'
+ else
+ # g++ 2.7 appears to require `-G' NOT `-shared' on this
+ # platform.
+ archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+ archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "^ .* -L"'
+ fi
+
+ hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir'
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag_CXX='${wl}-z,text'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We can NOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag_CXX='${wl}-z,text'
+ allow_undefined_flag_CXX='${wl}-z,nodefs'
+ archive_cmds_need_lc_CXX=no
+ hardcode_shlibpath_var_CXX=no
+ hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir'
+ hardcode_libdir_separator_CXX=':'
+ link_all_deplibs_CXX=yes
+ export_dynamic_flag_spec_CXX='${wl}-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+ ;;
+
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+
+ *)
+ # FIXME: insert proper C++ library support
+ ld_shlibs_CXX=no
+ ;;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+ test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+ GCC_CXX="$GXX"
+ LD_CXX="$LD"
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ # Dependencies to place before and after the object being linked:
+predep_objects_CXX=
+postdep_objects_CXX=
+predeps_CXX=
+postdeps_CXX=
+compiler_lib_search_path_CXX=
+
+cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+_LT_EOF
+
+if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ for p in `eval "$output_verbose_link_cmd"`; do
+ case $p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test $p = "-L" ||
+ test $p = "-R"; then
+ prev=$p
+ continue
+ else
+ prev=
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ case $p in
+ -L* | -R*)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$compiler_lib_search_path_CXX"; then
+ compiler_lib_search_path_CXX="${prev}${p}"
+ else
+ compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$postdeps_CXX"; then
+ postdeps_CXX="${prev}${p}"
+ else
+ postdeps_CXX="${postdeps_CXX} ${prev}${p}"
+ fi
+ fi
+ ;;
+
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test "$pre_test_object_deps_done" = no; then
+ if test -z "$predep_objects_CXX"; then
+ predep_objects_CXX="$p"
+ else
+ predep_objects_CXX="$predep_objects_CXX $p"
+ fi
+ else
+ if test -z "$postdep_objects_CXX"; then
+ postdep_objects_CXX="$p"
+ else
+ postdep_objects_CXX="$postdep_objects_CXX $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling CXX test program"
+fi
+
+$RM -f confest.$objext
+
+# PORTME: override above test on systems where it is broken
+case $host_os in
+interix[3-9]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ predep_objects_CXX=
+ postdep_objects_CXX=
+ postdeps_CXX=
+ ;;
+
+linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ if test "$solaris_use_stlport4" != yes; then
+ postdeps_CXX='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+solaris*)
+ case $cc_basename in
+ CC*)
+ # The more standards-conforming stlport4 library is
+ # incompatible with the Cstd library. Avoid specifying
+ # it if it's in CXXFLAGS. Ignore libCrun as
+ # -library=stlport4 depends on it.
+ case " $CXX $CXXFLAGS " in
+ *" -library=stlport4 "*)
+ solaris_use_stlport4=yes
+ ;;
+ esac
+
+ # Adding this requires a known-good setup of shared libraries for
+ # Sun compiler versions before 5.6, else PIC objects from an old
+ # archive will be linked into the output, leading to subtle bugs.
+ if test "$solaris_use_stlport4" != yes; then
+ postdeps_CXX='-library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+esac
+
+
+case " $postdeps_CXX " in
+*" -lc "*) archive_cmds_need_lc_CXX=no ;;
+esac
+ compiler_lib_search_dirs_CXX=
+if test -n "${compiler_lib_search_path_CXX}"; then
+ compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'`
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lt_prog_compiler_wl_CXX=
+lt_prog_compiler_pic_CXX=
+lt_prog_compiler_static_CXX=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+
+ # C++ specific cases for pic, static, wl, etc.
+ if test "$GXX" = yes; then
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the `-m68020' flag to GCC prevents building anything better,
+ # like `-m68040'.
+ lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ lt_prog_compiler_pic_CXX='-DDLL_EXPORT'
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic_CXX='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ lt_prog_compiler_pic_CXX=
+ ;;
+ interix[3-9]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic_CXX=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic_CXX='-fPIC -shared'
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[4-9]*)
+ # All AIX code is PIC.
+ if test "$host_cpu" = ia64; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static_CXX='-Bstatic'
+ else
+ lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ if test "$host_cpu" != ia64; then
+ lt_prog_compiler_pic_CXX='+Z'
+ fi
+ ;;
+ aCC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='${wl}-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_static_CXX='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ ;;
+ ecpc* )
+ # old Intel C++ for x86_64 which still supported -KPIC.
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ icpc* )
+ # Intel C++, used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-fPIC'
+ lt_prog_compiler_static_CXX='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-fpic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ xlc* | xlC*)
+ # IBM XL 8.0 on PPC
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-qpic'
+ lt_prog_compiler_static_CXX='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ lt_prog_compiler_pic_CXX='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic_CXX='-fPIC -shared'
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ lt_prog_compiler_wl_CXX='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ lt_prog_compiler_wl_CXX='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_static_CXX='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ lt_prog_compiler_wl_CXX='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ lt_prog_compiler_pic_CXX='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ lt_prog_compiler_pic_CXX='-pic'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ lt_prog_compiler_pic_CXX='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ lt_prog_compiler_wl_CXX='-Wl,'
+ lt_prog_compiler_pic_CXX='-KPIC'
+ lt_prog_compiler_static_CXX='-Bstatic'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ lt_prog_compiler_pic_CXX='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ lt_prog_compiler_can_build_shared_CXX=no
+ ;;
+ esac
+ fi
+
+case $host_os in
+ # For platforms which do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic_CXX=
+ ;;
+ *)
+ lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC"
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5
+$as_echo "$lt_prog_compiler_pic_CXX" >&6; }
+
+
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic_CXX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; }
+if test "${lt_cv_prog_compiler_pic_works_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_pic_works_CXX=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14212: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:14216: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_pic_works_CXX=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; }
+
+if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then
+ case $lt_prog_compiler_pic_CXX in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;;
+ esac
+else
+ lt_prog_compiler_pic_CXX=
+ lt_prog_compiler_can_build_shared_CXX=no
+fi
+
+fi
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if test "${lt_cv_prog_compiler_static_works_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_static_works_CXX=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_static_works_CXX=yes
+ fi
+ else
+ lt_cv_prog_compiler_static_works_CXX=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS="$save_LDFLAGS"
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; }
+
+if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then
+ :
+else
+ lt_prog_compiler_static_CXX=
+fi
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14311: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:14315: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o_CXX=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:14363: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:14367: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o_CXX=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5
+$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; }
+
+
+
+
+hard_links="nottested"
+if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then
+ # do not overwrite the value of need_locks provided by the user
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+ if test "$hard_links" = no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ case $host_os in
+ aix[4-9]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to AIX nm, but means don't demangle with GNU nm
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ export_symbols_cmds_CXX="$ltdll_cmds"
+ ;;
+ cygwin* | mingw* | cegcc*)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;/^.*[ ]__nm__/s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ *)
+ export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+ exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5
+$as_echo "$ld_shlibs_CXX" >&6; }
+test "$ld_shlibs_CXX" = no && can_build_shared=no
+
+with_gnu_ld_CXX=$with_gnu_ld
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc_CXX" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc_CXX=yes
+
+ if test "$enable_shared" = yes && test "$GCC" = yes; then
+ case $archive_cmds_CXX in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if test "${lt_cv_archive_cmds_need_lc_CXX+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl_CXX
+ pic_flag=$lt_prog_compiler_pic_CXX
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag_CXX
+ allow_undefined_flag_CXX=
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+ (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ then
+ lt_cv_archive_cmds_need_lc_CXX=no
+ else
+ lt_cv_archive_cmds_need_lc_CXX=yes
+ fi
+ allow_undefined_flag_CXX=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; }
+ archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+
+aix[4-9]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test "$host_cpu" = ia64; then
+ # AIX 5 supports IA64
+ library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line `#! .'. This would cause the generated library to
+ # depend on `.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ if test "$aix_use_runtimelinking" = yes; then
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ else
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='${libname}${release}.a $libname.a'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ fi
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='${libname}${shared_ext}'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=".dll"
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$host_os in
+ yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*)
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \${file}`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+ if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH printed by
+ # mingw gcc, but we are running on Cygwin. Gcc prints its search
+ # path with ; separators, and with drive letters. We can handle the
+ # drive letters (cygwin fileutils understands them), so leave them,
+ # especially as we might pass files found there to a mingw objdump,
+ # which wouldn't understand a cygwinified path. Ahh.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+ ;;
+ esac
+ ;;
+
+ *)
+ library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+ soname_spec='${libname}${release}${major}$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd1*)
+ dynamic_linker=no
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[123]*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+gnu*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ if test "X$HPUX_IA64_MODE" = X32; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ fi
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555.
+ postinstall_cmds='chmod 555 $lib'
+ ;;
+
+interix[3-9]*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test "$lt_cv_prog_gnu_ld" = yes; then
+ version_type=linux
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+ sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+# This must be Linux ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \
+ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+ lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+fi
+
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Append ld.so.conf contents to the search path
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec="/usr/lib"
+ need_lib_prefix=no
+ # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs.
+ case $host_os in
+ openbsd3.3 | openbsd3.3.*) need_version=yes ;;
+ *) need_version=no ;;
+ esac
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ case $host_os in
+ openbsd2.[89] | openbsd2.[89].*)
+ shlibpath_overrides_runpath=no
+ ;;
+ *)
+ shlibpath_overrides_runpath=yes
+ ;;
+ esac
+ else
+ shlibpath_overrides_runpath=yes
+ fi
+ ;;
+
+os2*)
+ libname_spec='$name'
+ shrext_cmds=".dll"
+ need_lib_prefix=no
+ library_names_spec='$libname${shared_ext} $libname.a'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=LIBPATH
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='${libname}${release}${shared_ext}$major'
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test "$with_gnu_ld" = yes; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec ;then
+ version_type=linux
+ library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+ soname_spec='$libname${shared_ext}.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=freebsd-elf
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test "$with_gnu_ld" = yes; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux
+ library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+ soname_spec='${libname}${release}${shared_ext}$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test "$dynamic_linker" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then
+ sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec"
+fi
+if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then
+ sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action_CXX=
+if test -n "$hardcode_libdir_flag_spec_CXX" ||
+ test -n "$runpath_var_CXX" ||
+ test "X$hardcode_automatic_CXX" = "Xyes" ; then
+
+ # We can hardcode non-existent directories.
+ if test "$hardcode_direct_CXX" != no &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no &&
+ test "$hardcode_minus_L_CXX" != no; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action_CXX=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action_CXX=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action_CXX=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5
+$as_echo "$hardcode_action_CXX" >&6; }
+
+if test "$hardcode_action_CXX" = relink ||
+ test "$inherit_rpath_CXX" = yes; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+ test "$enable_shared" = no; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ LDCXX=$LD
+ LD=$lt_save_LD
+ GCC=$lt_save_GCC
+ with_gnu_ld=$lt_save_with_gnu_ld
+ lt_cv_path_LDCXX=$lt_cv_path_LD
+ lt_cv_path_LD=$lt_save_path_LD
+ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test "$_lt_caught_CXX_error" != yes
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
@@ -12152,24 +16047,6 @@ fi
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
lt_prog_compiler_wl_FC=
lt_prog_compiler_pic_FC=
lt_prog_compiler_static_FC=
@@ -12473,11 +16350,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12476: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16353: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:12480: \$? = $ac_status" >&5
+ echo "$as_me:16357: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -12572,11 +16449,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12575: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16452: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:12579: \$? = $ac_status" >&5
+ echo "$as_me:16456: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -12624,11 +16501,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:12627: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:16504: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:12631: \$? = $ac_status" >&5
+ echo "$as_me:16508: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -15118,6 +18995,375 @@ ac_config_commands="$ac_config_commands gstdint.h"
+
+ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_mman_h" = x""yes; then :
+ gcc_header_sys_mman_h=yes
+else
+ gcc_header_sys_mman_h=no
+fi
+
+
+ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
+if test "x$ac_cv_func_mmap" = x""yes; then :
+ gcc_func_mmap=yes
+else
+ gcc_func_mmap=no
+fi
+
+if test "$gcc_header_sys_mman_h" != yes \
+ || test "$gcc_func_mmap" != yes; then
+ gcc_cv_func_mmap_file=no
+ gcc_cv_func_mmap_dev_zero=no
+ gcc_cv_func_mmap_anon=no
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether read-only mmap of a plain file works" >&5
+$as_echo_n "checking whether read-only mmap of a plain file works... " >&6; }
+if test "${gcc_cv_func_mmap_file+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Add a system to this blacklist if
+ # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
+ # memory area containing the same data that you'd get if you applied
+ # read() to the same fd. The only system known to have a problem here
+ # is VMS, where text files have record structure.
+ case "$host_os" in
+ vms* | ultrix*)
+ gcc_cv_func_mmap_file=no ;;
+ *)
+ gcc_cv_func_mmap_file=yes;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_file" >&5
+$as_echo "$gcc_cv_func_mmap_file" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap from /dev/zero works" >&5
+$as_echo_n "checking whether mmap from /dev/zero works... " >&6; }
+if test "${gcc_cv_func_mmap_dev_zero+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Add a system to this blacklist if it has mmap() but /dev/zero
+ # does not exist, or if mmapping /dev/zero does not give anonymous
+ # zeroed pages with both the following properties:
+ # 1. If you map N consecutive pages in with one call, and then
+ # unmap any subset of those pages, the pages that were not
+ # explicitly unmapped remain accessible.
+ # 2. If you map two adjacent blocks of memory and then unmap them
+ # both at once, they must both go away.
+ # Systems known to be in this category are Windows (all variants),
+ # VMS, and Darwin.
+ case "$host_os" in
+ vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
+ gcc_cv_func_mmap_dev_zero=no ;;
+ *)
+ gcc_cv_func_mmap_dev_zero=yes;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_dev_zero" >&5
+$as_echo "$gcc_cv_func_mmap_dev_zero" >&6; }
+
+ # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MAP_ANON(YMOUS)" >&5
+$as_echo_n "checking for MAP_ANON(YMOUS)... " >&6; }
+if test "${gcc_cv_decl_map_anon+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+int
+main ()
+{
+int n = MAP_ANONYMOUS;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ gcc_cv_decl_map_anon=yes
+else
+ gcc_cv_decl_map_anon=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_decl_map_anon" >&5
+$as_echo "$gcc_cv_decl_map_anon" >&6; }
+
+ if test $gcc_cv_decl_map_anon = no; then
+ gcc_cv_func_mmap_anon=no
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap with MAP_ANON(YMOUS) works" >&5
+$as_echo_n "checking whether mmap with MAP_ANON(YMOUS) works... " >&6; }
+if test "${gcc_cv_func_mmap_anon+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Add a system to this blacklist if it has mmap() and MAP_ANON or
+ # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
+ # doesn't give anonymous zeroed pages with the same properties listed
+ # above for use of /dev/zero.
+ # Systems known to be in this category are Windows, VMS, and SCO Unix.
+ case "$host_os" in
+ vms* | cygwin* | pe | mingw* | sco* | udk* )
+ gcc_cv_func_mmap_anon=no ;;
+ *)
+ gcc_cv_func_mmap_anon=yes;;
+ esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_anon" >&5
+$as_echo "$gcc_cv_func_mmap_anon" >&6; }
+ fi
+fi
+
+if test $gcc_cv_func_mmap_file = yes; then
+
+$as_echo "#define HAVE_MMAP_FILE 1" >>confdefs.h
+
+fi
+if test $gcc_cv_func_mmap_dev_zero = yes; then
+
+$as_echo "#define HAVE_MMAP_DEV_ZERO 1" >>confdefs.h
+
+fi
+if test $gcc_cv_func_mmap_anon = yes; then
+
+$as_echo "#define HAVE_MMAP_ANON 1" >>confdefs.h
+
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if test "${ac_cv_c_bigendian+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+# I don't like the default behaviour of WORDS_BIGENDIAN undefined for LE.
+
+
# Check to see if -pthread or -lpthread is needed. Prefer the former.
# In case the pthread.h system header is not found, this test will fail.
# ??? Not needed if linux futexes are used.
@@ -15993,159 +20239,6 @@ $as_echo "#define HAVE_SYNC_BUILTINS 1" >>confdefs.h
fi
-
-ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default"
-if test "x$ac_cv_header_sys_mman_h" = x""yes; then :
- gcc_header_sys_mman_h=yes
-else
- gcc_header_sys_mman_h=no
-fi
-
-
-ac_fn_c_check_func "$LINENO" "mmap" "ac_cv_func_mmap"
-if test "x$ac_cv_func_mmap" = x""yes; then :
- gcc_func_mmap=yes
-else
- gcc_func_mmap=no
-fi
-
-if test "$gcc_header_sys_mman_h" != yes \
- || test "$gcc_func_mmap" != yes; then
- gcc_cv_func_mmap_file=no
- gcc_cv_func_mmap_dev_zero=no
- gcc_cv_func_mmap_anon=no
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether read-only mmap of a plain file works" >&5
-$as_echo_n "checking whether read-only mmap of a plain file works... " >&6; }
-if test "${gcc_cv_func_mmap_file+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- # Add a system to this blacklist if
- # mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
- # memory area containing the same data that you'd get if you applied
- # read() to the same fd. The only system known to have a problem here
- # is VMS, where text files have record structure.
- case "$host_os" in
- vms* | ultrix*)
- gcc_cv_func_mmap_file=no ;;
- *)
- gcc_cv_func_mmap_file=yes;;
- esac
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_file" >&5
-$as_echo "$gcc_cv_func_mmap_file" >&6; }
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap from /dev/zero works" >&5
-$as_echo_n "checking whether mmap from /dev/zero works... " >&6; }
-if test "${gcc_cv_func_mmap_dev_zero+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- # Add a system to this blacklist if it has mmap() but /dev/zero
- # does not exist, or if mmapping /dev/zero does not give anonymous
- # zeroed pages with both the following properties:
- # 1. If you map N consecutive pages in with one call, and then
- # unmap any subset of those pages, the pages that were not
- # explicitly unmapped remain accessible.
- # 2. If you map two adjacent blocks of memory and then unmap them
- # both at once, they must both go away.
- # Systems known to be in this category are Windows (all variants),
- # VMS, and Darwin.
- case "$host_os" in
- vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
- gcc_cv_func_mmap_dev_zero=no ;;
- *)
- gcc_cv_func_mmap_dev_zero=yes;;
- esac
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_dev_zero" >&5
-$as_echo "$gcc_cv_func_mmap_dev_zero" >&6; }
-
- # Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MAP_ANON(YMOUS)" >&5
-$as_echo_n "checking for MAP_ANON(YMOUS)... " >&6; }
-if test "${gcc_cv_decl_map_anon+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#ifndef MAP_ANONYMOUS
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
-int
-main ()
-{
-int n = MAP_ANONYMOUS;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- gcc_cv_decl_map_anon=yes
-else
- gcc_cv_decl_map_anon=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_decl_map_anon" >&5
-$as_echo "$gcc_cv_decl_map_anon" >&6; }
-
- if test $gcc_cv_decl_map_anon = no; then
- gcc_cv_func_mmap_anon=no
- else
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap with MAP_ANON(YMOUS) works" >&5
-$as_echo_n "checking whether mmap with MAP_ANON(YMOUS) works... " >&6; }
-if test "${gcc_cv_func_mmap_anon+set}" = set; then :
- $as_echo_n "(cached) " >&6
-else
- # Add a system to this blacklist if it has mmap() and MAP_ANON or
- # MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
- # doesn't give anonymous zeroed pages with the same properties listed
- # above for use of /dev/zero.
- # Systems known to be in this category are Windows, VMS, and SCO Unix.
- case "$host_os" in
- vms* | cygwin* | pe | mingw* | sco* | udk* )
- gcc_cv_func_mmap_anon=no ;;
- *)
- gcc_cv_func_mmap_anon=yes;;
- esac
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_func_mmap_anon" >&5
-$as_echo "$gcc_cv_func_mmap_anon" >&6; }
- fi
-fi
-
-if test $gcc_cv_func_mmap_file = yes; then
-
-$as_echo "#define HAVE_MMAP_FILE 1" >>confdefs.h
-
-fi
-if test $gcc_cv_func_mmap_dev_zero = yes; then
-
-$as_echo "#define HAVE_MMAP_DEV_ZERO 1" >>confdefs.h
-
-fi
-if test $gcc_cv_func_mmap_anon = yes; then
-
-$as_echo "#define HAVE_MMAP_ANON 1" >>confdefs.h
-
-fi
-
-
-# Add -Wall -Werror if we are using GCC.
-if test "x$GCC" = "xyes"; then
- XCFLAGS="$XCFLAGS -Wall -Werror"
-fi
-
-XCFLAGS="$XCFLAGS $XPCFLAGS"
-
-
-
-
-
# Cleanup and exit.
CFLAGS="$save_CFLAGS"
cat >confcache <<\_ACEOF
@@ -16223,6 +20316,17 @@ $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
fi
rm -f confcache
+# Add -Wall -Werror if we are using GCC.
+if test "x$GCC" = "xyes"; then
+ XCFLAGS="$XCFLAGS -Wall -Werror"
+fi
+
+XCFLAGS="$XCFLAGS $XPCFLAGS"
+
+
+
+
+
if test ${multilib} = yes; then
multilib_arg="--enable-multilib"
else
@@ -16248,6 +20352,14 @@ else
ARCH_X86_FALSE=
fi
+ if test $enable_linux_futex = yes; then
+ ARCH_FUTEX_TRUE=
+ ARCH_FUTEX_FALSE='#'
+else
+ ARCH_FUTEX_TRUE='#'
+ ARCH_FUTEX_FALSE=
+fi
+
ac_config_files="$ac_config_files Makefile testsuite/Makefile libitm.spec"
@@ -16368,6 +20480,10 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
as_fn_error "conditional \"am__fastdepCC\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ as_fn_error "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then
as_fn_error "conditional \"am__fastdepCCAS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -16376,10 +20492,15 @@ if test -z "${BUILD_INFO_TRUE}" && test -z "${BUILD_INFO_FALSE}"; then
as_fn_error "conditional \"BUILD_INFO\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+ as_fn_error "conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+
if test -z "${LIBITM_BUILD_VERSIONED_SHLIB_TRUE}" && test -z "${LIBITM_BUILD_VERSIONED_SHLIB_FALSE}"; then
as_fn_error "conditional \"LIBITM_BUILD_VERSIONED_SHLIB\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -16388,6 +20509,10 @@ 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
fi
+if test -z "${ARCH_FUTEX_TRUE}" && test -z "${ARCH_FUTEX_FALSE}"; then
+ as_fn_error "conditional \"ARCH_FUTEX\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
: ${CONFIG_STATUS=./config.status}
ac_write_fail=0
@@ -17121,52 +21246,99 @@ postdep_objects='`$ECHO "X$postdep_objects" | $Xsed -e "$delay_single_quote_subs
predeps='`$ECHO "X$predeps" | $Xsed -e "$delay_single_quote_subst"`'
postdeps='`$ECHO "X$postdeps" | $Xsed -e "$delay_single_quote_subst"`'
compiler_lib_search_path='`$ECHO "X$compiler_lib_search_path" | $Xsed -e "$delay_single_quote_subst"`'
+LD_CXX='`$ECHO "X$LD_CXX" | $Xsed -e "$delay_single_quote_subst"`'
LD_FC='`$ECHO "X$LD_FC" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_cmds_CXX='`$ECHO "X$old_archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
old_archive_cmds_FC='`$ECHO "X$old_archive_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_CXX='`$ECHO "X$compiler_CXX" | $Xsed -e "$delay_single_quote_subst"`'
compiler_FC='`$ECHO "X$compiler_FC" | $Xsed -e "$delay_single_quote_subst"`'
+GCC_CXX='`$ECHO "X$GCC_CXX" | $Xsed -e "$delay_single_quote_subst"`'
GCC_FC='`$ECHO "X$GCC_FC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "X$lt_prog_compiler_no_builtin_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
lt_prog_compiler_no_builtin_flag_FC='`$ECHO "X$lt_prog_compiler_no_builtin_flag_FC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_wl_CXX='`$ECHO "X$lt_prog_compiler_wl_CXX" | $Xsed -e "$delay_single_quote_subst"`'
lt_prog_compiler_wl_FC='`$ECHO "X$lt_prog_compiler_wl_FC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_pic_CXX='`$ECHO "X$lt_prog_compiler_pic_CXX" | $Xsed -e "$delay_single_quote_subst"`'
lt_prog_compiler_pic_FC='`$ECHO "X$lt_prog_compiler_pic_FC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_prog_compiler_static_CXX='`$ECHO "X$lt_prog_compiler_static_CXX" | $Xsed -e "$delay_single_quote_subst"`'
lt_prog_compiler_static_FC='`$ECHO "X$lt_prog_compiler_static_FC" | $Xsed -e "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o_CXX='`$ECHO "X$lt_cv_prog_compiler_c_o_CXX" | $Xsed -e "$delay_single_quote_subst"`'
lt_cv_prog_compiler_c_o_FC='`$ECHO "X$lt_cv_prog_compiler_c_o_FC" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds_need_lc_CXX='`$ECHO "X$archive_cmds_need_lc_CXX" | $Xsed -e "$delay_single_quote_subst"`'
archive_cmds_need_lc_FC='`$ECHO "X$archive_cmds_need_lc_FC" | $Xsed -e "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes_CXX='`$ECHO "X$enable_shared_with_static_runtimes_CXX" | $Xsed -e "$delay_single_quote_subst"`'
enable_shared_with_static_runtimes_FC='`$ECHO "X$enable_shared_with_static_runtimes_FC" | $Xsed -e "$delay_single_quote_subst"`'
+export_dynamic_flag_spec_CXX='`$ECHO "X$export_dynamic_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
export_dynamic_flag_spec_FC='`$ECHO "X$export_dynamic_flag_spec_FC" | $Xsed -e "$delay_single_quote_subst"`'
+whole_archive_flag_spec_CXX='`$ECHO "X$whole_archive_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
whole_archive_flag_spec_FC='`$ECHO "X$whole_archive_flag_spec_FC" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_needs_object_CXX='`$ECHO "X$compiler_needs_object_CXX" | $Xsed -e "$delay_single_quote_subst"`'
compiler_needs_object_FC='`$ECHO "X$compiler_needs_object_FC" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_new_cmds_CXX='`$ECHO "X$old_archive_from_new_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
old_archive_from_new_cmds_FC='`$ECHO "X$old_archive_from_new_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds_CXX='`$ECHO "X$old_archive_from_expsyms_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
old_archive_from_expsyms_cmds_FC='`$ECHO "X$old_archive_from_expsyms_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+archive_cmds_CXX='`$ECHO "X$archive_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
archive_cmds_FC='`$ECHO "X$archive_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+archive_expsym_cmds_CXX='`$ECHO "X$archive_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
archive_expsym_cmds_FC='`$ECHO "X$archive_expsym_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+module_cmds_CXX='`$ECHO "X$module_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
module_cmds_FC='`$ECHO "X$module_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+module_expsym_cmds_CXX='`$ECHO "X$module_expsym_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
module_expsym_cmds_FC='`$ECHO "X$module_expsym_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+with_gnu_ld_CXX='`$ECHO "X$with_gnu_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`'
with_gnu_ld_FC='`$ECHO "X$with_gnu_ld_FC" | $Xsed -e "$delay_single_quote_subst"`'
+allow_undefined_flag_CXX='`$ECHO "X$allow_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
allow_undefined_flag_FC='`$ECHO "X$allow_undefined_flag_FC" | $Xsed -e "$delay_single_quote_subst"`'
+no_undefined_flag_CXX='`$ECHO "X$no_undefined_flag_CXX" | $Xsed -e "$delay_single_quote_subst"`'
no_undefined_flag_FC='`$ECHO "X$no_undefined_flag_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_CXX='`$ECHO "X$hardcode_libdir_flag_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_libdir_flag_spec_FC='`$ECHO "X$hardcode_libdir_flag_spec_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec_ld_CXX='`$ECHO "X$hardcode_libdir_flag_spec_ld_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_libdir_flag_spec_ld_FC='`$ECHO "X$hardcode_libdir_flag_spec_ld_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_libdir_separator_CXX='`$ECHO "X$hardcode_libdir_separator_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_libdir_separator_FC='`$ECHO "X$hardcode_libdir_separator_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct_CXX='`$ECHO "X$hardcode_direct_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_direct_FC='`$ECHO "X$hardcode_direct_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_direct_absolute_CXX='`$ECHO "X$hardcode_direct_absolute_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_direct_absolute_FC='`$ECHO "X$hardcode_direct_absolute_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_minus_L_CXX='`$ECHO "X$hardcode_minus_L_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_minus_L_FC='`$ECHO "X$hardcode_minus_L_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_shlibpath_var_CXX='`$ECHO "X$hardcode_shlibpath_var_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_shlibpath_var_FC='`$ECHO "X$hardcode_shlibpath_var_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_automatic_CXX='`$ECHO "X$hardcode_automatic_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_automatic_FC='`$ECHO "X$hardcode_automatic_FC" | $Xsed -e "$delay_single_quote_subst"`'
+inherit_rpath_CXX='`$ECHO "X$inherit_rpath_CXX" | $Xsed -e "$delay_single_quote_subst"`'
inherit_rpath_FC='`$ECHO "X$inherit_rpath_FC" | $Xsed -e "$delay_single_quote_subst"`'
+link_all_deplibs_CXX='`$ECHO "X$link_all_deplibs_CXX" | $Xsed -e "$delay_single_quote_subst"`'
link_all_deplibs_FC='`$ECHO "X$link_all_deplibs_FC" | $Xsed -e "$delay_single_quote_subst"`'
+fix_srcfile_path_CXX='`$ECHO "X$fix_srcfile_path_CXX" | $Xsed -e "$delay_single_quote_subst"`'
fix_srcfile_path_FC='`$ECHO "X$fix_srcfile_path_FC" | $Xsed -e "$delay_single_quote_subst"`'
+always_export_symbols_CXX='`$ECHO "X$always_export_symbols_CXX" | $Xsed -e "$delay_single_quote_subst"`'
always_export_symbols_FC='`$ECHO "X$always_export_symbols_FC" | $Xsed -e "$delay_single_quote_subst"`'
+export_symbols_cmds_CXX='`$ECHO "X$export_symbols_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
export_symbols_cmds_FC='`$ECHO "X$export_symbols_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+exclude_expsyms_CXX='`$ECHO "X$exclude_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`'
exclude_expsyms_FC='`$ECHO "X$exclude_expsyms_FC" | $Xsed -e "$delay_single_quote_subst"`'
+include_expsyms_CXX='`$ECHO "X$include_expsyms_CXX" | $Xsed -e "$delay_single_quote_subst"`'
include_expsyms_FC='`$ECHO "X$include_expsyms_FC" | $Xsed -e "$delay_single_quote_subst"`'
+prelink_cmds_CXX='`$ECHO "X$prelink_cmds_CXX" | $Xsed -e "$delay_single_quote_subst"`'
prelink_cmds_FC='`$ECHO "X$prelink_cmds_FC" | $Xsed -e "$delay_single_quote_subst"`'
+file_list_spec_CXX='`$ECHO "X$file_list_spec_CXX" | $Xsed -e "$delay_single_quote_subst"`'
file_list_spec_FC='`$ECHO "X$file_list_spec_FC" | $Xsed -e "$delay_single_quote_subst"`'
+hardcode_action_CXX='`$ECHO "X$hardcode_action_CXX" | $Xsed -e "$delay_single_quote_subst"`'
hardcode_action_FC='`$ECHO "X$hardcode_action_FC" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_lib_search_dirs_CXX='`$ECHO "X$compiler_lib_search_dirs_CXX" | $Xsed -e "$delay_single_quote_subst"`'
compiler_lib_search_dirs_FC='`$ECHO "X$compiler_lib_search_dirs_FC" | $Xsed -e "$delay_single_quote_subst"`'
+predep_objects_CXX='`$ECHO "X$predep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`'
predep_objects_FC='`$ECHO "X$predep_objects_FC" | $Xsed -e "$delay_single_quote_subst"`'
+postdep_objects_CXX='`$ECHO "X$postdep_objects_CXX" | $Xsed -e "$delay_single_quote_subst"`'
postdep_objects_FC='`$ECHO "X$postdep_objects_FC" | $Xsed -e "$delay_single_quote_subst"`'
+predeps_CXX='`$ECHO "X$predeps_CXX" | $Xsed -e "$delay_single_quote_subst"`'
predeps_FC='`$ECHO "X$predeps_FC" | $Xsed -e "$delay_single_quote_subst"`'
+postdeps_CXX='`$ECHO "X$postdeps_CXX" | $Xsed -e "$delay_single_quote_subst"`'
postdeps_FC='`$ECHO "X$postdeps_FC" | $Xsed -e "$delay_single_quote_subst"`'
+compiler_lib_search_path_CXX='`$ECHO "X$compiler_lib_search_path_CXX" | $Xsed -e "$delay_single_quote_subst"`'
compiler_lib_search_path_FC='`$ECHO "X$compiler_lib_search_path_FC" | $Xsed -e "$delay_single_quote_subst"`'
LTCC='$LTCC'
@@ -17238,31 +21410,57 @@ postdep_objects \
predeps \
postdeps \
compiler_lib_search_path \
+LD_CXX \
LD_FC \
+compiler_CXX \
compiler_FC \
+lt_prog_compiler_no_builtin_flag_CXX \
lt_prog_compiler_no_builtin_flag_FC \
+lt_prog_compiler_wl_CXX \
lt_prog_compiler_wl_FC \
+lt_prog_compiler_pic_CXX \
lt_prog_compiler_pic_FC \
+lt_prog_compiler_static_CXX \
lt_prog_compiler_static_FC \
+lt_cv_prog_compiler_c_o_CXX \
lt_cv_prog_compiler_c_o_FC \
+export_dynamic_flag_spec_CXX \
export_dynamic_flag_spec_FC \
+whole_archive_flag_spec_CXX \
whole_archive_flag_spec_FC \
+compiler_needs_object_CXX \
compiler_needs_object_FC \
+with_gnu_ld_CXX \
with_gnu_ld_FC \
+allow_undefined_flag_CXX \
allow_undefined_flag_FC \
+no_undefined_flag_CXX \
no_undefined_flag_FC \
+hardcode_libdir_flag_spec_CXX \
hardcode_libdir_flag_spec_FC \
+hardcode_libdir_flag_spec_ld_CXX \
hardcode_libdir_flag_spec_ld_FC \
+hardcode_libdir_separator_CXX \
hardcode_libdir_separator_FC \
+fix_srcfile_path_CXX \
fix_srcfile_path_FC \
+exclude_expsyms_CXX \
exclude_expsyms_FC \
+include_expsyms_CXX \
include_expsyms_FC \
+file_list_spec_CXX \
file_list_spec_FC \
+compiler_lib_search_dirs_CXX \
compiler_lib_search_dirs_FC \
+predep_objects_CXX \
predep_objects_FC \
+postdep_objects_CXX \
postdep_objects_FC \
+predeps_CXX \
predeps_FC \
+postdeps_CXX \
postdeps_FC \
+compiler_lib_search_path_CXX \
compiler_lib_search_path_FC; do
case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
*[\\\\\\\`\\"\\\$]*)
@@ -17293,14 +21491,23 @@ postuninstall_cmds \
finish_cmds \
sys_lib_search_path_spec \
sys_lib_dlsearch_path_spec \
+old_archive_cmds_CXX \
old_archive_cmds_FC \
+old_archive_from_new_cmds_CXX \
old_archive_from_new_cmds_FC \
+old_archive_from_expsyms_cmds_CXX \
old_archive_from_expsyms_cmds_FC \
+archive_cmds_CXX \
archive_cmds_FC \
+archive_expsym_cmds_CXX \
archive_expsym_cmds_FC \
+module_cmds_CXX \
module_cmds_FC \
+module_expsym_cmds_CXX \
module_expsym_cmds_FC \
+export_symbols_cmds_CXX \
export_symbols_cmds_FC \
+prelink_cmds_CXX \
prelink_cmds_FC; do
case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in
*[\\\\\\\`\\"\\\$]*)
@@ -17340,6 +21547,8 @@ fi
+
+
GCC="$GCC"
CC="$CC"
acx_cv_header_stdint="$acx_cv_header_stdint"
@@ -18110,7 +22319,7 @@ $as_echo X"$file" |
# The names of the tagged configurations supported by this script.
-available_tags="FC "
+available_tags="CXX FC "
# ### BEGIN LIBTOOL CONFIG
@@ -18712,6 +22921,159 @@ _LT_EOF
cat <<_LT_EOF >> "$ofile"
+# ### BEGIN LIBTOOL TAG CONFIG: CXX
+
+# The linker used to build libraries.
+LD=$lt_LD_CXX
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds_CXX
+
+# A language specific compiler.
+CC=$lt_compiler_CXX
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC_CXX
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl_CXX
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic_CXX
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static_CXX
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc_CXX
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object_CXX
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds_CXX
+archive_expsym_cmds=$lt_archive_expsym_cmds_CXX
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds_CXX
+module_expsym_cmds=$lt_module_expsym_cmds_CXX
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld_CXX
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag_CXX
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag_CXX
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX
+
+# If ld is used when linking, flag to hardcode \$libdir into a binary
+# during linking. This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct_CXX
+
+# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \${shlibpath_var} if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute_CXX
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L_CXX
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic_CXX
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath_CXX
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs_CXX
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path=$lt_fix_srcfile_path_CXX
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols_CXX
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds_CXX
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms_CXX
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms_CXX
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds_CXX
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec_CXX
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action_CXX
+
+# The directories searched by this compiler when creating a shared library.
+compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX
+
+# Dependencies to place before and after the objects being linked to
+# create a shared library.
+predep_objects=$lt_predep_objects_CXX
+postdep_objects=$lt_postdep_objects_CXX
+predeps=$lt_predeps_CXX
+postdeps=$lt_postdeps_CXX
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_compiler_lib_search_path_CXX
+
+# ### END LIBTOOL TAG CONFIG: CXX
+_LT_EOF
+
+
+ cat <<_LT_EOF >> "$ofile"
+
# ### BEGIN LIBTOOL TAG CONFIG: FC
# The linker used to build libraries.
diff --git a/libitm/configure.ac b/libitm/configure.ac
index 577a5f7c5a9..4c732a14b9c 100644
--- a/libitm/configure.ac
+++ b/libitm/configure.ac
@@ -103,6 +103,7 @@ AC_SUBST(toolexeclibdir)
m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
m4_define([_AC_ARG_VAR_PRECIOUS],[])
AC_PROG_CC
+AC_PROG_CXX
AM_PROG_AS
m4_rename_force([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
@@ -154,6 +155,15 @@ AC_CHECK_HEADERS(unistd.h semaphore.h sys/time.h malloc.h)
GCC_HEADER_STDINT(gstdint.h)
+GCC_AC_FUNC_MMAP_BLACKLIST
+
+AC_C_BIGENDIAN
+# I don't like the default behaviour of WORDS_BIGENDIAN undefined for LE.
+AH_BOTTOM(
+[#ifndef WORDS_BIGENDIAN
+#define WORDS_BIGENDIAN 0
+#endif])
+
# Check to see if -pthread or -lpthread is needed. Prefer the former.
# In case the pthread.h system header is not found, this test will fail.
# ??? Not needed if linux futexes are used.
@@ -210,7 +220,9 @@ CFLAGS="$save_CFLAGS $XCFLAGS"
# had a chance to set XCFLAGS.
LIBITM_CHECK_SYNC_BUILTINS
-GCC_AC_FUNC_MMAP_BLACKLIST
+# Cleanup and exit.
+CFLAGS="$save_CFLAGS"
+AC_CACHE_SAVE
# Add -Wall -Werror if we are using GCC.
if test "x$GCC" = "xyes"; then
@@ -223,10 +235,6 @@ AC_SUBST(config_path)
AC_SUBST(XCFLAGS)
AC_SUBST(XLDFLAGS)
-# Cleanup and exit.
-CFLAGS="$save_CFLAGS"
-AC_CACHE_SAVE
-
if test ${multilib} = yes; then
multilib_arg="--enable-multilib"
else
@@ -245,6 +253,7 @@ fi
AC_SUBST(link_itm)
AM_CONDITIONAL([ARCH_X86], [test "$ARCH" = x86])
+AM_CONDITIONAL([ARCH_FUTEX], [test $enable_linux_futex = yes])
AC_CONFIG_FILES(Makefile testsuite/Makefile libitm.spec)
AC_OUTPUT
diff --git a/libitm/configure.tgt b/libitm/configure.tgt
index 5aef3fa4e44..5293fa96f1e 100644
--- a/libitm/configure.tgt
+++ b/libitm/configure.tgt
@@ -84,7 +84,7 @@ case "${target_cpu}" in
esac
# Since we require POSIX threads, assume a POSIX system by default.
-config_path="$ARCH posix"
+config_path="$ARCH posix generic"
# Other system configury
case "${target}" in
@@ -100,15 +100,15 @@ case "${target}" in
;;
*-*-mingw32*)
- config_path="$ARCH mingw32 posix"
+ config_path="$ARCH mingw32 posix generic"
;;
*-*-solaris2.[56]*)
- config_path="$ARCH posix95 posix"
+ config_path="$ARCH posix95 posix generic"
XLDFLAGS="${XLDFLAGS} -lposix4"
;;
*-*-darwin*)
- config_path="$ARCH bsd posix"
+ config_path="$ARCH bsd posix generic"
;;
esac
diff --git a/libitm/copymask.c b/libitm/copymask.c
deleted file mode 100644
index 2a92710a3a9..00000000000
--- a/libitm/copymask.c
+++ /dev/null
@@ -1,195 +0,0 @@
-/* Copyright (C) 2009 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"
-
-#if ALLOW_UNMASKED_STORES
-static uint32_t const bit_to_byte_mask[16] =
-{
- 0x00000000,
- 0x000000ff,
- 0x0000ff00,
- 0x0000ffff,
- 0x00ff0000,
- 0x00ff00ff,
- 0x00ffff00,
- 0x00ffffff,
- 0xff000000,
- 0xff0000ff,
- 0xff00ff00,
- 0xff00ffff,
- 0xffff0000,
- 0xffff00ff,
- 0xffffff00,
- 0xffffffff
-};
-
-static void __attribute__((always_inline))
-copy_mask_w (gtm_word * __restrict d,
- const gtm_word * __restrict s,
- gtm_cacheline_mask m)
-{
- gtm_cacheline_mask tm = (1 << sizeof (gtm_word)) - 1;
-
- if (m & tm)
- {
- if ((m & tm) == tm)
- *d = *s;
- else
- {
- gtm_cacheline_mask bm;
-
- switch (sizeof (gtm_word))
- {
- case 8:
- bm = bit_to_byte_mask[(m >> 4) & 15];
- bm <<= 4 * sizeof (gtm_word);
- bm |= bit_to_byte_mask[m & 15];
- break;
- case 4:
- bm = bit_to_byte_mask[m & 15];
- break;
- default:
- __builtin_trap ();
- }
- *d = (*d & ~bm) | (*s & bm);
- }
- }
-}
-
-void
-gtm_cacheline_copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m)
-{
- const size_t n = sizeof (gtm_word);
- size_t i;
-
- if (m == (gtm_cacheline_mask)-1)
- {
- gtm_cacheline_copy (d, s);
- return;
- }
- if (__builtin_expect (m == 0), 0)
- return;
-
- for (i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n)
- copy_mask_w (&d->w[i], &s->w[i], m);
-}
-
-#else
-static inline void __attribute__((always_inline))
-copy_mask_1 (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m, size_t ofs, size_t idx)
-{
- if (m & (1ul << ofs))
- d->b[idx] = s->b[idx];
-}
-
-static inline void __attribute__((always_inline))
-copy_mask_2 (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m, size_t ofs, size_t idx)
-{
- gtm_cacheline_mask tm = 3ul << ofs;
- if (m & tm)
- {
- if ((m & tm) == tm)
- d->u16[idx] = s->u16[idx];
- else
- {
- copy_mask_1 (d, s, m, ofs, idx*2);
- copy_mask_1 (d, s, m, ofs + 1, idx*2 + 1);
- }
- }
-}
-
-static inline void __attribute__((always_inline))
-copy_mask_4 (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m, size_t ofs, size_t idx)
-{
- gtm_cacheline_mask tm = 15ul << ofs;
- if (m & tm)
- {
- if ((m & tm) == tm)
- d->u32[idx] = s->u32[idx];
- else
- {
- copy_mask_2 (d, s, m, ofs, idx*2);
- copy_mask_2 (d, s, m, ofs + 2, idx*2 + 1);
- }
- }
-}
-
-static inline void __attribute__((always_inline))
-copy_mask_8 (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m, size_t ofs, size_t idx)
-{
- gtm_cacheline_mask tm = 0xfful << ofs;
- if (m & tm)
- {
- if ((m & tm) == tm)
- d->u64[idx] = s->u64[idx];
- else
- {
- copy_mask_4 (d, s, m, ofs, idx*2);
- copy_mask_4 (d, s, m, ofs + 4, idx*2 + 1);
- }
- }
-}
-
-void
-gtm_cacheline_copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m)
-{
- const size_t n = sizeof (gtm_word);
- size_t i;
-
- if (m == (gtm_cacheline_mask)-1)
- {
- gtm_cacheline_copy (d, s);
- return;
- }
- if (__builtin_expect (m == 0, 0))
- return;
-
- for (i = 0; i < CACHELINE_SIZE / n; ++i, m >>= n)
- switch (n)
- {
- case 8:
- copy_mask_8 (d, s, m, 0, i);
- break;
- case 4:
- copy_mask_4 (d, s, m, 0, i);
- break;
- default:
- __builtin_trap ();
- }
-}
-
-#endif /* ALLOW_UNMASKED_STORES */
diff --git a/libitm/eh_cpp.c b/libitm/eh_cpp.cc
index bb6c71d9808..bd83f7295d8 100644
--- a/libitm/eh_cpp.c
+++ b/libitm/eh_cpp.cc
@@ -24,17 +24,23 @@
#include "libitm_i.h"
+using namespace GTM;
+
/* Everything from libstdc++ is weak, to avoid requiring that library
to be linked into plain C applications using libitm.so. */
#define WEAK __attribute__((weak))
+extern "C" {
+
extern void *__cxa_allocate_exception (size_t) WEAK;
extern void __cxa_throw (void *, void *, void *) WEAK;
extern void *__cxa_begin_catch (void *) WEAK;
extern void *__cxa_end_catch (void) WEAK;
extern void __cxa_tm_cleanup (void *, void *, unsigned int) WEAK;
+}
+
void *
_ITM_cxa_allocate_exception (size_t size)
@@ -66,16 +72,14 @@ _ITM_cxa_end_catch (void)
}
void
-GTM_revert_cpp_exceptions (void)
+GTM::gtm_transaction::revert_cpp_exceptions (void)
{
- struct gtm_transaction *tx = gtm_tx();
-
- if (tx->cxa_unthrown || tx->cxa_catch_count)
+ if (this->cxa_unthrown || this->cxa_catch_count)
{
- __cxa_tm_cleanup (tx->cxa_unthrown, tx->eh_in_flight,
- tx->cxa_catch_count);
- tx->cxa_catch_count = 0;
- tx->cxa_unthrown = NULL;
- tx->eh_in_flight = NULL;
+ __cxa_tm_cleanup (this->cxa_unthrown, this->eh_in_flight,
+ this->cxa_catch_count);
+ this->cxa_catch_count = 0;
+ this->cxa_unthrown = NULL;
+ this->eh_in_flight = NULL;
}
}
diff --git a/libitm/libitm.h b/libitm/libitm.h
index ac07a402b3b..b1e0bca1298 100644
--- a/libitm/libitm.h
+++ b/libitm/libitm.h
@@ -32,6 +32,9 @@
#include <stdbool.h>
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
#ifdef __i386__
# define ITM_REGPARM __attribute__((regparm(2)))
@@ -264,4 +267,21 @@ extern void _ITM_memsetW(void *, int, size_t) ITM_REGPARM;
extern void _ITM_memsetWaR(void *, int, size_t) ITM_REGPARM;
extern void _ITM_memsetWaW(void *, int, size_t) ITM_REGPARM;
+// ??? These are not yet in the official spec; still work-in-progress.
+
+extern void *_ITM_getTMCloneOrIrrevokable (void *) ITM_REGPARM;
+extern void *_ITM_getTMCloneSafe (void *) ITM_REGPARM;
+extern void _ITM_registerTMCloneTable (void *, size_t);
+extern void _ITM_deregisterTMCloneTable (void *);
+
+extern void *_ITM_cxa_allocate_exception (size_t);
+extern void _ITM_cxa_throw (void *obj, void *tinfo, void *dest);
+extern void *_ITM_cxa_begin_catch (void *exc_ptr);
+extern void _ITM_cxa_end_catch (void);
+extern void _ITM_commitTransactionEH(void *exc_ptr) ITM_REGPARM;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
#endif /* LIBITM_H */
diff --git a/libitm/libitm_i.h b/libitm/libitm_i.h
index d7dcdec56ad..52b6a15c6f5 100644
--- a/libitm/libitm_i.h
+++ b/libitm/libitm_i.h
@@ -30,222 +30,113 @@
#define LIBITM_I_H 1
#include "libitm.h"
-
#include "config.h"
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
#include <unwind.h>
+#include <type_traits>
#define UNUSED __attribute__((unused))
-
-/* Control how gtm_copy_cacheline_mask operates. If set, we use byte masking
- to update D, which *does* write to bytes not affected by the mask. It's
- unclear if this optimization is correct. */
-#define ALLOW_UNMASKED_STORES 0
-
+#define ALWAYS_INLINE __attribute__((always_inline))
#ifdef HAVE_ATTRIBUTE_VISIBILITY
-# pragma GCC visibility push(hidden)
-#endif
-
-#include "target.h"
-#include "rwlock.h"
-#include "aatree.h"
-
-/* A gtm_cacheline_mask stores a modified bit for every modified byte
- in the cacheline with which it is associated. */
-#if CACHELINE_SIZE == 8
-typedef uint8_t gtm_cacheline_mask;
-#elif CACHELINE_SIZE == 16
-typedef uint16_t gtm_cacheline_mask;
-#elif CACHELINE_SIZE == 32
-typedef uint32_t gtm_cacheline_mask;
-#elif CACHELINE_SIZE == 64
-typedef uint64_t gtm_cacheline_mask;
+# define HIDDEN __attribute__((visibility("hidden")))
#else
-#error "Unsupported cacheline size"
+# define HIDDEN
#endif
-typedef unsigned int gtm_word __attribute__((mode (word)));
-
-/* A cacheline. The smallest unit with which locks are associated. */
-typedef 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)];
-
-#if defined(__i386__) || defined(__x86_64__)
- /* ??? The definitions of gtm_cacheline_copy{,_mask} require all three
- of these types depending on the implementation, making it difficult
- to hide these inside the target header file. */
-# 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)];
-# endif
-#endif
-} gtm_cacheline;
-
-/* A "page" worth of saved cachelines plus modification masks. This
- arrangement is intended to minimize the overhead of alignment. The
- PAGE_SIZE defined by the target must be a constant for this to work,
- which means that this definition may not be the same as the real
- system page size. */
-
-#define CACHELINES_PER_PAGE \
- ((PAGE_SIZE - sizeof(void *)) \
- / (CACHELINE_SIZE + sizeof(gtm_cacheline_mask)))
+#define likely(X) __builtin_expect((X) != 0, 1)
+#define unlikely(X) __builtin_expect((X), 0)
-typedef struct gtm_cacheline_page
-{
- gtm_cacheline lines[CACHELINES_PER_PAGE] __attribute__((aligned(PAGE_SIZE)));
- gtm_cacheline_mask masks[CACHELINES_PER_PAGE];
- struct gtm_cacheline_page *prev;
-} gtm_cacheline_page;
-
-static inline gtm_cacheline_page *
-gtm_page_for_line (gtm_cacheline *c)
-{
- return (gtm_cacheline_page *)((uintptr_t)c & -PAGE_SIZE);
-}
+namespace GTM HIDDEN {
-static inline gtm_cacheline_mask *
-gtm_mask_for_line (gtm_cacheline *c)
-{
- gtm_cacheline_page *p = gtm_page_for_line (c);
- size_t index = c - &p->lines[0];
- return &p->masks[index];
-}
-
-/* A read lock function locks a cacheline. PTR must be cacheline aligned.
- The return value is the cacheline address (equal to PTR for a write-through
- implementation, and something else for a write-back implementation). */
-typedef gtm_cacheline *(*gtm_read_lock_fn)(uintptr_t cacheline);
-
-/* A write lock function locks a cacheline. PTR must be cacheline aligned.
- The return value is a pair of the cacheline address and a mask that must
- be updated with the bytes that are subsequently modified. We hope that
- the target implements small structure return efficiently so that this
- comes back in a pair of registers. If not, we're not really worse off
- than returning the second value via a second argument to the function. */
-
-typedef struct gtm_cacheline_mask_pair
-{
- gtm_cacheline *line;
- gtm_cacheline_mask *mask;
-} gtm_cacheline_mask_pair;
-
-typedef gtm_cacheline_mask_pair (*gtm_write_lock_fn)(uintptr_t cacheline);
-
-/* A versioned write lock on a cacheline. This must be wide enough to
- store a pointer, and preferably wide enough to avoid overflowing the
- version counter. Thus we use a "word", which should be 64-bits on
- 64-bit systems even when their pointer size is forced smaller. */
-typedef gtm_word gtm_stmlock;
-
-/* This has to be the same size as gtm_stmlock, we just use this name
- for documentation purposes. */
-typedef gtm_word gtm_version;
-
-/* The maximum value a version number can have. This is a consequence
- of having the low bit of gtm_stmlock reserved for the owned bit. */
-#define GTM_VERSION_MAX (~(gtm_version)0 >> 1)
-
-/* A value that may be used to indicate "uninitialized" for a version. */
-#define GTM_VERSION_INVALID (~(gtm_version)0)
-
-/* This bit is set when the write lock is held. When set, the balance of
- the bits in the lock is a pointer that references STM backend specific
- data; it is up to the STM backend to determine if this thread holds the
- lock. If this bit is clear, the balance of the bits are the last
- version number committed to the cacheline. */
-static inline bool
-gtm_stmlock_owned_p (gtm_stmlock lock)
-{
- return lock & 1;
-}
+using namespace std;
-static inline gtm_stmlock
-gtm_stmlock_set_owned (void *data)
-{
- return (gtm_stmlock)(uintptr_t)data | 1;
-}
+// A helper template for accessing an unsigned integral of SIZE bytes.
+template<size_t SIZE> struct sized_integral { };
+template<> struct sized_integral<1> { typedef uint8_t type; };
+template<> struct sized_integral<2> { typedef uint16_t type; };
+template<> struct sized_integral<4> { typedef uint32_t type; };
+template<> struct sized_integral<8> { typedef uint64_t type; };
-static inline void *
-gtm_stmlock_get_addr (gtm_stmlock lock)
-{
- return (void *)((uintptr_t)lock & ~(uintptr_t)1);
-}
+typedef unsigned int gtm_word __attribute__((mode (word)));
-static inline gtm_version
-gtm_stmlock_get_version (gtm_stmlock lock)
-{
- return lock >> 1;
-}
+// Locally defined protected allocation functions.
+//
+// To avoid dependency on libstdc++ new/delete, as well as to not
+// interfere with the wrapping of the global new/delete we wrap for
+// the user in alloc_cpp.cc, use class-local versions that defer
+// to malloc/free. Recall that operator new/delete does not go through
+// normal lookup and so we cannot simply inject a version into the
+// GTM namespace.
-static inline gtm_stmlock
-gtm_stmlock_set_version (gtm_version ver)
-{
- return ver << 1;
-}
+extern void * xmalloc (size_t s) __attribute__((malloc, nothrow));
+extern void * xrealloc (void *p, size_t s) __attribute__((malloc, nothrow));
-/* We use a fixed set of locks for all memory, hashed into the
- following table. */
-#define LOCK_ARRAY_SIZE (1024 * 1024)
-extern gtm_stmlock gtm_stmlock_array[LOCK_ARRAY_SIZE];
+} // namespace GTM
-static inline gtm_stmlock *
-gtm_get_stmlock (uintptr_t addr)
-{
- size_t idx = (addr / CACHELINE_SIZE) % LOCK_ARRAY_SIZE;
- return gtm_stmlock_array + idx;
-}
+#include "target.h"
+#include "rwlock.h"
+#include "aatree.h"
+#include "cacheline.h"
+#include "cachepage.h"
+#include "stmlock.h"
-/* The current global version number. */
-extern gtm_version gtm_clock;
+namespace GTM HIDDEN {
-/* A dispatch table parameterizes the implementation of the STM. */
-typedef struct gtm_dispatch
+// A dispatch table parameterizes the implementation of the STM.
+struct gtm_dispatch
{
- gtm_read_lock_fn R;
- gtm_read_lock_fn RaR;
- gtm_read_lock_fn RaW;
- gtm_read_lock_fn RfW;
-
- gtm_write_lock_fn W;
- gtm_write_lock_fn WaR;
- gtm_write_lock_fn WaW;
-
- bool (*trycommit) (void);
- void (*rollback) (void);
- void (*init) (bool);
- void (*fini) (void);
-
- bool write_through;
-} gtm_dispatch;
-
-
-/* These values define a mask used in gtm_transaction.state. */
-#define STATE_READONLY 0x0001
-#define STATE_SERIAL 0x0002
-#define STATE_IRREVOKABLE 0x0004
-#define STATE_ABORTING 0x0008
-
-/* These values are given to GTM_restart_transaction and indicate the
- reason for the restart. The reason is used to decide what STM
- implementation should be used during the next iteration. */
-typedef enum gtm_restart_reason
+ public:
+ enum lock_type { NOLOCK, R, RaR, RaW, RfW, W, WaR, WaW };
+
+ struct mask_pair
+ {
+ gtm_cacheline *line;
+ gtm_cacheline_mask *mask;
+
+ mask_pair() = default;
+ mask_pair(gtm_cacheline *l, gtm_cacheline_mask *m) : line(l), mask(m) { }
+ };
+
+ private:
+ // Disallow copies
+ gtm_dispatch(const gtm_dispatch &) = delete;
+ gtm_dispatch& operator=(const gtm_dispatch &) = delete;
+
+ public:
+ // The default version of these is pass-through. This merely gives the
+ // a single location to instantiate the base class vtable.
+ virtual const gtm_cacheline *read_lock(const gtm_cacheline *, lock_type);
+ virtual mask_pair write_lock(gtm_cacheline *, lock_type);
+
+ virtual bool trycommit() = 0;
+ virtual void rollback() = 0;
+ virtual void reinit() = 0;
+
+ // Use fini instead of dtor to support a static subclasses that uses
+ // a unique object and so we don't want to destroy it from common code.
+ virtual void fini() = 0;
+
+ bool read_only () const { return m_read_only; }
+ bool write_through() const { return m_write_through; }
+
+ static void *operator new(size_t s) { return xmalloc (s); }
+ static void operator delete(void *p) { free (p); }
+
+ protected:
+ const bool m_read_only;
+ const bool m_write_through;
+ gtm_dispatch(bool ro, bool wt) : m_read_only(ro), m_write_through(wt) { }
+
+ static gtm_cacheline_mask mask_sink;
+};
+
+// These values are given to GTM_restart_transaction and indicate the
+// reason for the restart. The reason is used to decide what STM
+// implementation should be used during the next iteration.
+enum gtm_restart_reason
{
RESTART_REALLOCATE,
RESTART_LOCKED_READ,
@@ -253,220 +144,140 @@ typedef enum gtm_restart_reason
RESTART_VALIDATE_READ,
RESTART_VALIDATE_WRITE,
RESTART_VALIDATE_COMMIT,
+ RESTART_SERIAL_IRR,
RESTART_NOT_READONLY,
NUM_RESTARTS
-} gtm_restart_reason;
+};
+// This type is private to alloc.c.
+struct gtm_alloc_action;
-/* This type is private to local.c. */
+// This type is private to local.c.
struct gtm_local_undo;
-/* This type is private to useraction.c. */
+// This type is private to useraction.c.
struct gtm_user_action;
-/* This type is private to the STM implementation. */
-struct gtm_method;
-
-
-/* All data relevant to a single transaction. */
-typedef struct gtm_transaction
+// All data relevant to a single transaction.
+struct gtm_transaction
{
- /* The jump buffer by which GTM_longjmp restarts the transaction.
- This field *must* be at the beginning of the transaction. */
+ // The jump buffer by which GTM_longjmp restarts the transaction.
+ // This field *must* be at the beginning of the transaction.
gtm_jmpbuf jb;
- /* Data used by local.c for the local memory undo log. */
+ // Data used by local.c for the local memory undo log.
struct gtm_local_undo **local_undo;
size_t n_local_undo;
size_t size_local_undo;
- /* Data used by alloc.c for the malloc/free undo log. */
- aa_tree alloc_actions;
+ // Data used by alloc.c for the malloc/free undo log.
+ aa_tree<uintptr_t, gtm_alloc_action> alloc_actions;
- /* Data used by useraction.c for the user defined undo log. */
+ // Data used by useraction.c for the user defined undo log.
struct gtm_user_action *commit_actions;
struct gtm_user_action *undo_actions;
- /* Data used by the STM implementation. */
- struct gtm_method *m;
-
- /* A pointer to the "outer" transaction. */
+ // A pointer to the "outer" transaction.
struct gtm_transaction *prev;
- /* A numerical identifier for this transaction. */
+ // A numerical identifier for this transaction.
_ITM_transactionId_t id;
- /* The _ITM_codeProperties of this transaction as given by the compiler. */
+ // The _ITM_codeProperties of this transaction as given by the compiler.
uint32_t prop;
- /* The nesting depth of this transaction. */
+ // The nesting depth of this transaction.
uint32_t nesting;
- /* A mask of bits indicating the current status of the transaction. */
+ // Set if this transaction owns the serial write lock.
+ static const uint32_t STATE_SERIAL = 0x0001;
+ // Set if the serial-irrevocable dispatch table is installed.
+ // Implies that no logging is being done, and abort is not possible.
+ static const uint32_t STATE_IRREVOCABLE = 0x0002;
+ // Set if we're in the process of aborting the transaction. This is
+ // used when _ITM_rollbackTransaction is called to begin the abort
+ // and ends with _ITM_commitTransaction.
+ static const uint32_t STATE_ABORTING = 0x0004;
+
+ // A bitmask of the above.
uint32_t state;
- /* Data used by eh_cpp.c for managing exceptions within the transaction. */
+ // Data used by eh_cpp.c for managing exceptions within the transaction.
uint32_t cxa_catch_count;
void *cxa_unthrown;
void *eh_in_flight;
- /* Data used by retry.c for deciding what STM implementation should
- be used for the next iteration of the transaction. */
+ // Data used by retry.c for deciding what STM implementation should
+ // be used for the next iteration of the transaction.
uint32_t restart_reason[NUM_RESTARTS];
uint32_t restart_total;
-} gtm_transaction;
-/* The maximum number of free gtm_transaction structs to be kept.
- This number must be greater than 1 in order for transaction abort
- to be handled properly. */
-#define MAX_FREE_TX 8
+ // The lock that provides access to serial mode. Non-serialized
+ // transactions acquire read locks; a serialized transaction aquires
+ // a write lock.
+ static gtm_rwlock serial_lock;
-/* All thread-local data required by the entire library. */
-typedef struct gtm_thread
-{
-#ifndef HAVE_ARCH_GTM_THREAD_TX
- /* The currently active transaction. Elided if the target provides
- some efficient mechanism for storing this. */
- gtm_transaction *tx;
-#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. */
- const gtm_dispatch *disp;
-#endif
+ // In alloc.cc
+ void commit_allocations (bool);
+ void record_allocation (void *, size_t, void (*)(void *));
+ void forget_allocation (void *, void (*)(void *));
+ size_t get_allocation_size (void *);
- /* A queue of free gtm_transaction structs. */
- gtm_transaction *free_tx[MAX_FREE_TX];
- unsigned free_tx_idx, free_tx_count;
-
- /* The value returned by _ITM_getThreadnum to identify this thread. */
- /* ??? At present, this is densely allocated beginning with 1 and
- we don't bother filling in this value until it is requested.
- Which means that the value returned is, as far as the user is
- concerned, essentially arbitrary. We wouldn't need this at all
- if we knew that pthread_t is integral and fits into an int. */
- /* ??? Consider using gettid on Linux w/ NPTL. At least that would
- be a value meaningful to the user. */
- int thread_num;
-} gtm_thread;
-
-/* Don't access this variable directly; use the functions below. */
-extern __thread gtm_thread _gtm_thr;
-
-#include "target_i.h"
-
-#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 void setup_gtm_thr(void) { }
-static inline gtm_thread *gtm_thr(void) { return &_gtm_thr; }
-#endif
+ // In beginend.cc
+ void rollback ();
+ bool trycommit ();
+ bool trycommit_and_finalize ();
+ void restart (gtm_restart_reason) ITM_NORETURN;
-#ifndef HAVE_ARCH_GTM_THREAD_TX
-/* If the target does not provide optimized access to the currently
- active transaction, simply access via GTM_THR. */
-static inline gtm_transaction * gtm_tx(void) { return gtm_thr()->tx; }
-static inline void set_gtm_tx(gtm_transaction *x) { gtm_thr()->tx = x; }
-#endif
+ // Invoked from assembly language, thus the "asm" specifier on
+ // the name, avoiding complex name mangling.
+ static uint32_t begin_transaction(uint32_t, const gtm_jmpbuf *)
+ __asm__("GTM_begin_transaction");
-#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 const gtm_dispatch * gtm_disp(void) { return gtm_thr()->disp; }
-static inline void set_gtm_disp(const gtm_dispatch *x) { gtm_thr()->disp = x; }
-#endif
+ // In eh_cpp.cc
+ void revert_cpp_exceptions ();
-#ifndef HAVE_ARCH_GTM_CACHELINE_COPY
-/* Copy S to D, with S and D both aligned no overlap. */
-static inline void
-gtm_cacheline_copy (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s)
-{
- *d = *s;
-}
-#endif
+ // In local.cc
+ void commit_local (void);
+ void rollback_local (void);
-/* Similarly, but only modify bytes with bits set in M. */
-extern void gtm_cacheline_copy_mask (gtm_cacheline * __restrict d,
- const gtm_cacheline * __restrict s,
- gtm_cacheline_mask m);
+ // In retry.cc
+ void decide_retry_strategy (gtm_restart_reason);
-#ifndef HAVE_ARCH_GTM_CCM_WRITE_BARRIER
-/* A write barrier to emit after gtm_copy_cacheline_mask. */
-static inline void
-gtm_ccm_write_barrier (void)
-{
- atomic_write_barrier ();
-}
-#endif
+ // In serial.cc
+ void serialirr_mode ();
-/* The lock that provides access to serial mode. Non-serialized transactions
- acquire read locks; the serialized transaction aquires a write lock. */
-extern gtm_rwlock gtm_serial_lock;
+ // In useraction.cc
+ static void run_actions (struct gtm_user_action **);
+ static void free_actions (struct gtm_user_action **);
+};
-/* An unscaled count of the number of times we should spin attempting to
- acquire locks before we block the current thread and defer to the OS.
- This variable isn't used when the standard POSIX lock implementations
- are used. */
-extern uint64_t gtm_spin_count_var;
+} // namespace GTM
-extern uint32_t GTM_begin_transaction(uint32_t, const gtm_jmpbuf *);
-extern uint32_t GTM_longjmp (const gtm_jmpbuf *, uint32_t, uint32_t)
- ITM_NORETURN;
+#include "tls.h"
-extern void GTM_commit_local (void);
-extern void GTM_rollback_local (void);
-extern void GTM_LB (const void *, size_t) ITM_REGPARM;
+namespace GTM HIDDEN {
-extern void GTM_serialmode (bool, bool);
-extern void GTM_decide_retry_strategy (gtm_restart_reason);
-extern void GTM_restart_transaction (gtm_restart_reason) ITM_NORETURN;
-
-extern void GTM_run_actions (struct gtm_user_action **);
-extern void GTM_free_actions (struct gtm_user_action **);
-
-extern void GTM_record_allocation (void *, size_t, void (*)(void *));
-extern void GTM_forget_allocation (void *, void (*)(void *));
-extern size_t GTM_get_allocation_size (void *);
-extern void GTM_commit_allocations (bool);
-
-extern void GTM_revert_cpp_exceptions (void);
-
-extern gtm_cacheline_page *GTM_page_alloc (void);
-extern void GTM_page_release (gtm_cacheline_page *, gtm_cacheline_page *);
-
-extern gtm_cacheline *GTM_null_read_lock (uintptr_t);
-extern gtm_cacheline_mask_pair GTM_null_write_lock (uintptr_t);
-
-static inline gtm_version
-gtm_get_clock (void)
-{
- gtm_version r;
-
- __sync_synchronize ();
- r = gtm_clock;
- atomic_read_barrier ();
-
- return r;
-}
+// An unscaled count of the number of times we should spin attempting to
+// acquire locks before we block the current thread and defer to the OS.
+// This variable isn't used when the standard POSIX lock implementations
+// are used.
+extern uint64_t gtm_spin_count_var;
-static inline gtm_version
-gtm_inc_clock (void)
-{
- gtm_version r = __sync_add_and_fetch (&gtm_clock, 1);
+extern "C" uint32_t GTM_longjmp (const gtm_jmpbuf *, uint32_t, uint32_t)
+ ITM_NORETURN;
- /* ??? Ought to handle wraparound for 32-bit. */
- if (sizeof(r) < 8 && r > GTM_VERSION_MAX)
- abort ();
+extern "C" void GTM_LB (const void *, size_t) ITM_REGPARM;
- return r;
-}
+extern void GTM_error (const char *fmt, ...)
+ __attribute__((format (printf, 1, 2)));
+extern void GTM_fatal (const char *fmt, ...)
+ __attribute__((noreturn, format (printf, 1, 2)));
-extern const gtm_dispatch dispatch_wbetl;
-extern const gtm_dispatch dispatch_readonly;
+extern gtm_dispatch *dispatch_wbetl();
+extern gtm_dispatch *dispatch_readonly();
+extern gtm_dispatch *dispatch_serial();
-#ifdef HAVE_ATTRIBUTE_VISIBILITY
-# pragma GCC visibility pop
-#endif
+} // namespace GTM
-#endif /* LIBITM_I_H */
+#endif // LIBITM_I_H
diff --git a/libitm/local.c b/libitm/local.cc
index 17358ad44ae..31c35222519 100644
--- a/libitm/local.c
+++ b/libitm/local.cc
@@ -24,42 +24,41 @@
#include "libitm_i.h"
+namespace GTM HIDDEN {
-typedef struct gtm_local_undo
+struct gtm_local_undo
{
void *addr;
size_t len;
char saved[];
-} gtm_local_undo;
+};
void
-GTM_commit_local (void)
+gtm_transaction::commit_local ()
{
- gtm_transaction *tx = gtm_tx();
- gtm_local_undo **local_undo = tx->local_undo;
- size_t i, n = tx->n_local_undo;
+ gtm_local_undo **local_undo = this->local_undo;
+ size_t i, n = this->n_local_undo;
if (n > 0)
{
for (i = 0; i < n; ++i)
free (local_undo[i]);
- tx->n_local_undo = 0;
+ this->n_local_undo = 0;
}
if (local_undo)
{
free (local_undo);
- tx->local_undo = NULL;
- tx->size_local_undo = 0;
+ this->local_undo = NULL;
+ this->size_local_undo = 0;
}
}
void
-GTM_rollback_local (void)
+gtm_transaction::rollback_local (void)
{
- gtm_transaction *tx = gtm_tx();
- gtm_local_undo **local_undo = tx->local_undo;
- size_t i, n = tx->n_local_undo;
+ gtm_local_undo **local_undo = this->local_undo;
+ size_t i, n = this->n_local_undo;
if (n > 0)
{
@@ -69,7 +68,7 @@ GTM_rollback_local (void)
memcpy (u->addr, u->saved, u->len);
free (u);
}
- tx->n_local_undo = 0;
+ this->n_local_undo = 0;
}
}
@@ -79,26 +78,31 @@ GTM_LB (const void *ptr, size_t len)
gtm_transaction *tx = gtm_tx();
gtm_local_undo *undo;
- undo = malloc (sizeof (struct gtm_local_undo) + len);
+ undo = (gtm_local_undo *) xmalloc (sizeof (struct gtm_local_undo) + len);
undo->addr = (void *) ptr;
undo->len = len;
if (tx->local_undo == NULL)
{
tx->size_local_undo = 32;
- tx->local_undo = malloc (sizeof (undo) * tx->size_local_undo);
+ tx->local_undo = (gtm_local_undo **)
+ xmalloc (sizeof (undo) * tx->size_local_undo);
}
else if (tx->n_local_undo == tx->size_local_undo)
{
tx->size_local_undo *= 2;
- tx->local_undo = realloc (tx->local_undo,
- sizeof (undo) * tx->size_local_undo);
+ tx->local_undo = (gtm_local_undo **)
+ xrealloc (tx->local_undo, sizeof (undo) * tx->size_local_undo);
}
tx->local_undo[tx->n_local_undo++] = undo;
memcpy (undo->saved, ptr, len);
}
+} // namespace GTM
+
+using namespace GTM;
+
void _ITM_LB (const void *ptr, size_t len) ITM_REGPARM
__attribute__((alias("GTM_LB")));
diff --git a/libitm/memcpy.c b/libitm/memcpy.cc
index cf01371b21b..672af98fb16 100644
--- a/libitm/memcpy.c
+++ b/libitm/memcpy.cc
@@ -24,22 +24,25 @@
#include "libitm_i.h"
+using namespace GTM;
static void
-do_memcpy (uintptr_t dst, uintptr_t src, size_t size,
- gtm_write_lock_fn W, gtm_read_lock_fn R)
+do_memcpy (uintptr_t idst, uintptr_t isrc, size_t size,
+ gtm_dispatch::lock_type W, gtm_dispatch::lock_type R)
{
- uintptr_t dofs = dst & (CACHELINE_SIZE - 1);
- uintptr_t sofs = src & (CACHELINE_SIZE - 1);
- gtm_cacheline *sline;
- gtm_cacheline_mask_pair dpair;
+ gtm_dispatch *disp = gtm_disp();
+ uintptr_t dofs = idst & (CACHELINE_SIZE - 1);
+ uintptr_t sofs = isrc & (CACHELINE_SIZE - 1);
+ const gtm_cacheline *src
+ = reinterpret_cast<const gtm_cacheline *>(isrc & -CACHELINE_SIZE);
+ gtm_cacheline *dst
+ = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE);
+ const gtm_cacheline *sline;
+ gtm_dispatch::mask_pair dpair;
if (size == 0)
return;
- dst &= -CACHELINE_SIZE;
- src &= -CACHELINE_SIZE;
-
if (dofs == sofs)
{
if (sofs != 0)
@@ -47,30 +50,30 @@ do_memcpy (uintptr_t dst, uintptr_t src, size_t size,
size_t sleft = CACHELINE_SIZE - sofs;
size_t min = (size <= sleft ? size : sleft);
- dpair = W(dst);
- sline = R(src);
+ dpair = disp->write_lock(dst, W);
+ sline = disp->read_lock(src, R);
*dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << sofs;
memcpy (&dpair.line->b[sofs], &sline->b[sofs], min);
- dst += CACHELINE_SIZE;
- src += CACHELINE_SIZE;
+ dst++;
+ src++;
size -= min;
}
while (size >= CACHELINE_SIZE)
{
- dpair = W(dst);
- sline = R(src);
+ dpair = disp->write_lock(dst, W);
+ sline = disp->read_lock(src, R);
*dpair.mask = -1;
- gtm_cacheline_copy (dpair.line, sline);
- dst += CACHELINE_SIZE;
- src += CACHELINE_SIZE;
+ *dpair.line = *sline;
+ dst++;
+ src++;
size -= CACHELINE_SIZE;
}
if (size != 0)
{
- dpair = W(dst);
- sline = R(src);
+ dpair = disp->write_lock(dst, W);
+ sline = disp->read_lock(src, R);
*dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1;
memcpy (dpair.line, sline, size);
}
@@ -80,13 +83,13 @@ do_memcpy (uintptr_t dst, uintptr_t src, size_t size,
gtm_cacheline c;
size_t sleft = CACHELINE_SIZE - sofs;
- sline = R(src);
+ sline = disp->read_lock(src, R);
if (dofs != 0)
{
size_t dleft = CACHELINE_SIZE - dofs;
size_t min = (size <= dleft ? size : dleft);
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs;
if (min <= sleft)
{
@@ -96,44 +99,41 @@ do_memcpy (uintptr_t dst, uintptr_t src, size_t size,
else
{
memcpy (&c, &sline->b[sofs], sleft);
- src += CACHELINE_SIZE;
- sline = R(src);
+ sline = disp->read_lock(++src, R);
sofs = min - sleft;
memcpy (&c.b[sleft], sline, sofs);
memcpy (&dpair.line->b[dofs], &c, min);
}
sleft = CACHELINE_SIZE - sofs;
- dst += CACHELINE_SIZE;
+ dst++;
size -= min;
}
while (size >= CACHELINE_SIZE)
{
memcpy (&c, &sline->b[sofs], sleft);
- src += CACHELINE_SIZE;
- sline = R(src);
+ sline = disp->read_lock(++src, R);
memcpy (&c.b[sleft], sline, sofs);
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask = -1;
- gtm_cacheline_copy (dpair.line, &c);
+ *dpair.line = c;
- dst += CACHELINE_SIZE;
+ dst++;
size -= CACHELINE_SIZE;
}
if (size != 0)
{
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1;
if (size <= sleft)
memcpy (dpair.line, &sline->b[sofs], size);
else
{
memcpy (&c, &sline->b[sofs], sleft);
- src += CACHELINE_SIZE;
- sline = R(src);
+ sline = disp->read_lock(++src, R);
memcpy (&c.b[sleft], sline, size - sleft);
memcpy (dpair.line, &c, size);
}
@@ -142,12 +142,13 @@ do_memcpy (uintptr_t dst, uintptr_t src, size_t size,
}
static void
-do_memmove (uintptr_t dst, uintptr_t src, size_t size,
- gtm_write_lock_fn W, gtm_read_lock_fn R)
+do_memmove (uintptr_t idst, uintptr_t isrc, size_t size,
+ gtm_dispatch::lock_type W, gtm_dispatch::lock_type R)
{
+ gtm_dispatch *disp = gtm_disp();
uintptr_t dleft, sleft, sofs, dofs;
- gtm_cacheline *sline;
- gtm_cacheline_mask_pair dpair;
+ const gtm_cacheline *sline;
+ gtm_dispatch::mask_pair dpair;
if (size == 0)
return;
@@ -156,46 +157,47 @@ do_memmove (uintptr_t dst, uintptr_t src, size_t size,
that out. It's tempting to just return here, as this is a no-op move.
However, our caller has the right to expect the locks to be acquired
as advertized. */
- if (__builtin_expect (dst == src, 0))
+ if (__builtin_expect (idst == isrc, 0))
{
- const gtm_dispatch *disp = gtm_disp();
-
/* If the write lock is already acquired, nothing to do. */
- if (W == disp->WaW)
+ if (W == gtm_dispatch::WaW)
return;
/* If the destination is protected, acquire a write lock. */
- if (W != GTM_null_write_lock)
- R = disp->RfW;
+ if (W != gtm_dispatch::NOLOCK)
+ R = gtm_dispatch::RfW;
/* Notice serial mode, where we don't acquire locks at all. */
- if (R == GTM_null_read_lock)
+ if (R == gtm_dispatch::NOLOCK)
return;
- dst = src + size;
- for (src &= -CACHELINE_SIZE; src < dst; src += CACHELINE_SIZE)
- R(src);
+ idst = isrc + size;
+ for (isrc &= -CACHELINE_SIZE; isrc < idst; isrc += CACHELINE_SIZE)
+ disp->read_lock(reinterpret_cast<const gtm_cacheline *>(isrc), R);
return;
}
/* Fall back to memcpy if the implementation above can handle it. */
- if (dst < src || src + size <= dst)
+ if (idst < isrc || isrc + size <= idst)
{
- do_memcpy (dst, src, size, W, R);
+ do_memcpy (idst, isrc, size, W, R);
return;
}
/* What remains requires a backward copy from the end of the blocks. */
- dst += size;
- src += size;
- dofs = dst & (CACHELINE_SIZE - 1);
- sofs = src & (CACHELINE_SIZE - 1);
+ idst += size;
+ isrc += size;
+ dofs = idst & (CACHELINE_SIZE - 1);
+ sofs = isrc & (CACHELINE_SIZE - 1);
dleft = CACHELINE_SIZE - dofs;
sleft = CACHELINE_SIZE - sofs;
- dst &= -CACHELINE_SIZE;
- src &= -CACHELINE_SIZE;
+
+ gtm_cacheline *dst
+ = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE);
+ const gtm_cacheline *src
+ = reinterpret_cast<const gtm_cacheline *>(isrc & -CACHELINE_SIZE);
if (dofs == 0)
- dst -= CACHELINE_SIZE;
+ dst--;
if (sofs == 0)
- src -= CACHELINE_SIZE;
+ src--;
if (dofs == sofs)
{
@@ -203,31 +205,31 @@ do_memmove (uintptr_t dst, uintptr_t src, size_t size,
optimization above, that implies that SIZE > CACHELINE_SIZE. */
if (sofs != 0)
{
- dpair = W(dst);
- sline = R(src);
+ dpair = disp->write_lock(dst, W);
+ sline = disp->read_lock(src, R);
*dpair.mask |= ((gtm_cacheline_mask)1 << sleft) - 1;
memcpy (dpair.line, sline, sleft);
- dst -= CACHELINE_SIZE;
- src -= CACHELINE_SIZE;
+ dst--;
+ src--;
size -= sleft;
}
while (size >= CACHELINE_SIZE)
{
- dpair = W(dst);
- sline = R(src);
+ dpair = disp->write_lock(dst, W);
+ sline = disp->read_lock(src, R);
*dpair.mask = -1;
- gtm_cacheline_copy (dpair.line, sline);
- dst -= CACHELINE_SIZE;
- src -= CACHELINE_SIZE;
+ *dpair.line = *sline;
+ dst--;
+ src--;
size -= CACHELINE_SIZE;
}
if (size != 0)
{
size_t ofs = CACHELINE_SIZE - size;
- dpair = W(dst);
- sline = R(src);
+ dpair = disp->write_lock(dst, W);
+ sline = disp->read_lock(src, R);
*dpair.mask |= (((gtm_cacheline_mask)1 << size) - 1) << ofs;
memcpy (&dpair.line->b[ofs], &sline->b[ofs], size);
}
@@ -236,7 +238,7 @@ do_memmove (uintptr_t dst, uintptr_t src, size_t size,
{
gtm_cacheline c;
- sline = R(src);
+ sline = disp->read_lock(src, R);
if (dofs != 0)
{
size_t min = (size <= dofs ? size : dofs);
@@ -250,34 +252,32 @@ do_memmove (uintptr_t dst, uintptr_t src, size_t size,
{
size_t min_ofs = min - sofs;
memcpy (&c.b[min_ofs], sline, sofs);
- src -= CACHELINE_SIZE;
- sline = R(src);
+ sline = disp->read_lock(--src, R);
sofs = CACHELINE_SIZE - min_ofs;
memcpy (&c, &sline->b[sofs], min_ofs);
}
dofs = dleft - min;
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs;
memcpy (&dpair.line->b[dofs], &c, min);
sleft = CACHELINE_SIZE - sofs;
- dst -= CACHELINE_SIZE;
+ dst--;
size -= min;
}
while (size >= CACHELINE_SIZE)
{
memcpy (&c.b[sleft], sline, sofs);
- src -= CACHELINE_SIZE;
- sline = R(src);
+ sline = disp->read_lock(--src, R);
memcpy (&c, &sline->b[sofs], sleft);
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask = -1;
- gtm_cacheline_copy (dpair.line, &c);
+ *dpair.line = c;
- dst -= CACHELINE_SIZE;
+ dst--;
size -= CACHELINE_SIZE;
}
@@ -288,12 +288,11 @@ do_memmove (uintptr_t dst, uintptr_t src, size_t size,
memcpy (&c.b[sleft], sline, sofs);
if (sleft > dofs)
{
- src -= CACHELINE_SIZE;
- sline = R(src);
+ sline = disp->read_lock(--src, R);
memcpy (&c, &sline->b[sofs], sleft);
}
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask |= (gtm_cacheline_mask)-1 << dofs;
memcpy (&dpair.line->b[dofs], &c.b[dofs], size);
}
@@ -303,30 +302,30 @@ do_memmove (uintptr_t dst, uintptr_t src, size_t size,
#define ITM_MEM_DEF(NAME, READ, WRITE) \
void ITM_REGPARM _ITM_memcpy##NAME(void *dst, const void *src, size_t size) \
{ \
- const gtm_dispatch *disp = gtm_disp(); \
- do_memcpy ((uintptr_t)dst, (uintptr_t)src, size, WRITE, READ); \
+ do_memcpy ((uintptr_t)dst, (uintptr_t)src, size, \
+ gtm_dispatch::WRITE, gtm_dispatch::READ); \
} \
void ITM_REGPARM _ITM_memmove##NAME(void *dst, const void *src, size_t size) \
{ \
- const gtm_dispatch *disp = gtm_disp(); \
- do_memmove ((uintptr_t)dst, (uintptr_t)src, size, WRITE, READ); \
+ do_memmove ((uintptr_t)dst, (uintptr_t)src, size, \
+ gtm_dispatch::WRITE, gtm_dispatch::READ); \
}
-ITM_MEM_DEF(RnWt, GTM_null_read_lock, disp->W)
-ITM_MEM_DEF(RnWtaR, GTM_null_read_lock, disp->WaR)
-ITM_MEM_DEF(RnWtaW, GTM_null_read_lock, disp->WaW)
+ITM_MEM_DEF(RnWt, NOLOCK, W)
+ITM_MEM_DEF(RnWtaR, NOLOCK, WaR)
+ITM_MEM_DEF(RnWtaW, NOLOCK, WaW)
-ITM_MEM_DEF(RtWn, disp->R, GTM_null_write_lock)
-ITM_MEM_DEF(RtWt, disp->R, disp->W)
-ITM_MEM_DEF(RtWtaR, disp->R, disp->WaR)
-ITM_MEM_DEF(RtWtaW, disp->R, disp->WaW)
+ITM_MEM_DEF(RtWn, R, NOLOCK)
+ITM_MEM_DEF(RtWt, R, W)
+ITM_MEM_DEF(RtWtaR, R, WaR)
+ITM_MEM_DEF(RtWtaW, R, WaW)
-ITM_MEM_DEF(RtaRWn, disp->RaR, GTM_null_write_lock)
-ITM_MEM_DEF(RtaRWt, disp->RaR, disp->W)
-ITM_MEM_DEF(RtaRWtaR, disp->RaR, disp->WaR)
-ITM_MEM_DEF(RtaRWtaW, disp->RaR, disp->WaW)
+ITM_MEM_DEF(RtaRWn, RaR, NOLOCK)
+ITM_MEM_DEF(RtaRWt, RaR, W)
+ITM_MEM_DEF(RtaRWtaR, RaR, WaR)
+ITM_MEM_DEF(RtaRWtaW, RaR, WaW)
-ITM_MEM_DEF(RtaWWn, disp->RaW, GTM_null_write_lock)
-ITM_MEM_DEF(RtaWWt, disp->RaW, disp->W)
-ITM_MEM_DEF(RtaWWtaR, disp->RaW, disp->WaR)
-ITM_MEM_DEF(RtaWWtaW, disp->RaW, disp->WaW)
+ITM_MEM_DEF(RtaWWn, RaW, NOLOCK)
+ITM_MEM_DEF(RtaWWt, RaW, W)
+ITM_MEM_DEF(RtaWWtaR, RaW, WaR)
+ITM_MEM_DEF(RtaWWtaW, RaW, WaW)
diff --git a/libitm/memset.c b/libitm/memset.cc
index d4a9fc63b14..d77b6264e21 100644
--- a/libitm/memset.c
+++ b/libitm/memset.cc
@@ -24,42 +24,44 @@
#include "libitm_i.h"
+using namespace GTM;
static void
-do_memset(uintptr_t dst, int c, size_t size, gtm_write_lock_fn W)
+do_memset(uintptr_t idst, int c, size_t size, gtm_dispatch::lock_type W)
{
- uintptr_t dofs = dst & (CACHELINE_SIZE - 1);
- gtm_cacheline_mask_pair dpair;
+ gtm_dispatch *disp = gtm_disp();
+ uintptr_t dofs = idst & (CACHELINE_SIZE - 1);
+ gtm_dispatch::mask_pair dpair;
+ gtm_cacheline *dst
+ = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE);
if (size == 0)
return;
- dst &= -CACHELINE_SIZE;
-
if (dofs != 0)
{
size_t dleft = CACHELINE_SIZE - dofs;
size_t min = (size <= dleft ? size : dleft);
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs;
memset (&dpair.line->b[dofs], c, min);
- dst += CACHELINE_SIZE;
+ dst++;
size -= min;
}
while (size >= CACHELINE_SIZE)
{
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask = -1;
memset (dpair.line, c, CACHELINE_SIZE);
- dst += CACHELINE_SIZE;
+ dst++;
size -= CACHELINE_SIZE;
}
if (size != 0)
{
- dpair = W(dst);
+ dpair = disp->write_lock(dst, W);
*dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1;
memset (dpair.line, c, size);
}
@@ -67,10 +69,7 @@ do_memset(uintptr_t dst, int c, size_t size, gtm_write_lock_fn W)
#define ITM_MEM_DEF(WRITE) \
void ITM_REGPARM _ITM_memset##WRITE(void *dst, int c, size_t size) \
-{ \
- const gtm_dispatch *disp = gtm_disp(); \
- do_memset ((uintptr_t)dst, c, size, disp->WRITE); \
-}
+{ do_memset ((uintptr_t)dst, c, size, gtm_dispatch::WRITE); }
ITM_MEM_DEF(W)
ITM_MEM_DEF(WaR)
diff --git a/libitm/method-readonly.c b/libitm/method-readonly.c
deleted file mode 100644
index 611bc8fc1ec..00000000000
--- a/libitm/method-readonly.c
+++ /dev/null
@@ -1,115 +0,0 @@
-/* Copyright (C) 2009 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"
-
-struct gtm_method
-{
- gtm_version start;
-};
-
-/* Acquire a read lock on ADDR. */
-
-static gtm_cacheline *
-readonly_R (uintptr_t addr)
-{
- return (gtm_cacheline *) addr;
-}
-
-static gtm_cacheline *
-readonly_RaW (uintptr_t addr)
-{
- abort ();
-}
-
-static gtm_cacheline *
-readonly_RfW (uintptr_t addr)
-{
- GTM_restart_transaction (RESTART_NOT_READONLY);
-}
-
-static gtm_cacheline_mask_pair
-readonly_W (uintptr_t addr)
-{
- GTM_restart_transaction (RESTART_NOT_READONLY);
-}
-
-static gtm_cacheline_mask_pair
-readonly_WaW (uintptr_t addr)
-{
- abort ();
-}
-
-/* Commit the transaction. */
-
-static bool
-readonly_trycommit (void)
-{
- struct gtm_method *m = gtm_tx()->m;
- return gtm_get_clock () == m->start;
-}
-
-static void
-readonly_rollback (void)
-{
- /* Nothing to do. */
-}
-
-static void
-readonly_init (bool first)
-{
- struct gtm_method *m;
-
- if (first)
- gtm_tx()->m = m = calloc (1, sizeof (*m));
- else
- m = gtm_tx()->m;
-
- m->start = gtm_get_clock ();
-}
-
-static void
-readonly_fini (void)
-{
- struct gtm_method *m = gtm_tx()->m;
- free (m);
-}
-
-const struct gtm_dispatch dispatch_readonly = {
- .R = readonly_R,
- .RaR = readonly_R,
- .RaW = readonly_RaW,
- .RfW = readonly_RfW,
-
- .W = readonly_W,
- .WaR = readonly_W,
- .WaW = readonly_WaW,
-
- .trycommit = readonly_trycommit,
- .rollback = readonly_rollback,
- .init = readonly_init,
- .fini = readonly_fini,
-
- .write_through = true
-};
diff --git a/libitm/method-readonly.cc b/libitm/method-readonly.cc
new file mode 100644
index 00000000000..70f5bed946e
--- /dev/null
+++ b/libitm/method-readonly.cc
@@ -0,0 +1,123 @@
+/* Copyright (C) 2009 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 {
+
+using namespace GTM;
+
+class readonly_dispatch : public gtm_dispatch
+{
+ private:
+ gtm_version m_start;
+
+ public:
+ readonly_dispatch();
+
+ virtual const gtm_cacheline *read_lock(const gtm_cacheline *, lock_type);
+ virtual mask_pair write_lock(gtm_cacheline *, lock_type);
+ virtual bool trycommit();
+ virtual void rollback();
+ virtual void reinit();
+ virtual void fini();
+};
+
+inline
+readonly_dispatch::readonly_dispatch()
+ : gtm_dispatch(true, true), m_start(gtm_get_clock ())
+{ }
+
+
+const gtm_cacheline *
+readonly_dispatch::read_lock(const gtm_cacheline *line, lock_type lock)
+{
+ switch (lock)
+ {
+ case NOLOCK:
+ case R:
+ case RaR:
+ return line;
+
+ case RfW:
+ gtm_tx()->restart (RESTART_NOT_READONLY);
+
+ case RaW:
+ default:
+ abort ();
+ }
+}
+
+gtm_dispatch::mask_pair
+readonly_dispatch::write_lock(gtm_cacheline *line, lock_type lock)
+{
+ switch (lock)
+ {
+ case NOLOCK:
+ {
+ gtm_dispatch::mask_pair pair;
+ pair.line = line;
+ pair.mask = &mask_sink;
+ return pair;
+ }
+
+ case WaW:
+ abort ();
+
+ default:
+ gtm_tx()->restart (RESTART_NOT_READONLY);
+ }
+}
+
+bool
+readonly_dispatch::trycommit ()
+{
+ return gtm_get_clock () == m_start;
+}
+
+void
+readonly_dispatch::rollback ()
+{
+ /* Nothing to do. */
+}
+
+void
+readonly_dispatch::reinit ()
+{
+ m_start = gtm_get_clock ();
+}
+
+void
+readonly_dispatch::fini ()
+{
+ delete this;
+}
+
+} // anon namespace
+
+gtm_dispatch *
+GTM::dispatch_readonly ()
+{
+ return new readonly_dispatch();
+}
diff --git a/libitm/method-wbetl.c b/libitm/method-wbetl.c
deleted file mode 100644
index a3549e33362..00000000000
--- a/libitm/method-wbetl.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/* Copyright (C) 2009 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"
-
-
-typedef struct r_entry
-{
- gtm_version version;
- volatile gtm_stmlock *lock;
-} r_entry_t;
-
-typedef struct r_set
-{
- r_entry_t *entries;
- int nb_entries;
- int size;
-} r_set_t;
-
-typedef struct w_entry
-{
- struct w_entry *next;
- uintptr_t addr;
- volatile gtm_stmlock *lock;
- gtm_cacheline *value;
- gtm_version version;
-} w_entry_t;
-
-typedef struct w_set
-{
- w_entry_t *entries;
- int nb_entries;
- int size;
- int reallocate;
-} w_set_t;
-
-struct gtm_method
-{
- gtm_version start;
- gtm_version end;
-
- r_set_t r_set;
- w_set_t w_set;
-
- gtm_cacheline_page *cache_page;
- int n_cache_page;
-};
-
-#define RW_SET_SIZE 4096
-
-/* Check if W is one of our write locks. */
-static inline bool
-wbetl_local_w_entry_p (struct gtm_method *m, w_entry_t *w)
-{
- return (m->w_set.entries <= w
- && w < m->w_set.entries + m->w_set.nb_entries);
-}
-
-/* Check if stripe has been read previously. */
-
-static inline r_entry_t *
-wbetl_has_read (struct gtm_method *m, volatile gtm_word *lock)
-{
- r_entry_t *r;
- int i;
-
- r = m->r_set.entries;
- for (i = m->r_set.nb_entries; i > 0; i--, r++)
- if (r->lock == lock)
- return r;
-
- return NULL;
-}
-
-/* Validate read set, i.e. check if all read addresses are still valid now. */
-
-static bool
-wbetl_validate (struct gtm_method *m)
-{
- r_entry_t *r;
- int i;
- gtm_word l;
-
- __sync_synchronize ();
-
- r = m->r_set.entries;
- for (i = m->r_set.nb_entries; i > 0; i--, r++)
- {
- l = *r->lock;
- if (gtm_stmlock_owned_p (l))
- {
- w_entry_t *w = gtm_stmlock_get_addr (l);
-
- if (!wbetl_local_w_entry_p (m, w))
- return false;
- }
- else
- {
- if (gtm_stmlock_get_version (l) != r->version)
- return false;
- }
- }
-
- return true;
-}
-
-/* Extend the snapshot range. */
-
-static bool
-wbetl_extend (struct gtm_method *m)
-{
- gtm_word now = gtm_get_clock ();
-
- if (wbetl_validate (m))
- {
- m->end = now;
- return true;
- }
- return false;
-}
-
-/* Acquire a write lock on ADDR. */
-
-static gtm_cacheline *
-wbetl_write_lock (uintptr_t addr)
-{
- volatile gtm_stmlock *lock;
- gtm_stmlock l, l2;
- gtm_version version;
- w_entry_t *w, *prev = NULL;
- struct gtm_method *m;
-
- m = gtm_tx()->m;
- lock = gtm_get_stmlock (addr);
- l = *lock;
-
- restart_no_load:
- if (gtm_stmlock_owned_p (l))
- {
- w = gtm_stmlock_get_addr (l);
-
- /* Did we previously write the same address? */
- if (wbetl_local_w_entry_p (m, w))
- {
- prev = w;
- while (1)
- {
- if (addr == prev->addr)
- return prev->value;
- if (prev->next == NULL)
- break;
- prev = prev->next;
- }
-
- /* Get version from previous entry write set. */
- version = prev->version;
-
- /* If there's not enough entries, we must reallocate the array,
- which invalidates all pointers to write set entries, which
- means we have to restart the transaction. */
- if (m->w_set.nb_entries == m->w_set.size)
- {
- m->w_set.size *= 2;
- m->w_set.reallocate = 1;
- GTM_restart_transaction (RESTART_REALLOCATE);
- }
-
- w = &m->w_set.entries[m->w_set.nb_entries];
- goto do_write;
- }
-
- GTM_restart_transaction (RESTART_LOCKED_WRITE);
- }
- else
- {
- version = gtm_stmlock_get_version (l);
-
- /* We might have read an older version previously. */
- if (version > m->end)
- {
- if (wbetl_has_read (m, lock) != NULL)
- GTM_restart_transaction (RESTART_VALIDATE_WRITE);
- }
-
- /* Extend write set, aborting to reallocate write set entries. */
- if (m->w_set.nb_entries == m->w_set.size)
- {
- m->w_set.size *= 2;
- m->w_set.reallocate = 1;
- GTM_restart_transaction (RESTART_REALLOCATE);
- }
-
- /* Acquire the lock. */
- w = &m->w_set.entries[m->w_set.nb_entries];
- l2 = gtm_stmlock_set_owned (w);
- l = __sync_val_compare_and_swap (lock, l, l2);
- if (l != l2)
- goto restart_no_load;
- }
-
- do_write:
- m->w_set.nb_entries++;
- w->addr = addr;
- w->lock = lock;
- w->version = version;
- w->next = NULL;
- if (prev != NULL)
- prev->next = w;
-
- {
- gtm_cacheline_page *page = m->cache_page;
- unsigned index = m->n_cache_page;
- gtm_cacheline *line;
-
- if (page == NULL || index == CACHELINES_PER_PAGE)
- {
- gtm_cacheline_page *npage = GTM_page_alloc ();
- npage->prev = page;
- m->cache_page = page = npage;
- m->n_cache_page = 1;
- index = 0;
- }
- else
- m->n_cache_page = index + 1;
-
- w->value = line = &page->lines[index];
- page->masks[index] = 0;
- gtm_cacheline_copy (line, (const gtm_cacheline *) addr);
-
- return line;
- }
-}
-
-/* Acquire a read lock on ADDR. */
-
-static gtm_cacheline *
-wbetl_read_lock (uintptr_t addr, bool after_read)
-{
- volatile gtm_stmlock *lock;
- gtm_stmlock l, l2;
- gtm_version version;
- w_entry_t *w;
- struct gtm_method *m;
-
- m = gtm_tx()->m;
- lock = gtm_get_stmlock (addr);
- l = *lock;
-
- restart_no_load:
- if (gtm_stmlock_owned_p (l))
- {
- w = gtm_stmlock_get_addr (l);
-
- /* Did we previously write the same address? */
- if (wbetl_local_w_entry_p (m, w))
- {
- while (1)
- {
- if (addr == w->addr)
- return w->value;
- if (w->next == NULL)
- return (gtm_cacheline *) addr;
- w = w->next;
- }
- }
-
- GTM_restart_transaction (RESTART_LOCKED_READ);
- }
-
- version = gtm_stmlock_get_version (l);
-
- /* If version is no longer valid, re-validate the read set. */
- if (version > m->end)
- {
- if (!wbetl_extend (m))
- GTM_restart_transaction (RESTART_VALIDATE_READ);
-
- /* Verify that the version has not yet been overwritten. The read
- value has not yet bee added to read set and may not have been
- checked during the extend. */
- __sync_synchronize ();
- l2 = *lock;
- if (l != l2)
- {
- l = l2;
- goto restart_no_load;
- }
- }
-
- if (!after_read)
- {
- r_entry_t *r;
-
- /* Add the address and version to the read set. */
- if (m->r_set.nb_entries == m->r_set.size)
- {
- m->r_set.size *= 2;
-
- m->r_set.entries = (r_entry_t *)
- realloc (m->r_set.entries, m->r_set.size * sizeof(r_entry_t));
- if (m->r_set.entries == NULL)
- abort ();
- }
- r = &m->r_set.entries[m->r_set.nb_entries++];
- r->version = version;
- r->lock = lock;
- }
-
- return (gtm_cacheline *) addr;
-}
-
-static gtm_cacheline *
-wbetl_after_write_lock (uintptr_t addr)
-{
- volatile gtm_stmlock *lock;
- gtm_stmlock l;
- w_entry_t *w;
- struct gtm_method *m;
-
- m = gtm_tx()->m;
- lock = gtm_get_stmlock (addr);
-
- l = *lock;
- assert (gtm_stmlock_owned_p (l));
-
- w = gtm_stmlock_get_addr (l);
- assert (wbetl_local_w_entry_p (m, w));
-
- while (1)
- {
- if (addr == w->addr)
- return w->value;
- w = w->next;
- }
-}
-
-static gtm_cacheline *
-wbetl_R (uintptr_t addr)
-{
- return wbetl_read_lock (addr, false);
-}
-
-static gtm_cacheline *
-wbetl_RaR (uintptr_t addr)
-{
- return wbetl_read_lock (addr, true);
-}
-
-static gtm_cacheline_mask_pair
-wbetl_W (uintptr_t addr)
-{
- gtm_cacheline_mask_pair pair;
- pair.line = wbetl_write_lock (addr);
- pair.mask = gtm_mask_for_line (pair.line);
- return pair;
-}
-
-static gtm_cacheline_mask_pair
-wbetl_WaW (uintptr_t addr)
-{
- gtm_cacheline_mask_pair pair;
- pair.line = wbetl_after_write_lock (addr);
- pair.mask = gtm_mask_for_line (pair.line);
- return pair;
-}
-
-/* Commit the transaction. */
-
-static bool
-wbetl_trycommit (void)
-{
- struct gtm_method *m = gtm_tx()->m;
- w_entry_t *w;
- gtm_word t;
- int i;
-
- if (m->w_set.nb_entries > 0)
- {
- /* Get commit timestamp. */
- t = gtm_inc_clock ();
-
- /* Validate only if a concurrent transaction has started since. */
- if (m->start != t - 1 && !wbetl_validate (m))
- return false;
-
- /* Install new versions, drop locks and set new timestamp. */
- w = m->w_set.entries;
- for (i = m->w_set.nb_entries; i > 0; i--, w++)
- gtm_cacheline_copy_mask ((gtm_cacheline *) w->addr,
- w->value, *gtm_mask_for_line (w->value));
-
- /* Only emit barrier after all cachelines are copied. */
- gtm_ccm_write_barrier ();
-
- w = m->w_set.entries;
- for (i = m->w_set.nb_entries; i > 0; i--, w++)
- if (w->next == NULL)
- *w->lock = gtm_stmlock_set_version (t);
-
- __sync_synchronize ();
- }
-
- return true;
-}
-
-static void
-wbetl_rollback (void)
-{
- struct gtm_method *m = gtm_tx()->m;
- w_entry_t *w;
- int i;
-
- /* Drop locks. */
- w = m->w_set.entries;
- for (i = m->w_set.nb_entries; i > 0; i--, w++)
- if (w->next == NULL)
- *w->lock = gtm_stmlock_set_version (w->version);
-
- __sync_synchronize ();
-}
-
-static void
-wbetl_init (bool first)
-{
- struct gtm_method *m;
-
- if (first)
- {
- gtm_tx()->m = m = calloc (1, sizeof (*m));
- m->r_set.size = RW_SET_SIZE;
- m->r_set.entries = malloc (RW_SET_SIZE * sizeof(r_entry_t));
- m->w_set.size = RW_SET_SIZE;
- m->w_set.entries = malloc (RW_SET_SIZE * sizeof(w_entry_t));
- }
- else
- {
- gtm_cacheline_page *page;
-
- m = gtm_tx()->m;
- m->r_set.nb_entries = 0;
-
- m->w_set.nb_entries = 0;
- if (m->w_set.reallocate)
- {
- m->w_set.reallocate = 0;
- m->w_set.entries = realloc (m->w_set.entries,
- m->w_set.size * sizeof(w_entry_t));
- }
-
- page = m->cache_page;
- if (page)
- {
- /* Release all but one of the pages of cachelines. */
- gtm_cacheline_page *prev = page->prev;
- if (prev)
- {
- gtm_cacheline_page *tail;
- for (tail = prev; tail->prev; tail = tail->prev)
- continue;
- page->prev = NULL;
- GTM_page_release (prev, tail);
- }
- /* Start the next cacheline allocation from the beginning. */
- m->n_cache_page = 0;
- }
- }
-
- m->start = m->end = gtm_get_clock ();
-}
-
-static void
-wbetl_fini (void)
-{
- struct gtm_method *m = gtm_tx()->m;
- gtm_cacheline_page *page, *tail;
-
- page = m->cache_page;
- if (page)
- {
- for (tail = page; tail->prev; tail = tail->prev)
- continue;
- GTM_page_release (page, tail);
- }
-
- free (m->r_set.entries);
- free (m->w_set.entries);
- free (m);
-}
-
-const struct gtm_dispatch dispatch_wbetl = {
- .R = wbetl_R,
- .RaR = wbetl_RaR,
- .RaW = wbetl_after_write_lock,
- .RfW = wbetl_write_lock,
-
- .W = wbetl_W,
- .WaR = wbetl_W,
- .WaW = wbetl_WaW,
-
- .trycommit = wbetl_trycommit,
- .rollback = wbetl_rollback,
- .init = wbetl_init,
- .fini = wbetl_fini,
-
- .write_through = false
-};
diff --git a/libitm/method-wbetl.cc b/libitm/method-wbetl.cc
new file mode 100644
index 00000000000..98ce1e4ef3a
--- /dev/null
+++ b/libitm/method-wbetl.cc
@@ -0,0 +1,530 @@
+/* Copyright (C) 2009 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 {
+
+using namespace GTM;
+
+class wbetl_dispatch : public gtm_dispatch
+{
+ private:
+ static const size_t RW_SET_SIZE = 4096;
+
+ struct r_entry
+ {
+ gtm_version version;
+ gtm_stmlock *lock;
+ };
+
+ r_entry *m_rset_entries;
+ size_t m_rset_nb_entries;
+ size_t m_rset_size;
+
+ struct w_entry
+ {
+ struct w_entry *next;
+ gtm_stmlock *lock;
+ gtm_cacheline *addr;
+ gtm_cacheline *value;
+ gtm_version version;
+ };
+
+ w_entry *m_wset_entries;
+ size_t m_wset_nb_entries;
+ size_t m_wset_size;
+ bool m_wset_reallocate;
+
+ gtm_version m_start;
+ gtm_version m_end;
+
+ gtm_cacheline_page *m_cache_page;
+ unsigned m_n_cache_page;
+
+ private:
+ bool local_w_entry_p (w_entry *w);
+ bool has_read (gtm_stmlock *lock);
+ bool validate();
+ bool extend();
+
+ gtm_cacheline *do_write_lock(gtm_cacheline *);
+ gtm_cacheline *do_after_write_lock(gtm_cacheline *);
+ const gtm_cacheline *do_read_lock(const gtm_cacheline *, bool);
+
+ public:
+ wbetl_dispatch();
+
+ virtual const gtm_cacheline *read_lock(const gtm_cacheline *, lock_type);
+ virtual mask_pair write_lock(gtm_cacheline *, lock_type);
+
+ virtual bool trycommit();
+ virtual void rollback();
+ virtual void reinit();
+ virtual void fini();
+};
+
+/* Check if W is one of our write locks. */
+
+inline bool
+wbetl_dispatch::local_w_entry_p (w_entry *w)
+{
+ return (m_wset_entries <= w && w < m_wset_entries + m_wset_nb_entries);
+}
+
+/* Check if stripe has been read previously. */
+
+inline bool
+wbetl_dispatch::has_read (gtm_stmlock *lock)
+{
+ // ??? Consider using an AA tree to lookup the r_set entries.
+ size_t n = m_rset_nb_entries;
+ for (size_t i = 0; i < n; ++i)
+ if (m_rset_entries[i].lock == lock)
+ return true;
+
+ return false;
+}
+
+/* Validate read set, i.e. check if all read addresses are still valid now. */
+
+bool
+wbetl_dispatch::validate ()
+{
+ __sync_synchronize ();
+
+ size_t n = m_rset_nb_entries;
+ for (size_t i = 0; i < n; ++i)
+ {
+ r_entry *r = &m_rset_entries[i];
+ gtm_stmlock l = *r->lock;
+
+ if (gtm_stmlock_owned_p (l))
+ {
+ w_entry *w = (w_entry *) gtm_stmlock_get_addr (l);
+
+ if (!local_w_entry_p (w))
+ return false;
+ }
+ else if (gtm_stmlock_get_version (l) != r->version)
+ return false;
+ }
+
+ return true;
+}
+
+/* Extend the snapshot range. */
+
+bool
+wbetl_dispatch::extend ()
+{
+ gtm_version now = gtm_get_clock ();
+
+ if (validate ())
+ {
+ m_end = now;
+ return true;
+ }
+ return false;
+}
+
+/* Acquire a write lock on ADDR. */
+
+gtm_cacheline *
+wbetl_dispatch::do_write_lock(gtm_cacheline *addr)
+{
+ gtm_stmlock *lock;
+ gtm_stmlock l, l2;
+ gtm_version version;
+ w_entry *w, *prev = NULL;
+
+ lock = gtm_get_stmlock (addr);
+ l = *lock;
+
+ restart_no_load:
+ if (gtm_stmlock_owned_p (l))
+ {
+ w = (w_entry *) gtm_stmlock_get_addr (l);
+
+ /* Did we previously write the same address? */
+ if (local_w_entry_p (w))
+ {
+ prev = w;
+ while (1)
+ {
+ if (addr == prev->addr)
+ return prev->value;
+ if (prev->next == NULL)
+ break;
+ prev = prev->next;
+ }
+
+ /* Get version from previous entry write set. */
+ version = prev->version;
+
+ /* If there's not enough entries, we must reallocate the array,
+ which invalidates all pointers to write set entries, which
+ means we have to restart the transaction. */
+ if (m_wset_nb_entries == m_wset_size)
+ {
+ m_wset_size *= 2;
+ m_wset_reallocate = true;
+ gtm_tx()->restart (RESTART_REALLOCATE);
+ }
+
+ w = &m_wset_entries[m_wset_nb_entries];
+ goto do_write;
+ }
+
+ gtm_tx()->restart (RESTART_LOCKED_WRITE);
+ }
+ else
+ {
+ version = gtm_stmlock_get_version (l);
+
+ /* We might have read an older version previously. */
+ if (version > m_end)
+ {
+ if (has_read (lock))
+ gtm_tx()->restart (RESTART_VALIDATE_WRITE);
+ }
+
+ /* Extend write set, aborting to reallocate write set entries. */
+ if (m_wset_nb_entries == m_wset_size)
+ {
+ m_wset_size *= 2;
+ m_wset_reallocate = true;
+ gtm_tx()->restart (RESTART_REALLOCATE);
+ }
+
+ /* Acquire the lock. */
+ w = &m_wset_entries[m_wset_nb_entries];
+ l2 = gtm_stmlock_set_owned (w);
+ l = __sync_val_compare_and_swap (lock, l, l2);
+ if (l != l2)
+ goto restart_no_load;
+ }
+
+ do_write:
+ m_wset_nb_entries++;
+ if (prev != NULL)
+ prev->next = w;
+ w->next = 0;
+ w->lock = lock;
+ w->addr = addr;
+ w->version = version;
+
+ gtm_cacheline_page *page = m_cache_page;
+ unsigned index = m_n_cache_page;
+
+ if (page == NULL || index == gtm_cacheline_page::LINES)
+ {
+ gtm_cacheline_page *npage = new gtm_cacheline_page;
+ npage->prev = page;
+ m_cache_page = page = npage;
+ m_n_cache_page = 1;
+ index = 0;
+ }
+ else
+ m_n_cache_page = index + 1;
+
+ gtm_cacheline *line = &page->lines[index];
+ w->value = line;
+ page->masks[index] = 0;
+ *line = *addr;
+
+ return line;
+}
+
+gtm_cacheline *
+wbetl_dispatch::do_after_write_lock (gtm_cacheline *addr)
+{
+ gtm_stmlock *lock;
+ gtm_stmlock l;
+ w_entry *w;
+
+ lock = gtm_get_stmlock (addr);
+ l = *lock;
+ assert (gtm_stmlock_owned_p (l));
+
+ w = (w_entry *) gtm_stmlock_get_addr (l);
+ assert (local_w_entry_p (w));
+
+ while (1)
+ {
+ if (addr == w->addr)
+ return w->value;
+ w = w->next;
+ }
+}
+
+/* Acquire a read lock on ADDR. */
+
+const gtm_cacheline *
+wbetl_dispatch::do_read_lock (const gtm_cacheline *addr, bool after_read)
+{
+ gtm_stmlock *lock;
+ gtm_stmlock l, l2;
+ gtm_version version;
+ w_entry *w;
+
+ lock = gtm_get_stmlock (addr);
+ l = *lock;
+
+ restart_no_load:
+ if (gtm_stmlock_owned_p (l))
+ {
+ w = (w_entry *) gtm_stmlock_get_addr (l);
+
+ /* Did we previously write the same address? */
+ if (local_w_entry_p (w))
+ {
+ while (1)
+ {
+ if (addr == w->addr)
+ return w->value;
+ if (w->next == NULL)
+ return addr;
+ w = w->next;
+ }
+ }
+
+ gtm_tx()->restart (RESTART_LOCKED_READ);
+ }
+
+ version = gtm_stmlock_get_version (l);
+
+ /* If version is no longer valid, re-validate the read set. */
+ if (version > m_end)
+ {
+ if (!extend ())
+ gtm_tx()->restart (RESTART_VALIDATE_READ);
+
+ if (!after_read)
+ {
+ // Verify that the version has not yet been overwritten. The read
+ // value has not yet been added to read set and may not have been
+ // checked during the extend.
+ //
+ // ??? This only makes sense if we're actually reading the value
+ // and returning it now -- which I believe the original TinySTM
+ // did. This doesn't make a whole lot of sense when we're
+ // manipulating cachelines as we are now. Do we need some other
+ // form of lock verification here, or is the validate call in
+ // trycommit sufficient?
+
+ __sync_synchronize ();
+ l2 = *lock;
+ if (l != l2)
+ {
+ l = l2;
+ goto restart_no_load;
+ }
+ }
+ }
+
+ if (!after_read)
+ {
+ r_entry *r;
+
+ /* Add the address and version to the read set. */
+ if (m_rset_nb_entries == m_rset_size)
+ {
+ m_rset_size *= 2;
+
+ m_rset_entries = (r_entry *)
+ xrealloc (m_rset_entries, m_rset_size * sizeof(r_entry));
+ }
+ r = &m_rset_entries[m_rset_nb_entries++];
+ r->version = version;
+ r->lock = lock;
+ }
+
+ return addr;
+}
+
+const gtm_cacheline *
+wbetl_dispatch::read_lock (const gtm_cacheline *addr, lock_type ltype)
+{
+ switch (ltype)
+ {
+ case NOLOCK:
+ return addr;
+ case R:
+ return do_read_lock (addr, false);
+ case RaR:
+ return do_read_lock (addr, true);
+ case RaW:
+ return do_after_write_lock (const_cast<gtm_cacheline *>(addr));
+ case RfW:
+ return do_write_lock (const_cast<gtm_cacheline *>(addr));
+ default:
+ abort ();
+ }
+}
+
+gtm_dispatch::mask_pair
+wbetl_dispatch::write_lock (gtm_cacheline *addr, lock_type ltype)
+{
+ gtm_cacheline *line;
+
+ switch (ltype)
+ {
+ case NOLOCK:
+ return mask_pair (addr, &mask_sink);
+ case W:
+ case WaR:
+ line = do_write_lock (addr);
+ break;
+ case WaW:
+ line = do_after_write_lock (addr);
+ break;
+ default:
+ abort ();
+ }
+
+ return mask_pair (line, gtm_cacheline_page::mask_for_page_line (line));
+}
+
+/* Commit the transaction. */
+
+bool
+wbetl_dispatch::trycommit ()
+{
+ const size_t n = m_wset_nb_entries;
+ if (n != 0)
+ {
+ /* Get commit timestamp. */
+ gtm_version t = gtm_inc_clock ();
+
+ /* Validate only if a concurrent transaction has started since. */
+ if (m_start != t - 1 && !validate ())
+ return false;
+
+ /* Install new versions. */
+ for (size_t i = 0; i < n; ++i)
+ {
+ w_entry *w = &m_wset_entries[i];
+ gtm_cacheline::copy_mask (w->addr, w->value,
+ *gtm_cacheline_page::mask_for_page_line (w->value));
+ }
+
+ /* Only emit barrier after all cachelines are copied. */
+ gtm_cacheline::copy_mask_wb ();
+
+ /* Drop locks. */
+ for (size_t i = 0; i < n; ++i)
+ {
+ w_entry *w = &m_wset_entries[i];
+ if (w->next == NULL)
+ *w->lock = gtm_stmlock_set_version (t);
+ }
+ }
+
+ __sync_synchronize ();
+ return true;
+}
+
+void
+wbetl_dispatch::rollback ()
+{
+ /* Drop locks. */
+ const size_t n = m_wset_nb_entries;
+ for (size_t i = 0; i < n; ++i)
+ {
+ w_entry *w = &m_wset_entries[i];
+ if (w->next == NULL)
+ *w->lock = gtm_stmlock_set_version (w->version);
+ }
+
+ __sync_synchronize ();
+}
+
+void
+wbetl_dispatch::reinit ()
+{
+ gtm_cacheline_page *page;
+
+ m_rset_nb_entries = 0;
+ m_wset_nb_entries = 0;
+
+ if (m_wset_reallocate)
+ {
+ m_wset_reallocate = 0;
+ m_wset_entries = (w_entry *)
+ xrealloc (m_wset_entries, m_wset_size * sizeof(w_entry));
+ }
+
+ page = m_cache_page;
+ if (page)
+ {
+ /* Release all but one of the pages of cachelines. */
+ gtm_cacheline_page *prev = page->prev;
+ if (prev)
+ {
+ page->prev = 0;
+ delete prev;
+ }
+
+ /* Start the next cacheline allocation from the beginning. */
+ m_n_cache_page = 0;
+ }
+
+ m_start = m_end = gtm_get_clock ();
+}
+
+void
+wbetl_dispatch::fini ()
+{
+ delete m_cache_page;
+ free (m_rset_entries);
+ free (m_wset_entries);
+ delete this;
+}
+
+wbetl_dispatch::wbetl_dispatch ()
+ : gtm_dispatch (false, false)
+{
+ m_rset_entries = (r_entry *) xmalloc (RW_SET_SIZE * sizeof(r_entry));
+ m_rset_nb_entries = 0;
+ m_rset_size = RW_SET_SIZE;
+
+ m_wset_entries = (w_entry *) xmalloc (RW_SET_SIZE * sizeof(w_entry));
+ m_wset_nb_entries = 0;
+ m_wset_size = RW_SET_SIZE;
+ m_wset_reallocate = false;
+
+ m_start = m_end = gtm_get_clock ();
+
+ m_cache_page = 0;
+ m_n_cache_page = 0;
+}
+
+} // anon namespace
+
+gtm_dispatch *
+GTM::dispatch_wbetl ()
+{
+ return new wbetl_dispatch ();
+}
diff --git a/libitm/query.c b/libitm/query.cc
index a4f2d7e0209..1f03ddf20fe 100644
--- a/libitm/query.c
+++ b/libitm/query.cc
@@ -24,6 +24,7 @@
#include "libitm_i.h"
+using namespace GTM;
int ITM_REGPARM
_ITM_versionCompatible (int version)
@@ -45,7 +46,7 @@ _ITM_inTransaction (void)
struct gtm_transaction *tx = gtm_tx();
if (tx)
{
- if (tx->state & STATE_IRREVOKABLE)
+ if (tx->state & gtm_transaction::STATE_IRREVOCABLE)
return inIrrevocableTransaction;
else
return inRetryableTransaction;
diff --git a/libitm/retry.cc b/libitm/retry.cc
new file mode 100644
index 00000000000..c68b0d50698
--- /dev/null
+++ b/libitm/retry.cc
@@ -0,0 +1,80 @@
+/* Copyright (C) 2008, 2009 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"
+
+void
+GTM::gtm_transaction::decide_retry_strategy (gtm_restart_reason r)
+{
+ struct gtm_dispatch *disp = gtm_disp ();
+
+ this->restart_reason[r]++;
+ this->restart_total++;
+
+ bool retry_irr = (r == RESTART_SERIAL_IRR);
+ bool retry_serial = (this->restart_total > 100 || retry_irr);
+
+ if (retry_serial)
+ {
+ // In serialirr_mode we can succeed with the upgrade to
+ // write-lock but fail the trycommit. In any case, if the
+ // write lock is not yet held, grab it. Don't do this with
+ // an upgrade, since we've no need to preserve the state we
+ // acquired with the read.
+ if ((this->state & STATE_SERIAL) == 0)
+ {
+ serial_lock.read_unlock ();
+ serial_lock.write_lock ();
+ }
+
+ // ??? We can only retry with dispatch_serial when the transaction
+ // doesn't contain an abort. TODO: Create a serial mode dispatch
+ // that does logging in order to support abort.
+ if (this->prop & pr_hasNoAbort)
+ retry_irr = true;
+ }
+
+ if (retry_irr)
+ {
+ this->state = (STATE_SERIAL | STATE_IRREVOCABLE);
+ disp->fini ();
+ disp = dispatch_serial ();
+ set_gtm_disp (disp);
+ }
+ else
+ {
+ if (r == RESTART_NOT_READONLY)
+ {
+ assert ((this->prop & pr_readOnly) == 0);
+ if (disp->read_only ())
+ {
+ disp->fini ();
+ disp = dispatch_wbetl ();
+ set_gtm_disp (disp);
+ return;
+ }
+ }
+ disp->reinit ();
+ }
+}
diff --git a/libitm/serial.c b/libitm/serial.c
deleted file mode 100644
index 52673d75e15..00000000000
--- a/libitm/serial.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Copyright (C) 2008, 2009 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"
-
-
-static gtm_cacheline_mask gtm_cacheline_mask_sink;
-
-gtm_cacheline *
-GTM_null_read_lock (uintptr_t ptr)
-{
- return (gtm_cacheline *) ptr;
-}
-
-gtm_cacheline_mask_pair
-GTM_null_write_lock (uintptr_t ptr)
-{
- gtm_cacheline_mask_pair pair;
- pair.line = (gtm_cacheline *) ptr;
- pair.mask = &gtm_cacheline_mask_sink;
- return pair;
-}
-
-static bool
-serial_trycommit (void)
-{
- return true;
-}
-
-static void
-serial_rollback (void)
-{
- abort ();
-}
-
-static void
-serial_init (bool first UNUSED)
-{
-}
-
-static void
-serial_fini (void)
-{
-}
-
-const static struct gtm_dispatch serial_dispatch =
-{
- .R = GTM_null_read_lock,
- .RaR = GTM_null_read_lock,
- .RaW = GTM_null_read_lock,
- .RfW = GTM_null_read_lock,
-
- .W = GTM_null_write_lock,
- .WaR = GTM_null_write_lock,
- .WaW = GTM_null_write_lock,
-
- .trycommit = serial_trycommit,
- .rollback = serial_rollback,
- .init = serial_init,
- .fini = serial_fini,
-};
-
-
-/* Put the transaction into serial mode. */
-
-void
-GTM_serialmode (bool initial, bool irrevokable)
-{
- struct gtm_transaction *tx = gtm_tx();
- const struct gtm_dispatch *old_disp;
-
- if (tx->state & STATE_SERIAL)
- {
- if (irrevokable)
- tx->state |= STATE_IRREVOKABLE;
- return;
- }
-
- old_disp = gtm_disp ();
- set_gtm_disp (&serial_dispatch);
-
- if (initial)
- gtm_rwlock_write_lock (&gtm_serial_lock);
- else
- {
- gtm_rwlock_write_upgrade (&gtm_serial_lock);
- if (old_disp->trycommit ())
- old_disp->fini ();
- else
- {
- tx->state = STATE_SERIAL;
- GTM_restart_transaction (RESTART_VALIDATE_COMMIT);
- }
- }
-
- tx->state = STATE_SERIAL | (irrevokable ? STATE_IRREVOKABLE : 0);
-}
-
-
-void ITM_REGPARM
-_ITM_changeTransactionMode (_ITM_transactionState state)
-{
- assert (state == modeSerialIrrevocable);
- GTM_serialmode (false, true);
-}
diff --git a/libitm/serial.cc b/libitm/serial.cc
new file mode 100644
index 00000000000..2a69d48a406
--- /dev/null
+++ b/libitm/serial.cc
@@ -0,0 +1,122 @@
+/* Copyright (C) 2008, 2009 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 {
+
+gtm_cacheline_mask gtm_dispatch::mask_sink;
+
+const gtm_cacheline *
+gtm_dispatch::read_lock(const gtm_cacheline *addr, lock_type)
+{
+ return addr;
+}
+
+gtm_dispatch::mask_pair
+gtm_dispatch::write_lock(gtm_cacheline *addr, lock_type)
+{
+ return mask_pair (addr, &mask_sink);
+}
+
+} // namespace GTM
+
+// Avoid a dependency on libstdc++ for the pure virtuals in gtm_dispatch.
+extern "C" void HIDDEN
+__cxa_pure_virtual ()
+{
+ abort ();
+}
+
+using namespace GTM;
+
+namespace {
+
+class serial_dispatch : public gtm_dispatch
+{
+ public:
+ serial_dispatch() : gtm_dispatch(false, true) { }
+
+ // The read_lock and write_lock methods are implented by the base class.
+
+ virtual bool trycommit() { return true; }
+ virtual void rollback() { abort(); }
+ virtual void reinit() { }
+ virtual void fini() { }
+};
+
+} // anon namespace
+
+static const serial_dispatch o_serial_dispatch;
+
+gtm_dispatch *
+GTM::dispatch_serial ()
+{
+ return const_cast<serial_dispatch *>(&o_serial_dispatch);
+}
+
+// Put the transaction into serial-irrevocable mode.
+
+void
+GTM::gtm_transaction::serialirr_mode ()
+{
+ struct gtm_dispatch *disp = gtm_disp ();
+ bool need_restart = true;
+
+ if (this->state & STATE_SERIAL)
+ {
+ if (this->state & STATE_IRREVOCABLE)
+ return;
+
+ // Given that we're already serial, the trycommit better work.
+ bool ok = disp->trycommit ();
+ assert (ok);
+ disp->fini ();
+ need_restart = false;
+ }
+ else if (serial_lock.write_upgrade ())
+ {
+ this->state |= STATE_SERIAL;
+ if (disp->trycommit ())
+ {
+ disp->fini ();
+ need_restart = false;
+ }
+ }
+
+ if (need_restart)
+ restart (RESTART_SERIAL_IRR);
+ else
+ {
+ this->state |= (STATE_SERIAL | STATE_IRREVOCABLE);
+ set_gtm_disp (dispatch_serial ());
+ }
+}
+
+void ITM_REGPARM
+_ITM_changeTransactionMode (_ITM_transactionState state)
+{
+ assert (state == modeSerialIrrevocable);
+ gtm_tx()->serialirr_mode ();
+}
diff --git a/libitm/stmlock.h b/libitm/stmlock.h
new file mode 100644
index 00000000000..e3b76627289
--- /dev/null
+++ b/libitm/stmlock.h
@@ -0,0 +1,123 @@
+/* Copyright (C) 2009 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_STMLOCK_H
+#define LIBITM_STMLOCK_H 1
+
+namespace GTM HIDDEN {
+
+/* A versioned write lock on a cacheline. This must be wide enough to
+ store a pointer, and preferably wide enough to avoid overflowing the
+ version counter. Thus we use a "word", which should be 64-bits on
+ 64-bit systems even when their pointer size is forced smaller. */
+typedef gtm_word gtm_stmlock;
+
+/* This has to be the same size as gtm_stmlock, we just use this name
+ for documentation purposes. */
+typedef gtm_word gtm_version;
+
+/* The maximum value a version number can have. This is a consequence
+ of having the low bit of gtm_stmlock reserved for the owned bit. */
+#define GTM_VERSION_MAX (~(gtm_version)0 >> 1)
+
+/* A value that may be used to indicate "uninitialized" for a version. */
+#define GTM_VERSION_INVALID (~(gtm_version)0)
+
+/* This bit is set when the write lock is held. When set, the balance of
+ the bits in the lock is a pointer that references STM backend specific
+ data; it is up to the STM backend to determine if this thread holds the
+ lock. If this bit is clear, the balance of the bits are the last
+ version number committed to the cacheline. */
+static inline bool
+gtm_stmlock_owned_p (gtm_stmlock lock)
+{
+ return lock & 1;
+}
+
+static inline gtm_stmlock
+gtm_stmlock_set_owned (void *data)
+{
+ return (gtm_stmlock)(uintptr_t)data | 1;
+}
+
+static inline void *
+gtm_stmlock_get_addr (gtm_stmlock lock)
+{
+ return (void *)((uintptr_t)lock & ~(uintptr_t)1);
+}
+
+static inline gtm_version
+gtm_stmlock_get_version (gtm_stmlock lock)
+{
+ return lock >> 1;
+}
+
+static inline gtm_stmlock
+gtm_stmlock_set_version (gtm_version ver)
+{
+ return ver << 1;
+}
+
+/* We use a fixed set of locks for all memory, hashed into the
+ following table. */
+#define LOCK_ARRAY_SIZE (1024 * 1024)
+extern gtm_stmlock gtm_stmlock_array[LOCK_ARRAY_SIZE];
+
+static inline gtm_stmlock *
+gtm_get_stmlock (const gtm_cacheline *addr)
+{
+ size_t idx = ((uintptr_t) addr / CACHELINE_SIZE) % LOCK_ARRAY_SIZE;
+ return gtm_stmlock_array + idx;
+}
+
+/* The current global version number. */
+extern gtm_version gtm_clock;
+
+static inline gtm_version
+gtm_get_clock (void)
+{
+ gtm_version r;
+
+ __sync_synchronize ();
+ r = gtm_clock;
+ atomic_read_barrier ();
+
+ return r;
+}
+
+static inline gtm_version
+gtm_inc_clock (void)
+{
+ gtm_version r = __sync_add_and_fetch (&gtm_clock, 1);
+
+ /* ??? Ought to handle wraparound for 32-bit. */
+ if (sizeof(r) < 8 && r > GTM_VERSION_MAX)
+ abort ();
+
+ return r;
+}
+
+} // namespace GTM
+
+#endif // LIBITM_STMLOCK_H
diff --git a/libitm/testsuite/Makefile.in b/libitm/testsuite/Makefile.in
index 9b377788145..a84a14b14bc 100644
--- a/libitm/testsuite/Makefile.in
+++ b/libitm/testsuite/Makefile.in
@@ -76,6 +76,10 @@ CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
@@ -136,6 +140,7 @@ abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
ac_ct_FC = @ac_ct_FC@
am__include = @am__include@
diff --git a/libitm/useraction.c b/libitm/useraction.cc
index 2847741b065..adbe470f6cc 100644
--- a/libitm/useraction.c
+++ b/libitm/useraction.cc
@@ -24,17 +24,18 @@
#include "libitm_i.h"
+namespace GTM HIDDEN {
-typedef struct gtm_user_action
+struct gtm_user_action
{
struct gtm_user_action *next;
_ITM_userCommitFunction fn;
void *arg;
-} gtm_user_action;
+};
void
-GTM_run_actions (gtm_user_action **list)
+gtm_transaction::run_actions (gtm_user_action **list)
{
gtm_user_action *a = *list;
@@ -54,7 +55,7 @@ GTM_run_actions (gtm_user_action **list)
void
-GTM_free_actions (gtm_user_action **list)
+gtm_transaction::free_actions (gtm_user_action **list)
{
gtm_user_action *a = *list;
@@ -71,6 +72,9 @@ GTM_free_actions (gtm_user_action **list)
while (a);
}
+} // namespace GTM
+
+using namespace GTM;
void ITM_REGPARM
_ITM_addUserCommitAction(_ITM_userCommitFunction fn,
@@ -82,7 +86,7 @@ _ITM_addUserCommitAction(_ITM_userCommitFunction fn,
for (tx = gtm_tx(); tx->id != tid; tx = tx->prev)
continue;
- a = malloc (sizeof (*a));
+ a = (gtm_user_action *) xmalloc (sizeof (*a));
a->next = tx->commit_actions;
a->fn = fn;
a->arg = arg;
@@ -96,7 +100,7 @@ _ITM_addUserUndoAction(_ITM_userUndoFunction fn, void * arg)
gtm_transaction *tx = gtm_tx();
gtm_user_action *a;
- a = malloc (sizeof (*a));
+ a = (gtm_user_action *) xmalloc (sizeof (*a));
a->next = tx->undo_actions;
a->fn = fn;
a->arg = arg;
diff --git a/libitm/util.cc b/libitm/util.cc
new file mode 100644
index 00000000000..b9a8727de21
--- /dev/null
+++ b/libitm/util.cc
@@ -0,0 +1,79 @@
+/* Copyright (C) 2009 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 <stdarg.h>
+#include <stdio.h>
+
+namespace GTM HIDDEN {
+
+static void
+gtm_verror (const char *fmt, va_list list)
+{
+ fputs ("\nlibitm: ", stderr);
+ vfprintf (stderr, fmt, list);
+ fputc ('\n', stderr);
+}
+
+void
+GTM_error (const char *fmt, ...)
+{
+ va_list list;
+
+ va_start (list, fmt);
+ gtm_verror (fmt, list);
+ va_end (list);
+}
+
+void
+GTM_fatal (const char *fmt, ...)
+{
+ va_list list;
+
+ va_start (list, fmt);
+ gtm_verror (fmt, list);
+ va_end (list);
+
+ exit (EXIT_FAILURE);
+}
+
+void *
+xmalloc (size_t size)
+{
+ void *r = malloc (size);
+ if (r == 0)
+ GTM_fatal ("Out of memory allocating %lu bytes", (unsigned long) size);
+ return r;
+}
+
+void *
+xrealloc (void *old, size_t size)
+{
+ void *r = realloc (old, size);
+ if (r == 0)
+ GTM_fatal ("Out of memory allocating %lu bytes", (unsigned long) size);
+ return r;
+}
+
+} // namespace GTM