This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[trans-mem] initial commit of runtime library
- From: Richard Henderson <rth at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 21 Nov 2008 16:28:53 -0800
- Subject: [trans-mem] initial commit of runtime library
I'm about 75% of the way to having something that should run simple test
cases on x86 linux. But it's been 10+ days since I've committed
anything and that seems a bit too long to have it all sitting only on my
laptop.
r~
--- Makefile.def (revision 141843)
+++ Makefile.def (local)
@@ -154,6 +154,7 @@ target_modules = { module= qthreads; };
target_modules = { module= rda; };
target_modules = { module= libada; };
target_modules = { module= libgomp; lib_path=.libs; };
+target_modules = { module= libitm; lib_path=.libs; };
// These are (some of) the make targets to be done in each subdirectory.
// Not all; these are the ones which don't have special options.
--- configure.ac (revision 141843)
+++ configure.ac (local)
@@ -182,6 +182,7 @@ target_libraries="target-libgcc \
target-libgloss \
target-newlib \
target-libgomp \
+ target-libitm \
target-libstdc++-v3 \
target-libmudflap \
target-libssp \
@@ -439,6 +440,24 @@ if test x$enable_libgomp = x ; then
esac
fi
+# Disable libitm on non POSIX hosted systems.
+if test x$enable_libitm = x ; then
+ # Enable libitm by default on hosted POSIX systems.
+ case "${target}" in
+ *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu)
+ ;;
+ *-*-netbsd* | *-*-freebsd* | *-*-openbsd*)
+ ;;
+ *-*-solaris2* | *-*-sysv4* | *-*-irix6* | *-*-osf* | *-*-hpux11*)
+ ;;
+ *-*-darwin* | *-*-aix*)
+ ;;
+ *)
+ noconfigdirs="$noconfigdirs target-libitm"
+ ;;
+ esac
+fi
+
# Default libgloss CPU subdirectory.
libgloss_dir="$target_cpu"
=== libitm (new directory)
==================================================================
--- libitm/Makefile.am (revision 141843)
+++ libitm/Makefile.am (local)
@@ -0,0 +1,37 @@
+## Process this file with automake to produce Makefile.in
+
+ACLOCAL_AMFLAGS = -I .. -I ../config
+SUBDIRS = testsuite
+
+## May be used by toolexeclibdir.
+gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER)
+
+config_path = @config_path@
+search_path = $(addprefix $(top_srcdir)/config/, $(config_path)) $(top_srcdir)
+
+fincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/finclude
+libsubincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
+
+vpath % $(strip $(search_path))
+
+AM_CPPFLAGS = $(addprefix -I, $(search_path))
+AM_CFLAGS = $(XCFLAGS)
+AM_LDFLAGS = $(XLDFLAGS) $(SECTION_LDFLAGS) $(OPT_LDFLAGS)
+
+CCAS = $(CC)
+CCASFLAGS = $(CFLAGS)
+
+toolexeclib_LTLIBRARIES = libitm.la
+nodist_toolexeclib_HEADERS = libitm.spec
+
+if LIBITM_BUILD_VERSIONED_SHLIB
+libitm_version_script = -Wl,--version-script,$(top_srcdir)/libitm.map
+else
+libitm_version_script =
+endif
+libitm_version_info = -version-info $(libtool_VERSION)
+libitm_la_LDFLAGS = $(libitm_version_info) $(libitm_version_script) \
+ -no-undefined
+
+libitm_la_SOURCES = beginend.c dispatch.c local.c query.c retry.c \
+ rwlock.c serial.c sjlj.S useraction.c futex.c
--- libitm/acinclude.m4 (revision 141843)
+++ libitm/acinclude.m4 (local)
@@ -0,0 +1,303 @@
+dnl ----------------------------------------------------------------------
+dnl This whole bit snagged from libgfortran.
+
+dnl Check whether the target supports __sync_*_compare_and_swap.
+AC_DEFUN([LIBITM_CHECK_SYNC_BUILTINS], [
+ AC_CACHE_CHECK([whether the target supports __sync_*_compare_and_swap],
+ libitm_cv_have_sync_builtins, [
+ AC_TRY_LINK([], [int foo, bar; bar = __sync_val_compare_and_swap(&foo, 0, 1);],
+ libitm_cv_have_sync_builtins=yes, libitm_cv_have_sync_builtins=no)])
+ if test $libitm_cv_have_sync_builtins = yes; then
+ AC_DEFINE(HAVE_SYNC_BUILTINS, 1,
+ [Define to 1 if the target supports __sync_*_compare_and_swap])
+ fi])
+
+dnl Check whether the target supports hidden visibility.
+AC_DEFUN([LIBITM_CHECK_ATTRIBUTE_VISIBILITY], [
+ AC_CACHE_CHECK([whether the target supports hidden visibility],
+ libitm_cv_have_attribute_visibility, [
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror"
+ AC_TRY_COMPILE([void __attribute__((visibility("hidden"))) foo(void) { }],
+ [], libitm_cv_have_attribute_visibility=yes,
+ libitm_cv_have_attribute_visibility=no)
+ CFLAGS="$save_CFLAGS"])
+ if test $libitm_cv_have_attribute_visibility = yes; then
+ AC_DEFINE(HAVE_ATTRIBUTE_VISIBILITY, 1,
+ [Define to 1 if the target supports __attribute__((visibility(...))).])
+ fi])
+
+dnl Check whether the target supports dllexport
+AC_DEFUN([LIBITM_CHECK_ATTRIBUTE_DLLEXPORT], [
+ AC_CACHE_CHECK([whether the target supports dllexport],
+ libitm_cv_have_attribute_dllexport, [
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror"
+ AC_TRY_COMPILE([void __attribute__((dllexport)) foo(void) { }],
+ [], libitm_cv_have_attribute_dllexport=yes,
+ libitm_cv_have_attribute_dllexport=no)
+ CFLAGS="$save_CFLAGS"])
+ if test $libitm_cv_have_attribute_dllexport = yes; then
+ AC_DEFINE(HAVE_ATTRIBUTE_DLLEXPORT, 1,
+ [Define to 1 if the target supports __attribute__((dllexport)).])
+ fi])
+
+dnl Check whether the target supports symbol aliases.
+AC_DEFUN([LIBITM_CHECK_ATTRIBUTE_ALIAS], [
+ AC_CACHE_CHECK([whether the target supports symbol aliases],
+ libitm_cv_have_attribute_alias, [
+ AC_TRY_LINK([
+void foo(void) { }
+extern void bar(void) __attribute__((alias("foo")));],
+ [bar();], libitm_cv_have_attribute_alias=yes, libitm_cv_have_attribute_alias=no)])
+ if test $libitm_cv_have_attribute_alias = yes; then
+ AC_DEFINE(HAVE_ATTRIBUTE_ALIAS, 1,
+ [Define to 1 if the target supports __attribute__((alias(...))).])
+ fi])
+
+sinclude(../libtool.m4)
+dnl The lines below arrange for aclocal not to bring an installed
+dnl libtool.m4 into aclocal.m4, while still arranging for automake to
+dnl add a definition of LIBTOOL to Makefile.in.
+ifelse(,,,[AC_SUBST(LIBTOOL)
+AC_DEFUN([AM_PROG_LIBTOOL])
+AC_DEFUN([AC_LIBTOOL_DLOPEN])
+AC_DEFUN([AC_PROG_LD])
+])
+
+dnl ----------------------------------------------------------------------
+dnl This whole bit snagged from libstdc++-v3.
+
+dnl
+dnl LIBITM_ENABLE
+dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING)
+dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, permit a|b|c)
+dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, SHELL-CODE-HANDLER)
+dnl
+dnl See docs/html/17_intro/configury.html#enable for documentation.
+dnl
+m4_define([LIBITM_ENABLE],[dnl
+m4_define([_g_switch],[--enable-$1])dnl
+m4_define([_g_help],[AC_HELP_STRING(_g_switch$3,[$4 @<:@default=$2@:>@])])dnl
+ AC_ARG_ENABLE($1,_g_help,
+ m4_bmatch([$5],
+ [^permit ],
+ [[
+ case "$enableval" in
+ m4_bpatsubst([$5],[permit ])) ;;
+ *) AC_MSG_ERROR(Unknown argument to enable/disable $1) ;;
+ dnl Idea for future: generate a URL pointing to
+ dnl "onlinedocs/configopts.html#whatever"
+ esac
+ ]],
+ [^$],
+ [[
+ case "$enableval" in
+ yes|no) ;;
+ *) AC_MSG_ERROR(Argument to enable/disable $1 must be yes or no) ;;
+ esac
+ ]],
+ [[$5]]),
+ [enable_]m4_bpatsubst([$1],-,_)[=][$2])
+m4_undefine([_g_switch])dnl
+m4_undefine([_g_help])dnl
+])
+
+
+dnl
+dnl If GNU ld is in use, check to see if tricky linker opts can be used. If
+dnl the native linker is in use, all variables will be defined to something
+dnl safe (like an empty string).
+dnl
+dnl Defines:
+dnl SECTION_LDFLAGS='-Wl,--gc-sections' if possible
+dnl OPT_LDFLAGS='-Wl,-O1' if possible
+dnl LD (as a side effect of testing)
+dnl Sets:
+dnl with_gnu_ld
+dnl libitm_gnu_ld_version (possibly)
+dnl
+dnl The last will be a single integer, e.g., version 1.23.45.0.67.89 will
+dnl set libitm_gnu_ld_version to 12345. Zeros cause problems.
+dnl
+AC_DEFUN([LIBITM_CHECK_LINKER_FEATURES], [
+ # If we're not using GNU ld, then there's no point in even trying these
+ # tests. Check for that first. We should have already tested for gld
+ # by now (in libtool), but require it now just to be safe...
+ test -z "$SECTION_LDFLAGS" && SECTION_LDFLAGS=''
+ test -z "$OPT_LDFLAGS" && OPT_LDFLAGS=''
+ AC_REQUIRE([AC_PROG_LD])
+ AC_REQUIRE([AC_PROG_AWK])
+
+ # The name set by libtool depends on the version of libtool. Shame on us
+ # for depending on an impl detail, but c'est la vie. Older versions used
+ # ac_cv_prog_gnu_ld, but now it's lt_cv_prog_gnu_ld, and is copied back on
+ # top of with_gnu_ld (which is also set by --with-gnu-ld, so that actually
+ # makes sense). We'll test with_gnu_ld everywhere else, so if that isn't
+ # set (hence we're using an older libtool), then set it.
+ if test x${with_gnu_ld+set} != xset; then
+ if test x${ac_cv_prog_gnu_ld+set} != xset; then
+ # We got through "ac_require(ac_prog_ld)" and still not set? Huh?
+ with_gnu_ld=no
+ else
+ with_gnu_ld=$ac_cv_prog_gnu_ld
+ fi
+ fi
+
+ # Start by getting the version number. I think the libtool test already
+ # does some of this, but throws away the result.
+ changequote(,)
+ ldver=`$LD --version 2>/dev/null | head -1 | \
+ sed -e 's/GNU ld \(version \)\{0,1\}\(([^)]*) \)\{0,1\}\([0-9.][0-9.]*\).*/\3/'`
+ changequote([,])
+ libitm_gnu_ld_version=`echo $ldver | \
+ $AWK -F. '{ if (NF<3) [$]3=0; print ([$]1*100+[$]2)*100+[$]3 }'`
+
+ # Set --gc-sections.
+ if test "$with_gnu_ld" = "notbroken"; then
+ # GNU ld it is! Joy and bunny rabbits!
+
+ # All these tests are for C++; save the language and the compiler flags.
+ # Need to do this so that g++ won't try to link in libstdc++
+ ac_test_CFLAGS="${CFLAGS+set}"
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS='-x c++ -Wl,--gc-sections'
+
+ # Check for -Wl,--gc-sections
+ # XXX This test is broken at the moment, as symbols required for linking
+ # are now in libsupc++ (not built yet). In addition, this test has
+ # cored on solaris in the past. In addition, --gc-sections doesn't
+ # really work at the moment (keeps on discarding used sections, first
+ # .eh_frame and now some of the glibc sections for iconv).
+ # Bzzzzt. Thanks for playing, maybe next time.
+ AC_MSG_CHECKING([for ld that supports -Wl,--gc-sections])
+ AC_TRY_RUN([
+ int main(void)
+ {
+ try { throw 1; }
+ catch (...) { };
+ return 0;
+ }
+ ], [ac_sectionLDflags=yes],[ac_sectionLDflags=no], [ac_sectionLDflags=yes])
+ if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+ else
+ # this is the suspicious part
+ CFLAGS=''
+ fi
+ if test "$ac_sectionLDflags" = "yes"; then
+ SECTION_LDFLAGS="-Wl,--gc-sections $SECTION_LDFLAGS"
+ fi
+ AC_MSG_RESULT($ac_sectionLDflags)
+ fi
+
+ # Set linker optimization flags.
+ if test x"$with_gnu_ld" = x"yes"; then
+ OPT_LDFLAGS="-Wl,-O1 $OPT_LDFLAGS"
+ fi
+
+ AC_SUBST(SECTION_LDFLAGS)
+ AC_SUBST(OPT_LDFLAGS)
+])
+
+
+dnl
+dnl Add version tags to symbols in shared library (or not), additionally
+dnl marking other symbols as private/local (or not).
+dnl
+dnl --enable-symvers=style adds a version script to the linker call when
+dnl creating the shared library. The choice of version script is
+dnl controlled by 'style'.
+dnl --disable-symvers does not.
+dnl + Usage: LIBITM_ENABLE_SYMVERS[(DEFAULT)]
+dnl Where DEFAULT is either 'yes' or 'no'. Passing `yes' tries to
+dnl choose a default style based on linker characteristics. Passing
+dnl 'no' disables versioning.
+dnl
+AC_DEFUN([LIBITM_ENABLE_SYMVERS], [
+
+LIBITM_ENABLE(symvers,yes,[=STYLE],
+ [enables symbol versioning of the shared library],
+ [permit yes|no|gnu])
+
+# If we never went through the LIBITM_CHECK_LINKER_FEATURES macro, then we
+# don't know enough about $LD to do tricks...
+AC_REQUIRE([LIBITM_CHECK_LINKER_FEATURES])
+# FIXME The following test is too strict, in theory.
+if test $enable_shared = no ||
+ test "x$LD" = x ||
+ test x$libitm_gnu_ld_version = x; then
+ enable_symvers=no
+fi
+
+# Check to see if libgcc_s exists, indicating that shared libgcc is possible.
+if test $enable_symvers != no; then
+ AC_MSG_CHECKING([for shared libgcc])
+ ac_save_CFLAGS="$CFLAGS"
+ CFLAGS=' -lgcc_s'
+ AC_TRY_LINK(, [return 0;], libitm_shared_libgcc=yes, libitm_shared_libgcc=no)
+ CFLAGS="$ac_save_CFLAGS"
+ if test $libitm_shared_libgcc = no; then
+ cat > conftest.c <<EOF
+int main (void) { return 0; }
+EOF
+changequote(,)dnl
+ libitm_libgcc_s_suffix=`${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS \
+ -shared -shared-libgcc -o conftest.so \
+ conftest.c -v 2>&1 >/dev/null \
+ | sed -n 's/^.* -lgcc_s\([^ ]*\) .*$/\1/p'`
+changequote([,])dnl
+ rm -f conftest.c conftest.so
+ if test x${libitm_libgcc_s_suffix+set} = xset; then
+ CFLAGS=" -lgcc_s$libitm_libgcc_s_suffix"
+ AC_TRY_LINK(, [return 0;], libitm_shared_libgcc=yes)
+ CFLAGS="$ac_save_CFLAGS"
+ fi
+ fi
+ AC_MSG_RESULT($libitm_shared_libgcc)
+fi
+
+# For GNU ld, we need at least this version. The format is described in
+# LIBITM_CHECK_LINKER_FEATURES above.
+libitm_min_gnu_ld_version=21400
+# XXXXXXXXXXX libitm_gnu_ld_version=21390
+
+# Check to see if unspecified "yes" value can win, given results above.
+# Change "yes" into either "no" or a style name.
+if test $enable_symvers = yes; then
+ if test $with_gnu_ld = yes &&
+ test $libitm_shared_libgcc = yes;
+ then
+ if test $libitm_gnu_ld_version -ge $libitm_min_gnu_ld_version ; then
+ enable_symvers=gnu
+ else
+ # The right tools, the right setup, but too old. Fallbacks?
+ AC_MSG_WARN(=== Linker version $libitm_gnu_ld_version is too old for)
+ AC_MSG_WARN(=== full symbol versioning support in this release of GCC.)
+ AC_MSG_WARN(=== You would need to upgrade your binutils to version)
+ AC_MSG_WARN(=== $libitm_min_gnu_ld_version or later and rebuild GCC.)
+ if test $libitm_gnu_ld_version -ge 21200 ; then
+ # Globbing fix is present, proper block support is not.
+ dnl AC_MSG_WARN([=== Dude, you are soooo close. Maybe we can fake it.])
+ dnl enable_symvers=???
+ AC_MSG_WARN([=== Symbol versioning will be disabled.])
+ enable_symvers=no
+ else
+ # 2.11 or older.
+ AC_MSG_WARN([=== Symbol versioning will be disabled.])
+ enable_symvers=no
+ fi
+ fi
+ else
+ # just fail for now
+ AC_MSG_WARN([=== You have requested some kind of symbol versioning, but])
+ AC_MSG_WARN([=== either you are not using a supported linker, or you are])
+ AC_MSG_WARN([=== not building a shared libgcc_s (which is required).])
+ AC_MSG_WARN([=== Symbol versioning will be disabled.])
+ enable_symvers=no
+ fi
+fi
+
+AM_CONDITIONAL(LIBITM_BUILD_VERSIONED_SHLIB, test $enable_symvers != no)
+AC_MSG_NOTICE(versioning on shared library symbols is $enable_symvers)
+])
--- libitm/beginend.c (revision 141843)
+++ libitm/beginend.c (local)
@@ -0,0 +1,192 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#include "libitm.h"
+
+
+__thread struct gtm_thread gtm_thr;
+gtm_rwlock gtm_serial_lock;
+
+/* ??? Move elsewhere when we figure out library initialization. */
+unsigned long long gtm_spin_count_var = 1000;
+
+static uint32_t global_tid;
+
+/* Allocate a transaction structure. Reuse an old one if possible. */
+
+static struct gtm_transaction *
+alloc_tx (void)
+{
+ struct gtm_transaction *tx;
+
+ if (gtm_thr.free_tx_count == 0)
+ tx = malloc (sizeof (*tx));
+ else
+ {
+ gtm_thr.free_tx_count--;
+ tx = gtm_thr.free_tx[gtm_thr.free_tx_idx];
+ gtm_thr.free_tx_idx = (gtm_thr.free_tx_idx + 1) % MAX_FREE_TX;
+ }
+
+ return tx;
+}
+
+/* Queue a transaction structure for freeing. We never free the given
+ transaction immediately -- this is a requirement of abortTransaction
+ as the jmpbuf is used immediately after calling this function. Thus
+ the requirement that this queue be per-thread. */
+
+static void
+free_tx (struct gtm_transaction *tx)
+{
+ unsigned idx = (gtm_thr.free_tx_idx + gtm_thr.free_tx_count) % MAX_FREE_TX;
+
+ if (gtm_thr.free_tx_count == MAX_FREE_TX)
+ {
+ gtm_thr.free_tx_idx = (gtm_thr.free_tx_idx + 1) % MAX_FREE_TX;
+ free (gtm_thr.free_tx[idx]);
+ }
+ else
+ gtm_thr.free_tx_count++;
+
+ gtm_thr.free_tx[idx] = tx;
+}
+
+
+uint32_t REGPARM
+GTM_begin_transaction (uint32_t prop, const struct gtm_jmpbuf *jb)
+{
+ struct gtm_transaction *tx = alloc_tx ();
+
+ memset (tx, 0, sizeof (*tx));
+
+ tx->prop = prop;
+ tx->prev = gtm_thr.tx;
+ if (tx->prev)
+ tx->nesting = tx->prev->nesting + 1;
+ tx->id = __sync_add_and_fetch (&global_tid, 1);
+ tx->jb = *jb;
+
+ gtm_thr.tx = tx;
+
+ if ((prop & pr_doesGoIrrevocable) || !(prop & pr_instrumentedCode))
+ {
+ GTM_serialmode (true);
+ return (prop & pr_uninstrumentedCode
+ ? a_runUninstrumentedCode : a_runInstrumentedCode);
+ }
+
+ gtm_rwlock_read_lock (>m_serial_lock);
+
+ return a_runInstrumentedCode | a_saveLiveVariables;
+}
+
+static void
+GTM_rollback_transaction (void)
+{
+ gtm_thr.disp->rollback ();
+ GTM_rollback_local ();
+ GTM_free_actions (>m_thr.tx->commit_actions);
+ GTM_run_actions (>m_thr.tx->undo_actions);
+}
+
+void REGPARM
+_ITM_rollbackTransaction (const _ITM_srcLocation * loc UNUSED)
+{
+ assert ((gtm_thr.tx->prop & pr_hasNoAbort) == 0);
+ assert ((gtm_thr.tx->state & STATE_ABORTING) == 0);
+
+ GTM_rollback_transaction ();
+ gtm_thr.tx->state |= STATE_ABORTING;
+}
+
+void REGPARM
+_ITM_abortTransaction (_ITM_abortReason reason,
+ const _ITM_srcLocation *loc UNUSED)
+{
+ struct gtm_transaction *tx;
+
+ assert (reason == userAbort);
+ assert ((gtm_thr.tx->prop & pr_hasNoAbort) == 0);
+ assert ((gtm_thr.tx->state & STATE_ABORTING) == 0);
+
+ GTM_rollback_transaction ();
+
+ if (gtm_thr.tx->state & STATE_SERIAL)
+ gtm_rwlock_write_unlock (>m_serial_lock);
+ else
+ gtm_rwlock_read_unlock (>m_serial_lock);
+
+ tx = gtm_thr.tx;
+ gtm_thr.tx = tx->prev;
+ free_tx (tx);
+
+ GTM_longjmp (&tx->jb, a_abortTransaction | a_restoreLiveVariables);
+}
+
+static bool
+GTM_trycommit_transaction (void)
+{
+ if (gtm_thr.disp->trycommit ())
+ {
+ GTM_commit_local ();
+ GTM_free_actions (>m_thr.tx->undo_actions);
+ GTM_run_actions (>m_thr.tx->commit_actions);
+ return true;
+ }
+ return false;
+}
+
+bool REGPARM
+_ITM_tryCommitTransaction (const _ITM_srcLocation *loc UNUSED)
+{
+ assert ((gtm_thr.tx->state & STATE_ABORTING) == 0);
+ return GTM_trycommit_transaction ();
+}
+
+void REGPARM
+_ITM_commitTransaction(const _ITM_srcLocation *loc UNUSED)
+{
+ struct gtm_transaction *tx = gtm_thr.tx;
+ uint32_t actions;
+
+ if ((tx->state & STATE_ABORTING) || GTM_trycommit_transaction ())
+ {
+ gtm_thr.tx = tx->prev;
+ free_tx (tx);
+ return;
+ }
+
+ GTM_decide_retry_strategy ();
+
+ actions = a_runInstrumentedCode | a_restoreLiveVariables;
+ if ((tx->prop & (pr_doesGoIrrevocable | pr_uninstrumentedCode))
+ == (pr_doesGoIrrevocable | pr_uninstrumentedCode))
+ actions = a_runUninstrumentedCode | a_restoreLiveVariables;
+
+ GTM_longjmp (&tx->jb, actions);
+}
=== libitm/config (new directory)
==================================================================
=== libitm/config/linux (new directory)
==================================================================
--- libitm/config/linux/futex.c (revision 141843)
+++ libitm/config/linux/futex.c (local)
@@ -0,0 +1,76 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+/* Provide access to the futex system call. */
+
+#include "libitm.h"
+#include "futex.h"
+#include <errno.h>
+
+
+#define FUTEX_WAIT 0
+#define FUTEX_WAKE 1
+#define FUTEX_PRIVATE_FLAG 128L
+
+
+static long int gtm_futex_wait = FUTEX_WAIT | FUTEX_PRIVATE_FLAG;
+static long int gtm_futex_wake = FUTEX_WAKE | FUTEX_PRIVATE_FLAG;
+
+
+void REGPARM
+futex_wait (int *addr, int val)
+{
+ unsigned long long i, count = gtm_spin_count_var;
+ long res;
+
+ for (i = 0; i < count; i++)
+ if (__builtin_expect (*addr != val, 0))
+ return;
+ else
+ cpu_relax ();
+
+ res = sys_futex0 (addr, gtm_futex_wait, val);
+ if (__builtin_expect (res == -ENOSYS, 0))
+ {
+ gtm_futex_wait = FUTEX_WAIT;
+ gtm_futex_wake = FUTEX_WAKE;
+ sys_futex0 (addr, FUTEX_WAIT, val);
+ }
+}
+
+
+void REGPARM
+futex_wake (int *addr, int count)
+{
+ long res = sys_futex0 (addr, gtm_futex_wake, count);
+ if (__builtin_expect (res == -ENOSYS, 0))
+ {
+ gtm_futex_wait = FUTEX_WAIT;
+ gtm_futex_wake = FUTEX_WAKE;
+ sys_futex0 (addr, FUTEX_WAKE, count);
+ }
+}
--- libitm/config/linux/futex.h (revision 141843)
+++ libitm/config/linux/futex.h (local)
@@ -0,0 +1,46 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+/* Provide access to the futex system call. */
+
+#ifndef GTM_FUTEX_H
+#define GTM_FUTEX_H 1
+
+#ifdef HAVE_ATTRIBUTE_VISIBILITY
+# pragma GCC visibility push(hidden)
+#endif
+
+#include "futex_bits.h"
+
+extern void futex_wait (int *addr, int val) REGPARM;
+extern void futex_wake (int *addr, int count) REGPARM;
+
+#ifdef HAVE_ATTRIBUTE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
+#endif /* GTM_FUTEX_H */
--- libitm/config/linux/rwlock.c (revision 141843)
+++ libitm/config/linux/rwlock.c (local)
@@ -0,0 +1,257 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#include <limits.h>
+#include "libitm.h"
+#include "futex.h"
+
+
+/* Lock the summary bit on LOCK. Return the contents of the summary word
+ (without the summary lock bit included). */
+
+static int REGPARM
+rwlock_lock_summary (gtm_rwlock *lock)
+{
+ int o;
+
+ restart:
+ o = __sync_fetch_and_or (&lock->summary, RWLOCK_S_LOCK);
+ if (o & RWLOCK_S_LOCK)
+ {
+ do
+ cpu_relax ();
+ while (lock->summary & RWLOCK_S_LOCK);
+ goto restart;
+ }
+
+ return o;
+}
+
+
+/* Acquire a RW lock for reading. */
+
+void REGPARM
+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 (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 REGPARM
+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 (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 (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 (!__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 REGPARM
+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 (o & RWLOCK_S_LOCK)
+ {
+ cpu_relax ();
+ goto restart;
+ }
+
+ /* If there's already someone trying to upgrade, then we fail. */
+ if (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 (!__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 REGPARM
+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 (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 (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 REGPARM
+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 (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 (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;
+}
--- libitm/config/linux/rwlock.h (revision 141843)
+++ libitm/config/linux/rwlock.h (local)
@@ -0,0 +1,53 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#ifndef GTM_RWLOCK_H
+#define GTM_RWLOCK_H
+
+/* The read-write summary definition. */
+
+#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
+
+typedef struct {
+ int summary;
+ int a_readers;
+ int w_readers;
+ int w_writers;
+} gtm_rwlock;
+
+extern void REGPARM gtm_rwlock_read_lock (gtm_rwlock *);
+extern void REGPARM gtm_rwlock_write_lock (gtm_rwlock *);
+extern bool REGPARM gtm_rwlock_write_upgrade (gtm_rwlock *);
+extern void REGPARM gtm_rwlock_read_unlock (gtm_rwlock *);
+extern void REGPARM gtm_rwlock_write_unlock (gtm_rwlock *);
+
+#endif /* GTM_RWLOCK_H */
=== libitm/config/linux/x86 (new directory)
==================================================================
--- libitm/config/linux/x86/futex_bits.h (revision 141843)
+++ libitm/config/linux/x86/futex_bits.h (local)
@@ -0,0 +1,96 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#ifdef __LP64__
+# ifndef SYS_futex
+# define SYS_futex 202
+# endif
+
+static inline long
+sys_futex0 (int *addr, long op, long val)
+{
+ long res;
+
+ __asm volatile ("syscall"
+ : "=a" (res)
+ : "0" (SYS_futex), "D" (addr), "S" (op), "d" (val)
+ : "r11", "rcx", "memory");
+
+ return res;
+}
+
+#else
+# ifndef SYS_futex
+# define SYS_futex 240
+# endif
+
+# ifdef __PIC__
+
+static inline long
+sys_futex0 (int *addr, int op, int val)
+{
+ long res;
+
+ __asm volatile ("xchgl\t%%ebx, %2\n\t"
+ "int\t$0x80\n\t"
+ "xchgl\t%%ebx, %2"
+ : "=a" (res)
+ : "0"(SYS_futex), "r" (addr), "c"(op),
+ "d"(val), "S"(0)
+ : "memory");
+ return res;
+}
+
+# else
+
+static inline long
+sys_futex0 (int *addr, int op, int val)
+{
+ long res;
+
+ __asm volatile ("int $0x80"
+ : "=a" (res)
+ : "0"(SYS_futex), "b" (addr), "c"(op),
+ "d"(val), "S"(0)
+ : "memory");
+ return res;
+}
+
+# endif /* __PIC__ */
+#endif /* __LP64__ */
+
+static inline void
+cpu_relax (void)
+{
+ __asm volatile ("rep; nop" : : : "memory");
+}
+
+static inline void
+atomic_write_barrier (void)
+{
+ __sync_synchronize ();
+}
=== libitm/config/x86 (new directory)
==================================================================
--- libitm/config/x86/sjlj.S (revision 141843)
+++ libitm/config/x86/sjlj.S (local)
@@ -0,0 +1,108 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+ .text
+ .p2align 4
+ .globl _ITM_beginTransaction
+ .type _ITM_beginTransaction, @function
+
+_ITM_beginTransaction:
+ .cfi_startproc
+#ifdef __LP64__
+ leaq 8(%rsp), %rax
+ movq (%rsp), %r8
+ subq $72, %rsp
+ .cfi_def_cfa_offset 80
+ movq %rax, (%rsp)
+ movq %r8, 8(%rsp)
+ movq %rbx, 16(%rsp)
+ movq %rbp, 24(%rsp)
+ movq %r12, 32(%rsp)
+ movq %r13, 40(%rsp)
+ movq %r14, 48(%rsp)
+ movq %r15, 56(%rsp)
+ movq %rsp, %rsi
+ call GTM_begin_transaction
+ addq $72, %rsp
+ .cfi_def_cfa_offset 8
+ ret
+#else
+ leal 4(%esp), %ecx
+ subl $28, %esp
+ .cfi_def_cfa_offset 32
+ movl %ecx, 8(%esp)
+ movl %ebx, 12(%esp)
+ movl %esi, 16(%esp)
+ movl %edi, 20(%esp)
+ movl %ebp, 24(%esp)
+ leal 8(%esp), %edx
+ call GTM_begin_transaction
+ addl $28, %esp
+ .cfi_def_cfa_offset 4
+ ret
+#endif
+ .cfi_endproc
+ .size _ITM_beginTransaction, .-_ITM_beginTransaction
+
+ .p2align 4
+ .globl GTM_longjmp
+ .type GTM_longjmp, @function
+ .hidden GTM_longjmp
+
+GTM_longjmp:
+ .cfi_startproc
+#ifdef __LP64__
+ movq (%rsi), %rcx
+ movq 8(%rsi), %rdx
+ movq 16(%rsi), %rbx
+ movq 24(%rsi), %rbp
+ movq 32(%rsi), %r12
+ movq 40(%rsi), %r13
+ movq 48(%rsi), %r14
+ movq 56(%rsi), %r15
+ movl %edi, %eax
+ .cfi_def_cfa %rcx, 0
+ .cfi_register %rip, %rdx
+ movq %rcx, %rsp
+ jmp *%rdx
+#else
+ xchgl %eax, %edx
+ movl (%edx), %ecx
+ movl 4(%edx), %ebx
+ movl 8(%edx), %esi
+ movl 12(%edx), %edi
+ movl 16(%edx), %ebp
+ movl 20(%edx), %edx
+ .cfi_def_cfa %ecx, 0
+ .cfi_register %eip, %edx
+ movl %ecx, %esp
+ jmp *%edx
+#endif
+ .cfi_endproc
+ .size GTM_longjmp, .-GTM_longjmp
+
+.section .note.GNU-stack, "", @progbits
--- libitm/config/x86/target.h (revision 141843)
+++ libitm/config/x86/target.h (local)
@@ -0,0 +1,46 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#ifdef __LP64__
+
+struct gtm_jmpbuf
+{
+ unsigned long cfa;
+ unsigned long i[7];
+};
+
+#else
+
+struct gtm_jmpbuf
+{
+ unsigned long cfa;
+ unsigned long i[5];
+};
+
+#define REGPARM __attribute__((regparm(2)))
+
+#endif
--- libitm/configure.ac (revision 141843)
+++ libitm/configure.ac (local)
@@ -0,0 +1,245 @@
+# Process this file with autoconf to produce a configure script, like so:
+# aclocal -I ../config && autoconf && autoheader && automake
+
+AC_PREREQ(2.59)
+AC_INIT([GNU TM Runtime Library], 1.0,,[libitm])
+AC_CONFIG_HEADER(config.h)
+
+# -------
+# Options
+# -------
+
+AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
+LIBITM_ENABLE(version-specific-runtime-libs, no, ,
+ [Specify that runtime libraries should be installed in a compiler-specific directory],
+ permit yes|no)
+AC_MSG_RESULT($enable_version_specific_runtime_libs)
+
+# We would like our source tree to be readonly. However when releases or
+# pre-releases are generated, the flex/bison generated files as well as the
+# various formats of manuals need to be included along with the rest of the
+# sources. Therefore we have --enable-generated-files-in-srcdir to do
+# just that.
+AC_MSG_CHECKING([for --enable-generated-files-in-srcdir])
+LIBITM_ENABLE(generated-files-in-srcdir, no, ,
+ [put copies of generated files in source dir intended for creating source
+ tarballs for users without texinfo bison or flex.],
+ permit yes|no)
+AC_MSG_RESULT($enable_generated_files_in_srcdir)
+AM_CONDITIONAL(GENINSRC, test "$enable_generated_files_in_srcdir" = yes)
+
+
+# -------
+# -------
+
+# Gets build, host, target, *_vendor, *_cpu, *_os, etc.
+#
+# You will slowly go insane if you do not grok the following fact: when
+# building this library, the top-level /target/ becomes the library's /host/.
+#
+# configure then causes --target to default to --host, exactly like any
+# other package using autoconf. Therefore, 'target' and 'host' will
+# always be the same. This makes sense both for native and cross compilers
+# just think about it for a little while. :-)
+#
+# Also, if this library is being configured as part of a cross compiler, the
+# top-level configure script will pass the "real" host as $with_cross_host.
+#
+# Do not delete or change the following two lines. For why, see
+# http://gcc.gnu.org/ml/libstdc++/2003-07/msg00451.html
+AC_CANONICAL_SYSTEM
+target_alias=${target_alias-$host_alias}
+
+# Sets up automake. Must come after AC_CANONICAL_SYSTEM. Each of the
+# following is magically included in AUTOMAKE_OPTIONS in each Makefile.am.
+# 1.9.0: minimum required version
+# no-define: PACKAGE and VERSION will not be #define'd in config.h (a bunch
+# of other PACKAGE_* variables will, however, and there's nothing
+# we can do about that; they come from AC_INIT).
+# foreign: we don't follow the normal rules for GNU packages (no COPYING
+# file in the top srcdir, etc, etc), so stop complaining.
+# -Wall: turns on all automake warnings...
+# -Wno-portability: ...except this one, since GNU make is required.
+# -Wno-override: ... and this one, since we do want this in testsuite.
+AM_INIT_AUTOMAKE([1.9.0 foreign -Wall -Wno-portability -Wno-override])
+AM_ENABLE_MULTILIB(, ..)
+
+# Calculate toolexeclibdir
+# Also toolexecdir, though it's only used in toolexeclibdir
+case ${enable_version_specific_runtime_libs} in
+ yes)
+ # Need the gcc compiler version to know where to install libraries
+ # and header files if --enable-version-specific-runtime-libs option
+ # is selected.
+ toolexecdir='$(libdir)/gcc/$(target_alias)'
+ toolexeclibdir='$(toolexecdir)/$(gcc_version)$(MULTISUBDIR)'
+ ;;
+ no)
+ if test -n "$with_cross_host" &&
+ test x"$with_cross_host" != x"no"; then
+ # Install a library built with a cross compiler in tooldir, not libdir.
+ toolexecdir='$(exec_prefix)/$(target_alias)'
+ toolexeclibdir='$(toolexecdir)/lib'
+ else
+ toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
+ toolexeclibdir='$(libdir)'
+ fi
+ multi_os_directory=`$CC -print-multi-os-directory`
+ case $multi_os_directory in
+ .) ;; # Avoid trailing /.
+ *) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;;
+ esac
+ ;;
+esac
+AC_SUBST(toolexecdir)
+AC_SUBST(toolexeclibdir)
+
+# Check the compiler.
+# The same as in boehm-gc and libstdc++. Have to borrow it from there.
+# We must force CC to /not/ be precious variables; otherwise
+# the wrong, non-multilib-adjusted value will be used in multilibs.
+# As a side effect, we have to subst CFLAGS ourselves.
+
+m4_rename([_AC_ARG_VAR_PRECIOUS],[real_PRECIOUS])
+m4_define([_AC_ARG_VAR_PRECIOUS],[])
+AC_PROG_CC
+m4_rename([real_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
+
+AC_SUBST(CFLAGS)
+
+# In order to override CFLAGS_FOR_TARGET, all of our special flags go
+# in XCFLAGS. But we need them in CFLAGS during configury. So put them
+# in both places for now and restore CFLAGS at the end of config.
+save_CFLAGS="$CFLAGS"
+
+# Add -Wall -Werror if we are using GCC.
+if test "x$GCC" = "xyes"; then
+ XCFLAGS="$XCFLAGS -Wall -Werror"
+fi
+
+# Find other programs we need.
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(RANLIB, ranlib, ranlib-not-found-in-path-error)
+AC_PATH_PROG(PERL, perl, perl-not-found-in-path-error)
+AC_PROG_MAKE_SET
+AC_PROG_INSTALL
+
+# See if makeinfo has been installed and is modern enough
+# that we can use it.
+ACX_CHECK_PROG_VER([MAKEINFO], [makeinfo], [--version],
+ [GNU texinfo.* \([0-9][0-9.]*\)],
+ [4.[4-9]*|4.[1-9][0-9]*|[5-9]*|[1-9][0-9]*])
+AM_CONDITIONAL(BUILD_INFO, test $gcc_cv_prog_makeinfo_modern = "yes")
+
+
+# Configure libtool
+AM_PROG_LIBTOOL
+AC_SUBST(enable_shared)
+AC_SUBST(enable_static)
+
+AM_MAINTAINER_MODE
+
+# We need gfortran to compile parts of the library
+# We can't use AC_PROG_FC because it expects a fully working gfortran.
+#AC_PROG_FC(gfortran)
+FC="$GFORTRAN"
+AC_PROG_FC(gfortran)
+FCFLAGS="$FCFLAGS -Wall"
+
+# For libtool versioning info, format is CURRENT:REVISION:AGE
+libtool_VERSION=1:0:0
+AC_SUBST(libtool_VERSION)
+
+# Check header files.
+AC_STDC_HEADERS
+AC_HEADER_TIME
+ACX_HEADER_STRING
+AC_CHECK_HEADERS(unistd.h semaphore.h sys/loadavg.h sys/time.h sys/time.h)
+
+GCC_HEADER_STDINT(gstdint.h)
+
+# 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.
+XPCFLAGS=""
+CFLAGS="$CFLAGS -pthread"
+AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <pthread.h>
+ void *g(void *d) { return NULL; }],
+ [pthread_t t; pthread_create(&t,NULL,g,NULL);])],
+ [XPCFLAGS=" -Wc,-pthread"],
+ [CFLAGS="$save_CFLAGS" LIBS="-lpthread $LIBS"
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [#include <pthread.h>
+ void *g(void *d) { return NULL; }],
+ [pthread_t t; pthread_create(&t,NULL,g,NULL);])],
+ [],
+ [AC_MSG_ERROR([Pthreads are required to build libitm])])])
+
+# Check for functions needed.
+AC_CHECK_FUNCS(getloadavg clock_gettime strtoull)
+
+# Check for broken semaphore implementation on darwin.
+# sem_init returns: sem_init error: Function not implemented.
+case "$host" in
+ *-darwin*)
+ AC_DEFINE(HAVE_BROKEN_POSIX_SEMAPHORES, 1,
+ Define if the POSIX Semaphores do not work on your system.)
+ ;;
+esac
+
+GCC_LINUX_FUTEX(:)
+
+# See if we support thread-local storage.
+GCC_CHECK_TLS
+
+# See what sort of export controls are availible.
+LIBITM_CHECK_ATTRIBUTE_VISIBILITY
+LIBITM_CHECK_ATTRIBUTE_DLLEXPORT
+LIBITM_CHECK_ATTRIBUTE_ALIAS
+LIBITM_ENABLE_SYMVERS
+
+if test $enable_symvers = gnu; then
+ AC_DEFINE(LIBITM_GNU_SYMBOL_VERSIONING, 1,
+ [Define to 1 if GNU symbol versioning is used for libitm.])
+fi
+
+# Get target configury.
+. ${srcdir}/configure.tgt
+CFLAGS="$save_CFLAGS $XCFLAGS"
+
+# Check for __sync_val_compare_and_swap, but only after the target has
+# had a chance to set XCFLAGS.
+LIBITM_CHECK_SYNC_BUILTINS
+
+XCFLAGS="$XCFLAGS$XPCFLAGS"
+
+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
+ multilib_arg=
+fi
+
+# Set up the set of libraries that we need to link against for libitm.
+# Note that the GOMP_SELF_SPEC in gcc.c will force -pthread for -fopenmp,
+# which will force linkage against -lpthread (or equivalent for the system).
+# That's not 100% ideal, but about the best we can do easily.
+if test $enable_shared = yes; then
+ link_itm="-litm %{static: $LIBS}"
+else
+ link_itm="-litm $LIBS"
+fi
+AC_SUBST(link_itm)
+
+AC_CONFIG_FILES(Makefile libitm.spec)
+AC_OUTPUT
--- libitm/configure.tgt (revision 141843)
+++ libitm/configure.tgt (local)
@@ -0,0 +1,121 @@
+# This is the target specific configuration file. This is invoked by the
+# autoconf generated configure script. Putting it in a separate shell file
+# lets us skip running autoconf when modifying target specific information.
+
+# This file switches on the shell variable ${target}, and sets the
+# following shell variables:
+# config_path An ordered list of directories to search for
+# sources and headers. This is relative to the
+# config subdirectory of the source tree.
+# XCFLAGS Add extra compile flags to use.
+# XLDFLAGS Add extra link flags to use.
+
+# Optimize TLS usage by avoiding the overhead of dynamic allocation.
+if test $gcc_cv_have_tls = yes ; then
+ case "${target}" in
+
+ *-*-linux*)
+ XCFLAGS="${XCFLAGS} -ftls-model=initial-exec"
+ ;;
+ esac
+fi
+
+# Since we require POSIX threads, assume a POSIX system by default.
+config_path="posix"
+
+# Check for futex enabled all at once.
+if test $enable_linux_futex = yes; then
+ case "${target}" in
+
+ alpha*-*-linux*)
+ config_path="linux/alpha linux alpha posix"
+ ;;
+
+ ia64*-*-linux*)
+ config_path="linux/ia64 linux ia64 posix"
+ ;;
+
+ mips*-*-linux*)
+ config_path="linux/mips linux mips posix"
+ ;;
+
+ powerpc*-*-linux*)
+ config_path="linux/powerpc linux powerpc posix"
+ ;;
+
+ s390*-*-linux*)
+ config_path="linux/s390 linux s390 posix"
+ ;;
+
+ # Note that bare i386 is not included here. We need cmpxchg.
+ i[456]86-*-linux*)
+ config_path="linux/x86 linux x86 posix"
+ case " ${CC} ${CFLAGS} " in
+ *" -m64 "*)
+ ;;
+ *)
+ if test -z "$with_arch"; then
+ XCFLAGS="${XCFLAGS} -march=i486 -msse2 -mtune=${target_cpu}"
+ fi
+ esac
+ ;;
+
+ # Similar jiggery-pokery for x86_64 multilibs, except here we
+ # can't rely on the --with-arch configure option, since that
+ # applies to the 64-bit side.
+ x86_64-*-linux*)
+ config_path="linux/x86 linux x86 posix"
+ case " ${CC} ${CFLAGS} " in
+ *" -m32 "*)
+ XCFLAGS="${XCFLAGS} -march=i486 -msse2 -mtune=i686"
+ ;;
+ esac
+ ;;
+
+ # Note that sparcv7 and sparcv8 is not included here. We need cas.
+ sparcv9-*-linux* | sparc64-*-linux*)
+ echo "int i;" > conftestx.c
+ if ${CC} ${CFLAGS} -c -o conftestx.o conftestx.c > /dev/null 2>&1; then
+ config_path="linux/sparc linux sparc posix"
+ case "`/usr/bin/file conftestx.o`" in
+ *32-bit*)
+ case " ${CC} ${CFLAGS}" in
+ *" -mcpu=ultrasparc"*)
+ ;;
+ *)
+ XCFLAGS="${XCFLAGS} -mcpu=v9"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -f conftestx.c conftestx.o
+ ;;
+ esac
+fi
+
+# Other system configury
+case "${target}" in
+
+ *-*-hpux11*)
+ # HPUX v11.x requires -lrt to resolve sem_init in libgomp.la
+ XLDFLAGS="${XLDFLAGS} -lrt"
+ ;;
+
+ *-*-mingw32*)
+ config_path="mingw32 posix"
+ ;;
+
+ *-*-solaris2.[56]*)
+ config_path="posix95 posix"
+ XLDFLAGS="${XLDFLAGS} -lposix4"
+ ;;
+
+ *-*-darwin*)
+ config_path="bsd posix"
+ ;;
+
+ *)
+ ;;
+
+esac
--- libitm/dispatch.c (revision 141843)
+++ libitm/dispatch.c (local)
@@ -0,0 +1,68 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#include "libitm.h"
+
+
+#define _ITM_READ(R, T) \
+_ITM_TYPE_##T REGPARM _ITM_##R##T(const _ITM_TYPE_##T *ptr) \
+{ \
+ return gtm_thr.disp->R##T (ptr); \
+}
+
+#define _ITM_WRITE(W, T) \
+void REGPARM _ITM_##W##T(_ITM_TYPE_##T *ptr, _ITM_TYPE_##T val) \
+{ \
+ gtm_thr.disp->W##T (ptr, val); \
+}
+
+_ITM_ALL_TYPES (_ITM_ALL_READS)
+_ITM_ALL_TYPES (_ITM_ALL_WRITES)
+
+#undef _ITM_READ
+#undef _ITM_WRITE
+
+#define _ITM_MCPY_RW(FN, R, W) \
+void REGPARM _ITM_##FN##R##W (void *dst, const void *src, size_t len) \
+{ \
+ gtm_thr.disp->FN##R##W (dst, src, len); \
+}
+
+_ITM_MCPY(memcpy)
+_ITM_MCPY(memmove)
+
+#undef _ITM_MCPY_RW
+
+#define _ITM_MSET_W(FN, W) \
+void REGPARM _ITM_##FN##W (void *dst, int src, size_t len) \
+{ \
+ gtm_thr.disp->FN##W (dst, src, len); \
+}
+
+_ITM_MSET(memset)
+
+#undef _ITM_MSET_W
--- libitm/libitm.h (revision 141843)
+++ libitm/libitm.h (local)
@@ -0,0 +1,348 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+/* The external interface of this library follows the specification described
+ in version 1 of http://www.intel.com/some/path/here.pdf. */
+
+#ifndef LIBITM_H
+#define LIBITM_H 1
+
+#include "config.h"
+#include "target.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef REGPARM
+# define REGPARM
+#endif
+
+#define NORETURN __attribute__((noreturn))
+#define UNUSED __attribute__((unused))
+
+/* The following are externally visible definitions and functions, though
+ only very few of these should be called by user code. */
+/* ??? Move declarations usable by user code to another header; figure out
+ how to unobtrusively define REGPARM there. */
+
+/* Values used as arguments to abort. */
+typedef enum {
+ userAbort = 1,
+ userRetry = 2,
+ TMConflict= 4,
+ exceptionBlockAbort = 8
+} _ITM_abortReason;
+
+/* Arguments to changeTransactionMode */
+typedef enum
+{
+ modeSerialIrrevocable,
+} _ITM_transactionState;
+
+/* Results from inTransaction */
+typedef enum
+{
+ outsideTransaction = 0, /* So "if (inTransaction(td))" works */
+ inRetryableTransaction,
+ inIrrevocableTransaction
+} _ITM_howExecuting;
+
+/* Values to describe properties of code, passed in to startTransaction */
+typedef enum
+{
+ pr_instrumentedCode = 0x0001,
+ pr_uninstrumentedCode = 0x0002,
+ pr_multiwayCode = pr_instrumentedCode | pr_uninstrumentedCode,
+ pr_hasNoXMMUpdate = 0x0004,
+ pr_hasNoAbort = 0x0008,
+ pr_hasNoRetry = 0x0010,
+ pr_hasNoIrrevocable = 0x0020,
+ pr_doesGoIrrevocable = 0x0040,
+ pr_hasNoSimpleReads = 0x0080,
+ pr_aWBarriersOmitted = 0x0100,
+ pr_RaRBarriersOmitted = 0x0200,
+ pr_undoLogCode = 0x0400,
+ pr_preferUninstrumented=0x0800,
+ pr_exceptionBlock = 0x1000,
+ pr_hasElse = 0x2000,
+} _ITM_codeProperties;
+
+/* Result from startTransaction that describes what actions to take. */
+typedef enum
+{
+ a_runInstrumentedCode = 0x01,
+ a_runUninstrumentedCode = 0x02,
+ a_saveLiveVariables = 0x04,
+ a_restoreLiveVariables = 0x08,
+ a_abortTransaction = 0x10,
+} _ITM_actions;
+
+typedef struct
+{
+ uint32_t reserved_1;
+ uint32_t flags;
+ uint32_t reserved_2;
+ uint32_t reserved_3;
+ const char *psource;
+} _ITM_srcLocation;
+
+typedef void (* _ITM_userUndoFunction)(void *);
+typedef void (* _ITM_userCommitFunction) (void *);
+
+#define _ITM_VERSION "0.90 (Feb 29 2008)"
+#define _ITM_VERSION_NO 90
+
+extern int _ITM_versionCompatible (int) REGPARM;
+extern const char * _ITM_libraryVersion (void) REGPARM;
+
+void _ITM_error(const _ITM_srcLocation *, int errorCode) REGPARM NORETURN;
+
+extern _ITM_howExecuting _ITM_inTransaction(void) REGPARM;
+
+typedef uint32_t _ITM_transactionId_t; /* Transaction identifier */
+#define _ITM_noTransactionId 1 /* Id for non-transactional code. */
+
+extern _ITM_transactionId_t _ITM_getTransactionId(void) REGPARM;
+
+extern uint32_t _ITM_beginTransaction(uint32_t, const _ITM_srcLocation *)
+ REGPARM;
+
+extern void _ITM_abortTransaction(_ITM_abortReason,
+ const _ITM_srcLocation *) REGPARM NORETURN;
+extern void _ITM_rollbackTransaction (const _ITM_srcLocation *) REGPARM;
+
+extern void _ITM_commitTransaction (const _ITM_srcLocation *) REGPARM;
+extern bool _ITM_tryCommitTransaction(const _ITM_srcLocation *) REGPARM;
+
+extern void _ITM_changeTransactionMode (_ITM_transactionState,
+ const _ITM_srcLocation *) REGPARM;
+
+/* The following typedefs exist to make the macro expansions below work
+ properly. They are not part of any API. */
+typedef uint8_t _ITM_TYPE_U1;
+typedef uint16_t _ITM_TYPE_U2;
+typedef uint32_t _ITM_TYPE_U4;
+typedef uint64_t _ITM_TYPE_U8;
+typedef float _ITM_TYPE_F;
+typedef double _ITM_TYPE_D;
+typedef long double _ITM_TYPE_E;
+typedef float _Complex _ITM_TYPE_CF;
+typedef double _Complex _ITM_TYPE_CD;
+typedef long double _Complex _ITM_TYPE_CE;
+
+/* ??? These are really specific to i386. Work out some way to handle
+ platform-specific vectors, assuming U8 doesn't fit the bill. */
+typedef int _ITM_TYPE_M64
+ __attribute__ ((__vector_size__ (8), __may_alias__));
+typedef float _ITM_TYPE_M128
+ __attribute__ ((__vector_size__ (16), __may_alias__));
+typedef float _ITM_TYPE_M256
+ __attribute__ ((__vector_size__ (32), __may_alias__));
+
+#define _ITM_READ(R, T) \
+ extern _ITM_TYPE_##T _ITM_##R##T (const _ITM_TYPE_##T *) REGPARM;
+#define _ITM_WRITE(W, T) \
+ extern void _ITM_##W##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) REGPARM;
+
+#define _ITM_ALL_READS(T) \
+ _ITM_READ(R, T) _ITM_READ(RaR, T) _ITM_READ(RaW, T) _ITM_READ(RfW, T)
+#define _ITM_ALL_WRITES(T) \
+ _ITM_WRITE(W, T) _ITM_WRITE(WaR, T) _ITM_WRITE(WaW, T)
+
+#define _ITM_ALL_TYPES(M) \
+ M(U1) M(U2) M(U4) M(U8) M(F) M(D) M(E) \
+ M(CF) M(CD) M(CE) M(M64) M(M128) M(M256)
+
+_ITM_ALL_TYPES(_ITM_ALL_READS)
+_ITM_ALL_TYPES(_ITM_ALL_WRITES)
+
+#define _ITM_LOG(T) \
+ extern void _ITM_L##T (const _ITM_TYPE_##T *) REGPARM;
+
+_ITM_ALL_TYPES(_ITM_LOG)
+
+#undef _ITM_READ
+#undef _ITM_WRITE
+
+#define _ITM_MCPY_RW(FN, R, W) \
+ extern void _ITM_##FN##R##W (void *, const void *, size_t) REGPARM;
+#define _ITM_MCPY_Wt(FN, R) \
+ _ITM_MCPY_RW(FN,R,Wt) _ITM_MCPY_RW(FN,R,WtaR) _ITM_MCPY_RW(FN,R,WtaW)
+#define _ITM_MCPY(FN) \
+ _ITM_MCPY_Wt(FN, Rn) \
+ _ITM_MCPY_Wt(FN, Rt) \
+ _ITM_MCPY_Wt(FN, RtaR) \
+ _ITM_MCPY_Wt(FN, RtaW) \
+ _ITM_MCPY_RW(FN, Rt, Wn) \
+ _ITM_MCPY_RW(FN, RtaR, Wn) \
+ _ITM_MCPY_RW(FN, RtaW, Wn)
+
+_ITM_MCPY(memcpy)
+_ITM_MCPY(memmove)
+
+#undef _ITM_MCPY_RW
+
+#define _ITM_MSET_W(FN, W) \
+ extern void _ITM_##FN##W (void * target, int src, size_t count) REGPARM;
+#define _ITM_MSET(FN) \
+ _ITM_MSET_W(FN, W) _ITM_MSET_W(FN, WaR) _ITM_MSET_W(FN, WaW)
+
+_ITM_MSET (memset)
+
+#undef _ITM_MSET_W
+
+extern void _ITM_LB (const void *, size_t) REGPARM;
+
+extern void _ITM_addUserCommitAction(_ITM_userCommitFunction,
+ _ITM_transactionId_t, void *) REGPARM;
+
+extern void _ITM_addUserUndoAction(_ITM_userUndoFunction, void *) REGPARM;
+
+extern int _ITM_getThreadnum(void) REGPARM;
+
+extern void _ITM_dropReferences (const void *, size_t) REGPARM;
+
+/* The following are internal implementation functions and definitions.
+ To distinguish them from those defined by the Intel ABI, they all
+ begin with GTM/gtm. */
+
+#ifdef HAVE_ATTRIBUTE_VISIBILITY
+# pragma GCC visibility push(hidden)
+#endif
+
+#include "rwlock.h"
+
+
+/* ??? We're talking about storing some of this data in glibc tls slots
+ begining at 10, and making this part of the ABI on Linux. Think about
+ how to declare such things. */
+
+struct gtm_dispatch
+{
+#define _ITM_READ(R, T) \
+ _ITM_TYPE_##T (*R##T)(const _ITM_TYPE_##T *) REGPARM;
+#define _ITM_WRITE(W, T) \
+ void (*W##T)(_ITM_TYPE_##T *, _ITM_TYPE_##T) REGPARM;
+ _ITM_ALL_TYPES (_ITM_ALL_READS)
+ _ITM_ALL_TYPES (_ITM_ALL_WRITES)
+#undef _ITM_READ
+#undef _ITM_WRITE
+
+#define _ITM_MCPY_RW(FN, R, W) \
+ void (* FN##R##W)(void *, const void *, size_t) REGPARM;
+ _ITM_MCPY(memcpy)
+ _ITM_MCPY(memmove)
+#undef _ITM_MCPY_RW
+
+#define _ITM_MSET_W(FN, W) \
+ void (*FN##W) (void *, int, size_t) REGPARM;
+ _ITM_MSET(memset)
+#undef _ITM_MSET_W
+
+ bool (*trycommit) (void);
+ void (*rollback) (void);
+};
+
+struct gtm_local_undo
+{
+ void *addr;
+ size_t len;
+ char saved[];
+};
+
+struct gtm_user_action
+{
+ struct gtm_user_action *next;
+ _ITM_userCommitFunction fn;
+ void *arg;
+};
+
+#define STATE_READONLY 0x0001
+#define STATE_SERIAL 0x0002
+#define STATE_IRREVOKABLE 0x0004
+#define STATE_ABORTING 0x0008
+
+struct gtm_transaction
+{
+ uint32_t prop;
+ uint32_t nesting;
+ uint32_t state;
+ uint32_t id;
+
+ struct gtm_jmpbuf jb;
+
+ struct gtm_local_undo **local_undo;
+ size_t n_local_undo;
+ size_t size_local_undo;
+
+ struct gtm_user_action *commit_actions;
+ struct gtm_user_action *undo_actions;
+
+ struct gtm_transaction *prev;
+};
+
+#define MAX_FREE_TX 8
+
+struct gtm_thread
+{
+ struct gtm_transaction *tx;
+ const struct gtm_dispatch *disp;
+
+ struct gtm_transaction *free_tx[MAX_FREE_TX];
+ unsigned free_tx_idx, free_tx_count;
+
+ int thread_num;
+};
+
+extern __thread struct gtm_thread gtm_thr;
+
+extern gtm_rwlock gtm_serial_lock;
+extern unsigned long long gtm_spin_count_var;
+
+extern uint32_t GTM_begin_transaction(uint32_t, const struct gtm_jmpbuf *)
+ REGPARM;
+
+extern uint32_t GTM_longjmp (const struct gtm_jmpbuf *, uint32_t)
+ REGPARM NORETURN;
+
+extern void GTM_commit_local (void);
+extern void GTM_rollback_local (void);
+
+extern void GTM_serialmode (bool) REGPARM;
+extern void GTM_decide_retry_strategy (void);
+
+extern void GTM_run_actions (struct gtm_user_action **) REGPARM;
+extern void GTM_free_actions (struct gtm_user_action **) REGPARM;
+
+#ifdef HAVE_ATTRIBUTE_VISIBILITY
+# pragma GCC visibility pop
+#endif
+
+#endif /* LIBITM_H */
--- libitm/libitm.map (revision 141843)
+++ libitm/libitm.map (local)
@@ -0,0 +1,162 @@
+LIBITM_1.0 {
+ global:
+ _ITM_abortTransaction;
+ _ITM_addUserCommitAction;
+ _ITM_addUserUndoAction;
+ _ITM_beginTransaction;
+ _ITM_changeTransactionMode;
+ _ITM_commitTransaction;
+ _ITM_error;
+ _ITM_getThreadnum;
+ _ITM_getTransactionId;
+ _ITM_inTransaction;
+ _ITM_libraryVersion;
+ _ITM_rollbackTransaction;
+ _ITM_tryCommitTransaction;
+ _ITM_versionCompatible;
+
+ _ITM_LB;
+ _ITM_LCD;
+ _ITM_LCE;
+ _ITM_LCF;
+ _ITM_LD;
+ _ITM_LE;
+ _ITM_LF;
+ _ITM_LM128;
+ _ITM_LM256;
+ _ITM_LM64;
+ _ITM_LU1;
+ _ITM_LU2;
+ _ITM_LU4;
+ _ITM_LU8;
+
+ _ITM_RCD;
+ _ITM_RCE;
+ _ITM_RCF;
+ _ITM_RD;
+ _ITM_RE;
+ _ITM_RF;
+ _ITM_RM128;
+ _ITM_RM256;
+ _ITM_RM64;
+ _ITM_RU1;
+ _ITM_RU2;
+ _ITM_RU4;
+ _ITM_RU8;
+ _ITM_RaRCD;
+ _ITM_RaRCE;
+ _ITM_RaRCF;
+ _ITM_RaRD;
+ _ITM_RaRE;
+ _ITM_RaRF;
+ _ITM_RaRM128;
+ _ITM_RaRM256;
+ _ITM_RaRM64;
+ _ITM_RaRU1;
+ _ITM_RaRU2;
+ _ITM_RaRU4;
+ _ITM_RaRU8;
+ _ITM_RaWCD;
+ _ITM_RaWCE;
+ _ITM_RaWCF;
+ _ITM_RaWD;
+ _ITM_RaWE;
+ _ITM_RaWF;
+ _ITM_RaWM128;
+ _ITM_RaWM256;
+ _ITM_RaWM64;
+ _ITM_RaWU1;
+ _ITM_RaWU2;
+ _ITM_RaWU4;
+ _ITM_RaWU8;
+ _ITM_RfWCD;
+ _ITM_RfWCE;
+ _ITM_RfWCF;
+ _ITM_RfWD;
+ _ITM_RfWE;
+ _ITM_RfWF;
+ _ITM_RfWM128;
+ _ITM_RfWM256;
+ _ITM_RfWM64;
+ _ITM_RfWU1;
+ _ITM_RfWU2;
+ _ITM_RfWU4;
+ _ITM_RfWU8;
+
+ _ITM_WCD;
+ _ITM_WCE;
+ _ITM_WCF;
+ _ITM_WD;
+ _ITM_WE;
+ _ITM_WF;
+ _ITM_WM128;
+ _ITM_WM256;
+ _ITM_WM64;
+ _ITM_WU1;
+ _ITM_WU2;
+ _ITM_WU4;
+ _ITM_WU8;
+ _ITM_WaRCD;
+ _ITM_WaRCE;
+ _ITM_WaRCF;
+ _ITM_WaRD;
+ _ITM_WaRE;
+ _ITM_WaRF;
+ _ITM_WaRM128;
+ _ITM_WaRM256;
+ _ITM_WaRM64;
+ _ITM_WaRU1;
+ _ITM_WaRU2;
+ _ITM_WaRU4;
+ _ITM_WaRU8;
+ _ITM_WaWCD;
+ _ITM_WaWCE;
+ _ITM_WaWCF;
+ _ITM_WaWD;
+ _ITM_WaWE;
+ _ITM_WaWF;
+ _ITM_WaWM128;
+ _ITM_WaWM256;
+ _ITM_WaWM64;
+ _ITM_WaWU1;
+ _ITM_WaWU2;
+ _ITM_WaWU4;
+ _ITM_WaWU8;
+
+ _ITM_memcpyRnWt;
+ _ITM_memcpyRnWtaR;
+ _ITM_memcpyRnWtaW;
+ _ITM_memcpyRtWn;
+ _ITM_memcpyRtWt;
+ _ITM_memcpyRtWtaR;
+ _ITM_memcpyRtWtaW;
+ _ITM_memcpyRtaRWn;
+ _ITM_memcpyRtaRWt;
+ _ITM_memcpyRtaRWtaR;
+ _ITM_memcpyRtaRWtaW;
+ _ITM_memcpyRtaWWn;
+ _ITM_memcpyRtaWWt;
+ _ITM_memcpyRtaWWtaR;
+ _ITM_memcpyRtaWWtaW;
+ _ITM_memmoveRnWt;
+ _ITM_memmoveRnWtaR;
+ _ITM_memmoveRnWtaW;
+ _ITM_memmoveRtWn;
+ _ITM_memmoveRtWt;
+ _ITM_memmoveRtWtaR;
+ _ITM_memmoveRtWtaW;
+ _ITM_memmoveRtaRWn;
+ _ITM_memmoveRtaRWt;
+ _ITM_memmoveRtaRWtaR;
+ _ITM_memmoveRtaRWtaW;
+ _ITM_memmoveRtaWWn;
+ _ITM_memmoveRtaWWt;
+ _ITM_memmoveRtaWWtaR;
+ _ITM_memmoveRtaWWtaW;
+ _ITM_memsetW;
+ _ITM_memsetWaR;
+ _ITM_memsetWaW;
+
+ local:
+ *;
+};
--- libitm/libitm.spec.in (revision 141843)
+++ libitm/libitm.spec.in (local)
@@ -0,0 +1,3 @@
+# This spec file is read by gcc when linking. It is used to specify the
+# standard libraries we need in order to link with -fgnu-tm
+*link_itm: @link_itm@
--- libitm/local.c (revision 141843)
+++ libitm/local.c (local)
@@ -0,0 +1,114 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#include "libitm.h"
+
+
+void
+GTM_commit_local (void)
+{
+ struct gtm_transaction *tx = gtm_thr.tx;
+ struct gtm_local_undo **local_undo = tx->local_undo;
+ size_t i, n = tx->n_local_undo;
+
+ if (n > 0)
+ {
+ for (i = 0; i < n; ++i)
+ free (local_undo[i]);
+ tx->n_local_undo = 0;
+ }
+ if (local_undo)
+ {
+ free (local_undo);
+ tx->local_undo = NULL;
+ tx->size_local_undo = 0;
+ }
+}
+
+static void
+rollback_local (struct gtm_local_undo *undo)
+{
+ memcpy (undo->addr, undo->saved, undo->len);
+}
+
+void
+GTM_rollback_local (void)
+{
+ struct gtm_transaction *tx = gtm_thr.tx;
+ struct gtm_local_undo **local_undo = tx->local_undo;
+ size_t i, n = tx->n_local_undo;
+
+ if (n > 0)
+ {
+ for (i = n; i-- > 0; )
+ {
+ rollback_local (local_undo[i]);
+ free (local_undo[i]);
+ }
+ tx->n_local_undo = 0;
+ }
+}
+
+static void *
+alloc_local (void *addr, size_t len)
+{
+ struct gtm_transaction *tx = gtm_thr.tx;
+ struct gtm_local_undo *undo;
+
+ undo = malloc (sizeof (struct gtm_local_undo) + len);
+ undo->addr = addr;
+ undo->len = len;
+
+ if (tx->local_undo == NULL)
+ {
+ tx->size_local_undo = 32;
+ tx->local_undo = malloc (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[tx->n_local_undo++] = undo;
+
+ return undo->saved;
+}
+
+#define _ITM_LOG_DEF(T) \
+void REGPARM _ITM_L##T (const _ITM_TYPE_##T *ptr) \
+{ \
+ *(_ITM_TYPE_##T *)alloc_local((void *)ptr, sizeof(_ITM_TYPE_##T)) = *ptr; \
+}
+
+_ITM_ALL_TYPES(_ITM_LOG_DEF)
+
+void REGPARM
+_ITM_LB (const void *ptr, size_t len)
+{
+ memcpy(alloc_local ((void *)ptr, len), ptr, len);
+}
--- libitm/query.c (revision 141843)
+++ libitm/query.c (local)
@@ -0,0 +1,88 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#include "libitm.h"
+
+
+int REGPARM
+_ITM_versionCompatible (int version)
+{
+ return version == _ITM_VERSION_NO;
+}
+
+
+const char * REGPARM
+_ITM_libraryVersion (void)
+{
+ return "GNU libitm " _ITM_VERSION;
+}
+
+
+_ITM_howExecuting REGPARM
+_ITM_inTransaction (void)
+{
+ struct gtm_transaction *tx = gtm_thr.tx;
+ if (tx)
+ {
+ if (tx->state & STATE_IRREVOKABLE)
+ return inIrrevocableTransaction;
+ else
+ return inRetryableTransaction;
+ }
+ return outsideTransaction;
+}
+
+
+_ITM_transactionId_t REGPARM
+_ITM_getTransactionId (void)
+{
+ struct gtm_transaction *tx = gtm_thr.tx;
+ return tx ? tx->id : _ITM_noTransactionId;
+}
+
+
+int REGPARM
+_ITM_getThreadnum (void)
+{
+ static int global_num;
+ int num = gtm_thr.thread_num;
+
+ if (num == 0)
+ {
+ num = __sync_add_and_fetch (&global_num, 1);
+ gtm_thr.thread_num = num;
+ }
+
+ return num;
+}
+
+
+void REGPARM NORETURN
+_ITM_error (const _ITM_srcLocation * loc UNUSED, int errorCode UNUSED)
+{
+ abort ();
+}
--- libitm/retry.c (revision 141843)
+++ libitm/retry.c (local)
@@ -0,0 +1,34 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#include "libitm.h"
+
+
+void
+GTM_decide_retry_strategy (void)
+{
+}
--- libitm/serial.c (revision 141843)
+++ libitm/serial.c (local)
@@ -0,0 +1,115 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#include "libitm.h"
+
+
+#define SERIAL(T) \
+static _ITM_TYPE_##T REGPARM serial_R##T(const _ITM_TYPE_##T *ptr) \
+{ \
+ return *ptr; \
+} \
+static void REGPARM serial_W##T(_ITM_TYPE_##T *ptr, _ITM_TYPE_##T val) \
+{ \
+ *ptr = val; \
+}
+
+_ITM_ALL_TYPES (SERIAL)
+
+#undef SERIAL
+
+static void REGPARM serial_memcpy (void *dst, const void *src, size_t len)
+{
+ memcpy (dst, src, len);
+}
+
+static void REGPARM serial_memmove (void *dst, const void *src, size_t len)
+{
+ memmove (dst, src, len);
+}
+
+static void REGPARM serial_memset (void *dst, int src, size_t len)
+{
+ memset (dst, src, len);
+}
+
+static bool serial_trycommit (void)
+{
+ return true;
+}
+
+static void serial_rollback (void)
+{
+ abort ();
+}
+
+const static struct gtm_dispatch serial_dispatch =
+{
+#define _ITM_READ(R, T) .R##T = serial_R##T,
+#define _ITM_WRITE(W, T) .W##T = serial_W##T,
+ _ITM_ALL_TYPES (_ITM_ALL_READS)
+ _ITM_ALL_TYPES (_ITM_ALL_WRITES)
+#undef _ITM_READ
+#undef _ITM_WRITE
+
+#define _ITM_MCPY_RW(FN, R, W) .FN##R##W = serial_##FN,
+ _ITM_MCPY(memcpy)
+ _ITM_MCPY(memmove)
+#undef _ITM_MCPY_RW
+
+#define _ITM_MSET_W(FN, W) .FN##W = serial_##FN,
+ _ITM_MSET(memset)
+#undef _ITM_MSET_W
+
+ .trycommit = serial_trycommit,
+ .rollback = serial_rollback,
+};
+
+
+void REGPARM
+GTM_serialmode (bool initial)
+{
+ if (gtm_thr.tx->state & STATE_SERIAL)
+ return;
+
+ if (initial)
+ gtm_rwlock_write_lock (>m_serial_lock);
+ else
+ gtm_rwlock_write_upgrade (>m_serial_lock);
+
+ gtm_thr.tx->state = STATE_SERIAL | STATE_IRREVOKABLE;
+ gtm_thr.disp = &serial_dispatch;
+}
+
+
+void REGPARM
+_ITM_changeTransactionMode (_ITM_transactionState state,
+ const _ITM_srcLocation *loc UNUSED)
+{
+ assert (state == modeSerialIrrevocable);
+ GTM_serialmode (false);
+}
=== libitm/testsuite (new directory)
==================================================================
--- libitm/useraction.c (revision 141843)
+++ libitm/useraction.c (local)
@@ -0,0 +1,99 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+ Contributed by Richard Henderson <rth@redhat.com>.
+
+ This file is part of the GNU Transactional Memory Library (libitm).
+
+ Libgomp is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ Libgomp 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 Lesser General Public License for
+ more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with libgomp; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* As a special exception, if you link this library with other files, some
+ of which are compiled with GCC, to produce an executable, this library
+ does not by itself cause the resulting executable to be covered by the
+ GNU General Public License. This exception does not however invalidate
+ any other reasons why the executable file might be covered by the GNU
+ General Public License. */
+
+#include "libitm.h"
+
+
+void REGPARM
+GTM_run_actions (struct gtm_user_action **list)
+{
+ struct gtm_user_action *a = *list;
+
+ if (a == NULL)
+ return;
+ *list = NULL;
+
+ do
+ {
+ struct gtm_user_action *n = a->next;
+ a->fn (a->arg);
+ free (a);
+ a = n;
+ }
+ while (a);
+}
+
+
+void REGPARM
+GTM_free_actions (struct gtm_user_action **list)
+{
+ struct gtm_user_action *a = *list;
+
+ if (a == NULL)
+ return;
+ *list = NULL;
+
+ do
+ {
+ struct gtm_user_action *n = a->next;
+ free (a);
+ a = n;
+ }
+ while (a);
+}
+
+
+void REGPARM
+_ITM_addUserCommitAction(_ITM_userCommitFunction fn,
+ _ITM_transactionId_t tid, void *arg)
+{
+ struct gtm_transaction *tx;
+ struct gtm_user_action *a;
+
+ for (tx = gtm_thr.tx; tx->id != tid; tx = tx->prev)
+ continue;
+
+ a = malloc (sizeof (*a));
+ a->next = tx->commit_actions;
+ a->fn = fn;
+ a->arg = arg;
+ tx->commit_actions = a;
+}
+
+
+void REGPARM
+_ITM_addUserUndoAction(_ITM_userUndoFunction fn, void * arg)
+{
+ struct gtm_transaction *tx = gtm_thr.tx;
+ struct gtm_user_action *a;
+
+ a = malloc (sizeof (*a));
+ a->next = tx->undo_actions;
+ a->fn = fn;
+ a->arg = arg;
+ tx->undo_actions = a;
+}