diff mbox

4/n: trans-mem: runtime

Message ID 4EB2D478.2080208@redhat.com
State New
Headers show

Commit Message

Aldy Hernandez Nov. 3, 2011, 5:50 p.m. UTC
+
+#endif // LIBITM_STMLOCK_H

Comments

Joseph Myers Nov. 3, 2011, 8:19 p.m. UTC | #1
On Thu, 3 Nov 2011, Aldy Hernandez wrote:

> +# 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"

I don't actually see where gfortran is used.  If not used, this should be 
removed.  If it is used, I think you need something at toplevel to ensure 
that the library isn't built if the --enable-languages option disables 
Fortran, and I don't see that in the toplevel changes.
Richard Sandiford Nov. 29, 2011, 2:05 p.m. UTC | #2
Way behind, sorry, and probably irrelevant anyway, but:

Aldy Hernandez <aldyh@redhat.com> writes:
> +#define ITM_BARRIERS(T) \
> +  extern _ITM_TYPE_##T _ITM_R##T(const _ITM_TYPE_##T *) ITM_REGPARM;	\
> +  extern _ITM_TYPE_##T _ITM_RaR##T(const _ITM_TYPE_##T *) ITM_REGPARM;	\
> +  extern _ITM_TYPE_##T _ITM_RaW##T(const _ITM_TYPE_##T *) ITM_REGPARM;	\
> +  extern _ITM_TYPE_##T _ITM_RfW##T(const _ITM_TYPE_##T *) ITM_REGPARM;	\
> +  extern void _ITM_W##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM;	\
> +  extern void _ITM_WaR##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM;	\
> +  extern void _ITM_WaW##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM;
> +
> +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)
> +
> +#define ITM_LOG(T) \
> +  extern void _ITM_L##T (const _ITM_TYPE_##T *) ITM_REGPARM;
> +
> +ITM_LOG(U1)
> +ITM_LOG(U2)
> +ITM_LOG(U4)
> +ITM_LOG(U8)
> +ITM_LOG(F)
> +ITM_LOG(D)
> +ITM_LOG(E)
> +ITM_LOG(CF)
> +ITM_LOG(CD)
> +ITM_LOG(CE)
> +
> +#if defined(__i386__) || defined(__x86_64__)
> +# ifdef __MMX__
> +  typedef int _ITM_TYPE_M64 __attribute__((vector_size(8), may_alias));
> +  ITM_BARRIERS(M64)
> +  ITM_LOG(M64)
> +# endif
> +# ifdef __SSE__
> +  typedef float _ITM_TYPE_M128 __attribute__((vector_size(16), may_alias));
> +  ITM_BARRIERS(M128)
> +  ITM_LOG(M128)
> +# endif
> +# ifdef __AVX__
> +  typedef float _ITM_TYPE_M256 __attribute__((vector_size(32), may_alias));
> +  ITM_BARRIERS(M256)
> +  ITM_LOG(M256)
> +# endif
> +#endif /* i386 */
> +
> +#undef ITM_BARRIERS
> +#undef ITM_LOG

...should these kind of temporary macros have a name outside the
user's namespace?  _ITM or _GCC_ITM, or whatever?

Richard
diff mbox

Patch

Index: libitm/util.cc
===================================================================
--- libitm/util.cc	(.../trunk)	(revision 0)
+++ libitm/util.cc	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,85 @@ 
+/* 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, bool separate_cl)
+{
+  // TODO Use posix_memalign if separate_cl is true, or some other 
allocation
+  // method that will avoid sharing cache lines with data used by other
+  // threads.
+  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, bool separate_cl)
+{
+  // TODO Use posix_memalign if separate_cl is true, or some other 
allocation
+  // method that will avoid sharing cache lines with data used by other
+  // threads.
+  void *r = realloc (old, size);
+  if (r == 0)
+    GTM_fatal ("Out of memory allocating %lu bytes", (unsigned long) size);
+  return r;
+}
+
+} // namespace GTM
Index: libitm/configure.ac
===================================================================
--- libitm/configure.ac	(.../trunk)	(revision 0)
+++ libitm/configure.ac	(.../branches/transactional-memory)	(revision 
180773)
@@ -0,0 +1,262 @@ 
+# Process this file with autoreconf to produce a configure script.
+
+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
+AC_PROG_CXX
+AM_PROG_AS
+m4_rename_force([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"
+
+# Find other programs we need.
+AC_CHECK_TOOL(AR, ar)
+AC_CHECK_TOOL(NM, nm)
+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/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.
+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(strtoull memalign posix_memalign)
+
+# 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
+
+# Determine the proper ABI type for size_t.
+LIBITM_CHECK_SIZE_T_MANGLING
+
+# 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
+LIBITM_CHECK_64BIT_SYNC_BUILTINS
+
+# Cleanup and exit.
+CFLAGS="$save_CFLAGS"
+AC_CACHE_SAVE
+
+# Add -Wall -Werror if we are using GCC.
+if test "x$GCC" = "xyes"; then
+  XCFLAGS="$XCFLAGS -Wall -Werror"
+fi
+
+XCFLAGS="$XCFLAGS $XPCFLAGS"
+
+AC_SUBST(config_path)
+AC_SUBST(XCFLAGS)
+AC_SUBST(XLDFLAGS)
+
+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)
+
+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
Index: libitm/libitm.h
===================================================================
--- libitm/libitm.h	(.../trunk)	(revision 0)
+++ libitm/libitm.h	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,288 @@ 
+/* 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/>.  */
+
+/* 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 <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __i386__
+/* Only for 32-bit x86.  */
+# define ITM_REGPARM	__attribute__((regparm(2)))
+#else
+# define ITM_REGPARM
+#endif
+
+#define ITM_NORETURN	__attribute__((noreturn))
+#define ITM_PURE __attribute__((transaction_pure))
+
+/* The following are externally visible definitions and functions, though
+   only very few of these should be called by user code.  */
+
+/* Values used as arguments to abort. */
+typedef enum {
+    userAbort = 1,
+    userRetry = 2,
+    TMConflict= 4,
+    exceptionBlockAbort = 8,
+    outerAbort = 16
+} _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 beginTransaction */
+typedef enum
+{
+   pr_instrumentedCode		= 0x0001,
+   pr_uninstrumentedCode	= 0x0002,
+   pr_multiwayCode		= pr_instrumentedCode | pr_uninstrumentedCode,
+   /* Called pr_hasNoXMMUpdate in the Intel document, used for
+      avoiding vector register save/restore for any target.  */
+   pr_hasNoVectorUpdate		= 0x0004,
+   pr_hasNoAbort		= 0x0008,
+   /* Not present in the Intel document, used for avoiding
+      floating point register save/restore for any target.  */
+   pr_hasNoFloatUpdate		= 0x0010,
+   pr_hasNoIrrevocable		= 0x0020,
+   pr_doesGoIrrevocable		= 0x0040,
+   pr_aWBarriersOmitted		= 0x0100,
+   pr_RaRBarriersOmitted	= 0x0200,
+   pr_undoLogCode		= 0x0400,
+   pr_preferUninstrumented	= 0x0800,
+   /* Exception blocks are not used nor supported. */
+   pr_exceptionBlock		= 0x1000,
+   pr_hasElse			= 0x2000,
+   pr_readOnly			= 0x4000,
+   pr_hasNoSimpleReads		= 0x400000
+} _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) ITM_REGPARM;
+extern const char * _ITM_libraryVersion (void) ITM_REGPARM;
+
+void _ITM_error(const _ITM_srcLocation *, int errorCode)
+  ITM_REGPARM ITM_NORETURN;
+
+extern _ITM_howExecuting _ITM_inTransaction(void) ITM_REGPARM;
+
+typedef uint64_t _ITM_transactionId_t;	/* Transaction identifier */
+#define _ITM_noTransactionId 1		/* Id for non-transactional code. */
+
+extern _ITM_transactionId_t _ITM_getTransactionId(void) ITM_REGPARM;
+
+extern uint32_t _ITM_beginTransaction(uint32_t, ...) ITM_REGPARM;
+
+extern void _ITM_abortTransaction(_ITM_abortReason) ITM_REGPARM 
ITM_NORETURN;
+
+extern void _ITM_commitTransaction (void) ITM_REGPARM;
+
+extern void _ITM_changeTransactionMode (_ITM_transactionState) ITM_REGPARM;
+
+extern void _ITM_addUserCommitAction(_ITM_userCommitFunction,
+				     _ITM_transactionId_t, void *) ITM_REGPARM;
+
+extern void _ITM_addUserUndoAction(_ITM_userUndoFunction, void *) 
ITM_REGPARM;
+
+extern int _ITM_getThreadnum(void) ITM_REGPARM;
+
+extern void _ITM_dropReferences (void *, size_t) ITM_REGPARM ITM_PURE;
+
+extern void *_ITM_malloc (size_t)
+       __attribute__((__malloc__)) ITM_PURE;
+
+extern void *_ITM_calloc (size_t, size_t)
+       __attribute__((__malloc__)) ITM_PURE;
+
+extern  void _ITM_free (void *) ITM_PURE;
+
+
+/* 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;
+
+#define ITM_BARRIERS(T) \
+  extern _ITM_TYPE_##T _ITM_R##T(const _ITM_TYPE_##T *) ITM_REGPARM;	\
+  extern _ITM_TYPE_##T _ITM_RaR##T(const _ITM_TYPE_##T *) ITM_REGPARM;	\
+  extern _ITM_TYPE_##T _ITM_RaW##T(const _ITM_TYPE_##T *) ITM_REGPARM;	\
+  extern _ITM_TYPE_##T _ITM_RfW##T(const _ITM_TYPE_##T *) ITM_REGPARM;	\
+  extern void _ITM_W##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM;	\
+  extern void _ITM_WaR##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM;	\
+  extern void _ITM_WaW##T (_ITM_TYPE_##T *, _ITM_TYPE_##T) ITM_REGPARM;
+
+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)
+
+#define ITM_LOG(T) \
+  extern void _ITM_L##T (const _ITM_TYPE_##T *) ITM_REGPARM;
+
+ITM_LOG(U1)
+ITM_LOG(U2)
+ITM_LOG(U4)
+ITM_LOG(U8)
+ITM_LOG(F)
+ITM_LOG(D)
+ITM_LOG(E)
+ITM_LOG(CF)
+ITM_LOG(CD)
+ITM_LOG(CE)
+
+#if defined(__i386__) || defined(__x86_64__)
+# ifdef __MMX__
+  typedef int _ITM_TYPE_M64 __attribute__((vector_size(8), may_alias));
+  ITM_BARRIERS(M64)
+  ITM_LOG(M64)
+# endif
+# ifdef __SSE__
+  typedef float _ITM_TYPE_M128 __attribute__((vector_size(16), may_alias));
+  ITM_BARRIERS(M128)
+  ITM_LOG(M128)
+# endif
+# ifdef __AVX__
+  typedef float _ITM_TYPE_M256 __attribute__((vector_size(32), may_alias));
+  ITM_BARRIERS(M256)
+  ITM_LOG(M256)
+# endif
+#endif /* i386 */
+
+#undef ITM_BARRIERS
+#undef ITM_LOG
+
+extern void _ITM_LB (const void *, size_t) ITM_REGPARM;
+
+extern void _ITM_memcpyRnWt(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRnWtaR(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRnWtaW(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtWn(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtWt(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtWtaR(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtWtaW(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtaRWn(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtaRWt(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtaRWtaR(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtaRWtaW(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtaWWn(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtaWWt(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtaWWtaR(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memcpyRtaWWtaW(void *, const void *, size_t) ITM_REGPARM;
+
+extern void _ITM_memmoveRnWt(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRnWtaR(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRnWtaW(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtWn(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtWt(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtWtaR(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtWtaW(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtaRWn(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtaRWt(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtaRWtaR(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtaRWtaW(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtaWWn(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtaWWt(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtaWWtaR(void *, const void *, size_t) ITM_REGPARM;
+extern void _ITM_memmoveRtaWWtaW(void *, const void *, size_t) ITM_REGPARM;
+
+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_getTMCloneOrIrrevocable (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 */
Index: libitm/barrier.cc
===================================================================
--- libitm/barrier.cc	(.../trunk)	(revision 0)
+++ libitm/barrier.cc	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,44 @@ 
+/* Copyright (C) 2008, 2009, 2011 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"
+
+using namespace GTM;
+
+bool abi_dispatch::memmove_overlap_check(void *dst, const void *src,
+    size_t size, ls_modifier dst_mod, ls_modifier src_mod)
+{
+  if (dst_mod == NONTXNAL || src_mod == NONTXNAL)
+    {
+      if (((uintptr_t)dst <= (uintptr_t)src ?
+          (uintptr_t)dst + size > (uintptr_t)src :
+          (uintptr_t)src + size > (uintptr_t)dst))
+        GTM::GTM_fatal("_ITM_memmove overlapping and t/nt is not allowed");
+      return false;
+    }
+  return true;
+}
+
+CREATE_DISPATCH_FUNCTIONS(GTM::abi_disp()->, )
+
Index: libitm/alloc.cc
===================================================================
--- libitm/alloc.cc	(.../trunk)	(revision 0)
+++ libitm/alloc.cc	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,129 @@ 
+/* Copyright (C) 2009, 2011 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 {
+
+void
+gtm_thread::record_allocation (void *ptr, void (*free_fn)(void *))
+{
+  uintptr_t iptr = (uintptr_t) ptr;
+
+  gtm_alloc_action *a = this->alloc_actions.find(iptr);
+  if (a == 0)
+    a = this->alloc_actions.insert(iptr);
+
+  a->free_fn = free_fn;
+  a->allocated = true;
+}
+
+void
+gtm_thread::forget_allocation (void *ptr, void (*free_fn)(void *))
+{
+  uintptr_t iptr = (uintptr_t) ptr;
+
+  gtm_alloc_action *a = this->alloc_actions.find(iptr);
+  if (a == 0)
+    a = this->alloc_actions.insert(iptr);
+
+  a->free_fn = free_fn;
+  a->allocated = false;
+}
+
+namespace {
+struct commit_cb_data {
+  aa_tree<uintptr_t, gtm_alloc_action>* parent;
+  bool revert_p;
+};
+}
+
+static void
+commit_allocations_2 (uintptr_t key, gtm_alloc_action *a, void *data)
+{
+  void *ptr = (void *)key;
+  commit_cb_data *cb_data = static_cast<commit_cb_data *>(data);
+
+  if (cb_data->revert_p)
+    {
+      // Roll back nested allocations.
+      if (a->allocated)
+        a->free_fn (ptr);
+    }
+  else
+    {
+      if (a->allocated)
+        {
+          // Add nested allocations to parent transaction.
+          gtm_alloc_action* a_parent = cb_data->parent->insert(key);
+          *a_parent = *a;
+        }
+      else
+        {
+          // ??? We could eliminate a parent allocation that matches this
+          // memory release, if we had support for removing all accesses
+          // to this allocation from the transaction's undo and redo logs
+          // (otherwise, the parent transaction's undo or redo might 
write to
+          // data that is already shared again because of calling free()).
+          // We don't have this support currently, and the benefit of this
+          // optimization is unknown, so just add it to the parent.
+          gtm_alloc_action* a_parent;
+          a_parent = cb_data->parent->insert(key);
+          *a_parent = *a;
+        }
+    }
+}
+
+static void
+commit_allocations_1 (uintptr_t key, gtm_alloc_action *a, void *cb_data)
+{
+  void *ptr = (void *)key;
+  uintptr_t revert_p = (uintptr_t) cb_data;
+
+  if (a->allocated == revert_p)
+    a->free_fn (ptr);
+}
+
+/* Permanently commit allocated memory during transaction.
+
+   REVERT_P is true if instead of committing the allocations, we want
+   to roll them back (and vice versa).  */
+void
+gtm_thread::commit_allocations (bool revert_p,
+    aa_tree<uintptr_t, gtm_alloc_action>* parent)
+{
+  if (parent)
+    {
+      commit_cb_data cb_data;
+      cb_data.parent = parent;
+      cb_data.revert_p = revert_p;
+      this->alloc_actions.traverse (commit_allocations_2, &cb_data);
+    }
+  else
+    this->alloc_actions.traverse (commit_allocations_1,
+				  (void *)(uintptr_t)revert_p);
+  this->alloc_actions.clear ();
+}
+
+} // namespace GTM
Index: libitm/configure.tgt
===================================================================
--- libitm/configure.tgt	(.../trunk)	(revision 0)
+++ libitm/configure.tgt	(.../branches/transactional-memory)	(revision 
180773)
@@ -0,0 +1,115 @@ 
+# -*- shell-script -*-
+# 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
+
+    # For x86, we use slots in the TCB head for most of our TLS.
+    # The setup of those slots in beginTransaction can afford to
+    # use the global-dynamic model.
+    i[456]86-*-linux* | x86_64-*-linux*)
+	;;
+
+    *-*-linux*)
+	XCFLAGS="${XCFLAGS} -ftls-model=initial-exec"
+	;;
+  esac
+fi
+
+# Map the target cpu to an ARCH sub-directory.  At the same time,
+# work out any special compilation flags as necessary.
+case "${target_cpu}" in
+  alpha*)	ARCH=alpha ;;
+  ia64*)	ARCH=ia64 ;;
+  mips*)	ARCH=mips ;;
+  powerpc*)	ARCH=powerpc ;;
+  s390*)	ARCH=s390 ;;
+
+  i[456]86)
+	case " ${CC} ${CFLAGS} " in
+	  *" -m64 "*)
+	    ;;
+	  *)
+	    if test -z "$with_arch"; then
+	      XCFLAGS="${XCFLAGS} -march=i486 -mtune=${target_cpu}"
+	      XCFLAGS="${XCFLAGS} -fomit-frame-pointer"
+	    fi
+	esac
+	ARCH=x86
+	;;
+
+  x86_64)
+	case " ${CC} ${CFLAGS} " in
+	  *" -m32 "*)
+	    XCFLAGS="${XCFLAGS} -march=i486 -mtune=i686"
+	    XCFLAGS="${XCFLAGS} -fomit-frame-pointer"
+	    ;;
+	esac
+	ARCH=x86
+	;;
+
+  sparcv9 | sparc64)
+	# Note that sparcv7 and sparcv8 is not included here.  We need cas.
+	echo "int i;" > conftestx.c
+	if ${CC} ${CFLAGS} -c -o conftestx.o conftestx.c > /dev/null 2>&1; then
+	  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
+	ARCH=sparc
+	;;
+
+  *)
+	ARCH="${target_cpu}"
+	;;
+esac
+
+# Since we require POSIX threads, assume a POSIX system by default.
+config_path="$ARCH posix generic"
+
+# Other system configury
+case "${target}" in
+  *-*-linux*)
+	if test $enable_linux_futex = yes; then
+	  config_path="linux/$ARCH linux $config_path"
+	fi
+	;;
+
+  *-*-hpux11*)
+	# HPUX v11.x requires -lrt to resolve sem_init in libgomp.la
+	XLDFLAGS="${XLDFLAGS} -lrt"
+	;;
+
+  *-*-mingw32*)
+	config_path="$ARCH mingw32 posix generic"
+	;;
+
+  *-*-solaris2.[56]*)
+	config_path="$ARCH posix95 posix generic"
+	XLDFLAGS="${XLDFLAGS} -lposix4"
+	;;
+
+  *-*-darwin*)
+	config_path="$ARCH bsd posix generic"
+	;;
+esac
Index: libitm/libitm.spec.in
===================================================================
--- libitm/libitm.spec.in	(.../trunk)	(revision 0)
+++ libitm/libitm.spec.in	(.../branches/transactional-memory)	(revision 
180773)
@@ -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@
Index: libitm/memset.cc
===================================================================
--- libitm/memset.cc	(.../trunk)	(revision 0)
+++ libitm/memset.cc	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,78 @@ 
+/* 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"
+
+using namespace GTM;
+
+static void
+do_memset(uintptr_t idst, int c, size_t size, abi_dispatch::lock_type W)
+{
+  abi_dispatch *disp = abi_disp();
+  uintptr_t dofs = idst & (CACHELINE_SIZE - 1);
+  abi_dispatch::mask_pair dpair;
+  gtm_cacheline *dst
+    = reinterpret_cast<gtm_cacheline *>(idst & -CACHELINE_SIZE);
+
+  if (size == 0)
+    return;
+
+  if (dofs != 0)
+    {
+      size_t dleft = CACHELINE_SIZE - dofs;
+      size_t min = (size <= dleft ? size : dleft);
+
+      dpair = disp->write_lock(dst, W);
+      *dpair.mask |= (((gtm_cacheline_mask)1 << min) - 1) << dofs;
+      memset (&dpair.line->b[dofs], c, min);
+      dst++;
+      size -= min;
+    }
+
+  while (size >= CACHELINE_SIZE)
+    {
+      dpair = disp->write_lock(dst, W);
+      *dpair.mask = -1;
+      memset (dpair.line, c, CACHELINE_SIZE);
+      dst++;
+      size -= CACHELINE_SIZE;
+    }
+
+  if (size != 0)
+    {
+      dpair = disp->write_lock(dst, W);
+      *dpair.mask |= ((gtm_cacheline_mask)1 << size) - 1;
+      memset (dpair.line, c, size);
+    }
+}
+
+#define ITM_MEM_DEF(WRITE) \
+void ITM_REGPARM _ITM_memset##WRITE(void *dst, int c, size_t size)	\
+{									\
+  do_memset ((uintptr_t)dst, c, size, abi_dispatch::WRITE);		\
+}
+
+ITM_MEM_DEF(W)
+ITM_MEM_DEF(WaR)
+ITM_MEM_DEF(WaW)
Index: libitm/alloc_cpp.cc
===================================================================
--- libitm/alloc_cpp.cc	(.../trunk)	(revision 0)
+++ libitm/alloc_cpp.cc	(.../branches/transactional-memory)	(revision 
180773)
@@ -0,0 +1,152 @@ 
+/* Copyright (C) 2009, 2011 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"
+
+using namespace GTM;
+
+/* Mangling the names by hand requires that we know how size_t is handled.
+   We've gotten the letter from autoconf, now substitute it into the names.
+   Everything below uses X as a placeholder for clarity.  */
+
+#define S1(x,y)			x##y
+#define S(x,y)			S1(x,y)
+
+#define _ZnwX			S(_Znw,MANGLE_SIZE_T)
+#define _ZnaX			S(_Zna,MANGLE_SIZE_T)
+#define _ZnwXRKSt9nothrow_t	S(S(_Znw,MANGLE_SIZE_T),RKSt9nothrow_t)
+#define _ZnaXRKSt9nothrow_t	S(S(_Zna,MANGLE_SIZE_T),RKSt9nothrow_t)
+
+#define _ZGTtnwX		S(_ZGTtnw,MANGLE_SIZE_T)
+#define _ZGTtnaX		S(_ZGTtna,MANGLE_SIZE_T)
+#define _ZGTtnwXRKSt9nothrow_t	S(S(_ZGTtnw,MANGLE_SIZE_T),RKSt9nothrow_t)
+#define _ZGTtnaXRKSt9nothrow_t	S(S(_ZGTtna,MANGLE_SIZE_T),RKSt9nothrow_t)
+
+/* Everything from libstdc++ is weak, to avoid requiring that library
+   to be linked into plain C applications using libitm.so.  */
+
+extern "C" {
+
+extern void *_ZnwX (size_t) __attribute__((weak));
+extern void _ZdlPv (void *) __attribute__((weak));
+extern void *_ZnaX (size_t) __attribute__((weak));
+extern void _ZdaPv (void *) __attribute__((weak));
+
+typedef const struct nothrow_t { } *c_nothrow_p;
+
+extern void *_ZnwXRKSt9nothrow_t (size_t, c_nothrow_p) 
__attribute__((weak));
+extern void _ZdlPvRKSt9nothrow_t (void *, c_nothrow_p) 
__attribute__((weak));
+extern void *_ZnaXRKSt9nothrow_t (size_t, c_nothrow_p) 
__attribute__((weak));
+extern void _ZdaPvRKSt9nothrow_t (void *, c_nothrow_p) 
__attribute__((weak));
+
+/* Wrap the delete nothrow symbols for usage with a single argument.
+   Perhaps should have a configure type check for this, because the
+   std::nothrow_t reference argument is unused (empty class), and most
+   targets don't actually need that second argument.  So we _could_
+   invoke these functions as if they were a single argument free.  */
+static void
+del_opnt (void *ptr)
+{
+  _ZdlPvRKSt9nothrow_t (ptr, NULL);
+}
+
+static void
+del_opvnt (void *ptr)
+{
+  _ZdaPvRKSt9nothrow_t (ptr, NULL);
+}
+
+/* Wrap: operator new (std::size_t sz)  */
+void *
+_ZGTtnwX (size_t sz)
+{
+  void *r = _ZnwX (sz);
+  if (r)
+    gtm_thr()->record_allocation (r, _ZdlPv);
+  return r;
+}
+
+/* Wrap: operator new (std::size_t sz, const std::nothrow_t&)  */
+void *
+_ZGTtnwXRKSt9nothrow_t (size_t sz, c_nothrow_p nt)
+{
+  void *r = _ZnwXRKSt9nothrow_t (sz, nt);
+  if (r)
+    gtm_thr()->record_allocation (r, del_opnt);
+  return r;
+}
+
+/* Wrap: operator new[] (std::size_t sz)  */
+void *
+_ZGTtnaX (size_t sz)
+{
+  void *r = _ZnaX (sz);
+  if (r)
+    gtm_thr()->record_allocation (r, _ZdaPv);
+  return r;
+}
+
+/* Wrap: operator new[] (std::size_t sz, const std::nothrow_t& nothrow)  */
+void *
+_ZGTtnaXRKSt9nothrow_t (size_t sz, c_nothrow_p nt)
+{
+  void *r = _ZnaXRKSt9nothrow_t (sz, nt);
+  if (r)
+    gtm_thr()->record_allocation (r, del_opvnt);
+  return r;
+}
+
+/* Wrap: operator delete(void* ptr)  */
+void
+_ZGTtdlPv (void *ptr)
+{
+  if (ptr)
+    gtm_thr()->forget_allocation (ptr, _ZdlPv);
+}
+
+/* Wrap: operator delete (void *ptr, const std::nothrow_t&)  */
+void
+_ZGTtdlPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt UNUSED)
+{
+  if (ptr)
+    gtm_thr()->forget_allocation (ptr, del_opnt);
+}
+
+/* Wrap: operator delete[] (void *ptr)  */
+void
+_ZGTtdaPv (void *ptr)
+{
+  if (ptr)
+    gtm_thr()->forget_allocation (ptr, _ZdaPv);
+}
+
+/* Wrap: operator delete[] (void *ptr, const std::nothrow_t&)  */
+void
+_ZGTtdaPvRKSt9nothrow_t (void *ptr, c_nothrow_p nt UNUSED)
+{
+  if (ptr)
+    gtm_thr()->forget_allocation (ptr, del_opvnt);
+}
+
+} // extern "C"
Index: libitm/method-serial.cc
===================================================================
--- libitm/method-serial.cc	(.../trunk)	(revision 0)
+++ libitm/method-serial.cc	(.../branches/transactional-memory) 
(revision 180773)
@@ -0,0 +1,285 @@ 
+/* Copyright (C) 2008, 2009, 2011 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"
+
+// Avoid a dependency on libstdc++ for the pure virtuals in abi_dispatch.
+extern "C" void HIDDEN
+__cxa_pure_virtual ()
+{
+  abort ();
+}
+
+using namespace GTM;
+
+namespace {
+
+// This group consists of the serial, serialirr, and serialirr_onwrite
+// methods, which all need no global state (except what is already provided
+// by the serial mode implementation).
+struct serial_mg : public method_group
+{
+  virtual void init() { }
+  virtual void fini() { }
+};
+
+static serial_mg o_serial_mg;
+
+
+class serialirr_dispatch : public abi_dispatch
+{
+ public:
+  serialirr_dispatch() : abi_dispatch(false, true, true, false, 
&o_serial_mg)
+  { }
+
+ protected:
+  serialirr_dispatch(bool ro, bool wt, bool uninstrumented,
+      bool closed_nesting, method_group* mg) :
+    abi_dispatch(ro, wt, uninstrumented, closed_nesting, mg) { }
+
+  // Transactional loads and stores simply access memory directly.
+  // These methods are static to avoid indirect calls, and will be used 
by the
+  // virtual ABI dispatch methods or by static direct-access methods 
created
+  // below.
+  template <typename V> static V load(const V* addr, ls_modifier mod)
+  {
+    return *addr;
+  }
+  template <typename V> static void store(V* addr, const V value,
+      ls_modifier mod)
+  {
+    *addr = value;
+  }
+
+ public:
+  static void memtransfer_static(void *dst, const void* src, size_t size,
+      bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
+  {
+    if (!may_overlap)
+      ::memcpy(dst, src, size);
+    else
+      ::memmove(dst, src, size);
+  }
+
+  static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
+  {
+    ::memset(dst, c, size);
+  }
+
+  CREATE_DISPATCH_METHODS(virtual, )
+  CREATE_DISPATCH_METHODS_MEM()
+
+  virtual gtm_restart_reason begin_or_restart() { return NO_RESTART; }
+  virtual bool trycommit(gtm_word& priv_time) { return true; }
+  virtual void rollback(gtm_transaction_cp *cp) { abort(); }
+
+  virtual abi_dispatch* closed_nesting_alternative()
+  {
+    // For nested transactions with an instrumented code path, we can do
+    // undo logging.
+    return GTM::dispatch_serial();
+  }
+};
+
+class serial_dispatch : public abi_dispatch
+{
+protected:
+  static void log(const void *addr, size_t len)
+  {
+    // TODO Ensure that this gets inlined: Use internal log interface 
and LTO.
+    GTM_LB(addr, len);
+  }
+
+  template <typename V> static V load(const V* addr, ls_modifier mod)
+  {
+    return *addr;
+  }
+  template <typename V> static void store(V* addr, const V value,
+      ls_modifier mod)
+  {
+    if (mod != WaW)
+      log(addr, sizeof(V));
+    *addr = value;
+  }
+
+public:
+  static void memtransfer_static(void *dst, const void* src, size_t size,
+      bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
+  {
+    if (dst_mod != WaW && dst_mod != NONTXNAL)
+      log(dst, size);
+    if (!may_overlap)
+      ::memcpy(dst, src, size);
+    else
+      ::memmove(dst, src, size);
+  }
+
+  static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
+  {
+    if (mod != WaW)
+      log(dst, size);
+    ::memset(dst, c, size);
+  }
+
+  virtual gtm_restart_reason begin_or_restart() { return NO_RESTART; }
+  virtual bool trycommit(gtm_word& priv_time) { return true; }
+  // Local undo will handle this.
+  // trydropreference() need not be changed either.
+  virtual void rollback(gtm_transaction_cp *cp) { }
+
+  CREATE_DISPATCH_METHODS(virtual, )
+  CREATE_DISPATCH_METHODS_MEM()
+
+  serial_dispatch() : abi_dispatch(false, true, false, true, 
&o_serial_mg) { }
+};
+
+
+// Like serialirr_dispatch but does not requests serial-irrevocable 
mode until
+// the first write in the transaction. Can be useful for read-mostly 
workloads
+// and testing, but is likely too simple to be of general purpose.
+class serialirr_onwrite_dispatch : public serialirr_dispatch
+{
+ public:
+  serialirr_onwrite_dispatch() :
+    serialirr_dispatch(false, true, false, false, &o_serial_mg) { }
+
+ protected:
+  static void pre_write()
+  {
+    gtm_thread *tx = gtm_thr();
+    if (!(tx->state & (gtm_thread::STATE_SERIAL
+        | gtm_thread::STATE_IRREVOCABLE)))
+      tx->serialirr_mode();
+  }
+
+  // Transactional loads access memory directly.
+  // Transactional stores switch to serial mode first.
+  template <typename V> static void store(V* addr, const V value,
+      ls_modifier mod)
+  {
+    pre_write();
+    serialirr_dispatch::store(addr, value, mod);
+  }
+
+ public:
+  static void memtransfer_static(void *dst, const void* src, size_t size,
+      bool may_overlap, ls_modifier dst_mod, ls_modifier src_mod)
+  {
+    pre_write();
+    serialirr_dispatch::memtransfer_static(dst, src, size, may_overlap,
+        dst_mod, src_mod);
+  }
+
+  static void memset_static(void *dst, int c, size_t size, ls_modifier mod)
+  {
+    pre_write();
+    serialirr_dispatch::memset_static(dst, c, size, mod);
+  }
+
+  CREATE_DISPATCH_METHODS(virtual, )
+  CREATE_DISPATCH_METHODS_MEM()
+
+  virtual void rollback(gtm_transaction_cp *cp)
+  {
+    gtm_thread *tx = gtm_thr();
+    if (tx->state & gtm_thread::STATE_IRREVOCABLE)
+      abort();
+  }
+};
+
+} // anon namespace
+
+static const serialirr_dispatch o_serialirr_dispatch;
+static const serial_dispatch o_serial_dispatch;
+static const serialirr_onwrite_dispatch o_serialirr_onwrite_dispatch;
+
+abi_dispatch *
+GTM::dispatch_serialirr ()
+{
+  return const_cast<serialirr_dispatch *>(&o_serialirr_dispatch);
+}
+
+abi_dispatch *
+GTM::dispatch_serial ()
+{
+  return const_cast<serial_dispatch *>(&o_serial_dispatch);
+}
+
+abi_dispatch *
+GTM::dispatch_serialirr_onwrite ()
+{
+  return
+      const_cast<serialirr_onwrite_dispatch 
*>(&o_serialirr_onwrite_dispatch);
+}
+
+// Put the transaction into serial-irrevocable mode.
+
+void
+GTM::gtm_thread::serialirr_mode ()
+{
+  struct abi_dispatch *disp = abi_disp ();
+  bool need_restart = true;
+
+  if (this->state & STATE_SERIAL)
+    {
+      if (this->state & STATE_IRREVOCABLE)
+	return;
+
+      // Try to commit the dispatch-specific part of the transaction, as we
+      // would do for an outermost commit.
+      // We're already serial, so we don't need to ensure privatization 
safety
+      // for other transactions here.
+      gtm_word priv_time = 0;
+      bool ok = disp->trycommit (priv_time);
+      // Given that we're already serial, the trycommit better work.
+      assert (ok);
+      need_restart = false;
+    }
+  else if (serial_lock.write_upgrade (this))
+    {
+      this->state |= STATE_SERIAL;
+      // Try to commit the dispatch-specific part of the transaction, as we
+      // would do for an outermost commit.
+      // We have successfully upgraded to serial mode, so we don't need to
+      // ensure privatization safety for other transactions here.
+      gtm_word priv_time = 0;
+      if (disp->trycommit (priv_time))
+        need_restart = false;
+    }
+
+  if (need_restart)
+    restart (RESTART_SERIAL_IRR);
+  else
+    {
+      this->state |= (STATE_SERIAL | STATE_IRREVOCABLE);
+      set_abi_disp (dispatch_serialirr ());
+    }
+}
+
+void ITM_REGPARM
+_ITM_changeTransactionMode (_ITM_transactionState state)
+{
+  assert (state == modeSerialIrrevocable);
+  gtm_thr()->serialirr_mode ();
+}
Index: libitm/eh_cpp.cc
===================================================================
--- libitm/eh_cpp.cc	(.../trunk)	(revision 0)
+++ libitm/eh_cpp.cc	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,108 @@ 
+/* 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"
+
+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)
+{
+  void *r = __cxa_allocate_exception (size);
+  gtm_thr()->cxa_unthrown = r;
+  return r;
+}
+
+void
+_ITM_cxa_throw (void *obj, void *tinfo, void *dest)
+{
+  gtm_thr()->cxa_unthrown = NULL;
+  __cxa_throw (obj, tinfo, dest);
+}
+
+void *
+_ITM_cxa_begin_catch (void *exc_ptr)
+{
+  gtm_thr()->cxa_catch_count++;
+  return __cxa_begin_catch (exc_ptr);
+}
+
+void
+_ITM_cxa_end_catch (void)
+{
+  gtm_thr()->cxa_catch_count--;
+  __cxa_end_catch ();
+}
+
+void
+GTM::gtm_thread::revert_cpp_exceptions (gtm_transaction_cp *cp)
+{
+  if (cp)
+    {
+      // If rolling back a nested transaction, only clean up unthrown
+      // exceptions since the last checkpoint. Always reset eh_in_flight
+      // because it just contains the argument provided to
+      // _ITM_commitTransactionEH
+      void *unthrown =
+          (cxa_unthrown != cp->cxa_unthrown ? cxa_unthrown : NULL);
+      assert (cxa_catch_count >= cp->cxa_catch_count);
+      uint32_t catch_count = cxa_catch_count - cp->cxa_catch_count;
+      if (unthrown || catch_count)
+        {
+          __cxa_tm_cleanup (unthrown, this->eh_in_flight, catch_count);
+          cxa_catch_count = cp->cxa_catch_count;
+          cxa_unthrown = cp->cxa_unthrown;
+          this->eh_in_flight = NULL;
+        }
+    }
+  else
+    {
+      // Both cxa_catch_count and cxa_unthrown are maximal because EH 
regions
+      // and transactions are properly nested.
+      if (this->cxa_unthrown || this->cxa_catch_count)
+        {
+          __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;
+        }
+    }
+}
Index: libitm/barrier.tpl
===================================================================
--- libitm/barrier.tpl	(.../trunk)	(revision 0)
+++ libitm/barrier.tpl	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,170 @@ 
+/* -*- c++ -*- */
+/* 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, abi_dispatch::lock_type lock)
+{
+  //
+  // Find the cacheline that holds the current value of *PTR.
+  //
+  abi_dispatch *disp = abi_disp();
+  uintptr_t iptr = reinterpret_cast<uintptr_t>(ptr);
+  // Normalize PTR by chopping off the bottom bits so we can search
+  // for PTR in the cacheline hash.
+  uintptr_t iline = iptr & -CACHELINE_SIZE;
+  // The position in the resulting cacheline where *PTR is actually stored.
+  uintptr_t iofs = iptr & (CACHELINE_SIZE - 1);
+  const gtm_cacheline *pline = reinterpret_cast<const gtm_cacheline 
*>(iline);
+  // Search for the actual cacheline that holds the current value of *PTR.
+  const gtm_cacheline *line = disp->read_lock(pline, lock);
+
+  // Point to the position in the cacheline where *PTR is stored.
+  ptr = reinterpret_cast<const T *>(&line->b[iofs]);
+
+  // Straight up loads, because we're either aligned, or we don't care
+  // about alignment.
+  //
+  // If we require alignment on type T, do a straight load if we're
+  // aligned.  Otherwise do a straight load IFF the load fits entirely
+  // in this cacheline.  That is, it won't span multiple cachelines.
+  if (__builtin_expect (strict_alignment<T>::value
+			? (iofs & (sizeof (T) - 1)) == 0
+			: iofs + sizeof(T) <= CACHELINE_SIZE, 1))
+    {
+    do_normal_load:
+      return *ptr;
+    }
+  // If alignment on T is necessary, but we're unaligned, yet we fit
+  // entirely in this cacheline... do the unaligned load dance.
+  else if (__builtin_expect (strict_alignment<T>::value
+			     && iofs + sizeof(T) <= CACHELINE_SIZE, 1))
+    {
+    do_unaligned_load:
+      return unaligned_load<T>(ptr);
+    }
+  // Otherwise, this load will span multiple cachelines.
+  else
+    {
+      // Get the following cacheline for the rest of the data.
+      const gtm_cacheline *line2 = disp->read_lock(pline + 1, lock);
+
+      // If the two cachelines are adjacent, just load it all in one
+      // swoop.
+      if (line2 == line + 1)
+	{
+	  if (!strict_alignment<T>::value)
+	    goto do_normal_load;
+	  else
+	    goto do_unaligned_load;
+	}
+      else
+	{
+	  // Otherwise, ask the backend to load from two different
+	  // cachelines.
+	  return unaligned_load2<T>(line, line2, iofs);
+	}
+    }
+}
+
+template<typename T>
+void do_write (T *ptr, T val, abi_dispatch::lock_type lock)
+{
+  // Note: See comments for do_read() above for hints on this
+  // function.  Ideally we should abstract out a lot out of these two
+  // functions, and avoid all this duplication.
+
+  abi_dispatch *disp = abi_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;
+  abi_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;
+      abi_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, abi_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, abi_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)
Index: libitm/retry.cc
===================================================================
--- libitm/retry.cc	(.../trunk)	(revision 0)
+++ libitm/retry.cc	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,265 @@ 
+/* Copyright (C) 2008, 2009, 2011 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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "libitm_i.h"
+
+// The default TM method used when starting a new transaction.
+static GTM::abi_dispatch* default_dispatch = 0;
+// The default TM method as requested by the user, if any.
+static GTM::abi_dispatch* default_dispatch_user = 0;
+
+void
+GTM::gtm_thread::decide_retry_strategy (gtm_restart_reason r)
+{
+  struct abi_dispatch *disp = abi_disp ();
+
+  this->restart_reason[r]++;
+  this->restart_total++;
+
+  if (r == RESTART_INIT_METHOD_GROUP)
+    {
+      // A re-initializations of the method group has been requested. 
Switch
+      // to serial mode, initialize, and resume normal operation.
+      if ((state & STATE_SERIAL) == 0)
+        {
+          // We have to eventually re-init the method group. Therefore,
+          // we cannot just upgrade to a write lock here because this could
+          // fail forever when other transactions execute in serial mode.
+          // However, giving up the read lock then means that a change 
of the
+          // method group could happen in-between, so check that we're not
+          // re-initializing without a need.
+          // ??? Note that we can still re-initialize too often, but 
avoiding
+          // that would increase code complexity, which seems unnecessary
+          // given that re-inits should be very infrequent.
+          serial_lock.read_unlock(this);
+          serial_lock.write_lock();
+          if (disp->get_method_group() == 
default_dispatch->get_method_group())
+            {
+              // Still the same method group.
+              disp->get_method_group()->fini();
+              disp->get_method_group()->init();
+            }
+          serial_lock.write_unlock();
+          serial_lock.read_lock(this);
+          if (disp->get_method_group() != 
default_dispatch->get_method_group())
+            {
+              disp = default_dispatch;
+              set_abi_disp(disp);
+            }
+        }
+      else
+        {
+          // We are a serial transaction already, which makes things 
simple.
+          disp->get_method_group()->fini();
+          disp->get_method_group()->init();
+        }
+    }
+
+  bool retry_irr = (r == RESTART_SERIAL_IRR);
+  bool retry_serial = (retry_irr || this->restart_total > 100);
+
+  // We assume closed nesting to be infrequently required, so just use
+  // dispatch_serial (with undo logging) if required.
+  if (r == RESTART_CLOSED_NESTING)
+    retry_serial = true;
+
+  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.
+      // Note that we will be restarting with either dispatch_serial or
+      // dispatch_serialirr, which are compatible with all TM methods; if
+      // we would retry with a different method, we would have to first 
check
+      // whether the default dispatch or the method group have changed. 
Also,
+      // the caller must have rolled back the previous transaction, so we
+      // don't have to worry about things such as privatization.
+      if ((this->state & STATE_SERIAL) == 0)
+	{
+	  this->state |= STATE_SERIAL;
+	  serial_lock.read_unlock (this);
+	  serial_lock.write_lock ();
+	}
+
+      // We can retry with dispatch_serialirr if the transaction
+      // doesn't contain an abort and if we don't need closed nesting.
+      if ((this->prop & pr_hasNoAbort) && (r != RESTART_CLOSED_NESTING))
+	retry_irr = true;
+    }
+
+  // Note that we can just use serial mode here without having to switch
+  // TM method sets because serial mode is compatible with all of them.
+  if (retry_irr)
+    {
+      this->state = (STATE_SERIAL | STATE_IRREVOCABLE);
+      disp = dispatch_serialirr ();
+      set_abi_disp (disp);
+    }
+  else if (retry_serial)
+    {
+      disp = dispatch_serial();
+      set_abi_disp (disp);
+    }
+}
+
+
+// Decides which TM method should be used on the first attempt to run this
+// transaction.
+GTM::abi_dispatch*
+GTM::gtm_thread::decide_begin_dispatch (uint32_t prop)
+{
+  // TODO Pay more attention to prop flags (eg, *omitted) when selecting
+  // dispatch.
+  if ((prop & pr_doesGoIrrevocable) || !(prop & pr_instrumentedCode))
+    return dispatch_serialirr();
+
+  // If we might need closed nesting and the default dispatch has an
+  // alternative that supports closed nesting, use it.
+  // ??? We could choose another TM method that we know supports closed
+  // nesting but isn't the default (e.g., dispatch_serial()). However, we
+  // assume that aborts that need closed nesting are infrequent, so don't
+  // choose a non-default method until we have to actually restart the
+  // transaction.
+  if (!(prop & pr_hasNoAbort) && !default_dispatch->closed_nesting()
+      && default_dispatch->closed_nesting_alternative())
+    return default_dispatch->closed_nesting_alternative();
+
+  // No special case, just use the default dispatch.
+  return default_dispatch;
+}
+
+
+void
+GTM::gtm_thread::set_default_dispatch(GTM::abi_dispatch* disp)
+{
+  if (default_dispatch == disp)
+    return;
+  if (default_dispatch)
+    {
+      // If we are switching method groups, initialize and shut down 
properly.
+      if (default_dispatch->get_method_group() != disp->get_method_group())
+        {
+          default_dispatch->get_method_group()->fini();
+          disp->get_method_group()->init();
+        }
+    }
+  else
+    disp->get_method_group()->init();
+  default_dispatch = disp;
+}
+
+
+static GTM::abi_dispatch*
+parse_default_method()
+{
+  const char *env = getenv("ITM_DEFAULT_METHOD");
+  GTM::abi_dispatch* disp = 0;
+  if (env == NULL)
+    return 0;
+
+  while (isspace((unsigned char) *env))
+    ++env;
+  if (strncmp(env, "serialirr_onwrite", 17) == 0)
+    {
+      disp = GTM::dispatch_serialirr_onwrite();
+      env += 17;
+    }
+  else if (strncmp(env, "serialirr", 9) == 0)
+    {
+      disp = GTM::dispatch_serialirr();
+      env += 9;
+    }
+  else if (strncmp(env, "serial", 6) == 0)
+    {
+      disp = GTM::dispatch_serial();
+      env += 6;
+    }
+  else if (strncmp(env, "gl_wt", 5) == 0)
+    {
+      disp = GTM::dispatch_gl_wt();
+      env += 5;
+    }
+  else
+    goto unknown;
+
+  while (isspace((unsigned char) *env))
+    ++env;
+  if (*env == '\0')
+    return disp;
+
+ unknown:
+  GTM::GTM_error("Unknown TM method in environment variable "
+      "ITM_DEFAULT_METHOD\n");
+  return 0;
+}
+
+// Gets notifications when the number of registered threads changes. 
This is
+// used to initialize the method set choice and trigger straightforward 
choice
+// adaption.
+// This must be called only by serial threads.
+void
+GTM::gtm_thread::number_of_threads_changed(unsigned previous, unsigned now)
+{
+  if (previous == 0)
+    {
+      // No registered threads before, so initialize.
+      static bool initialized = false;
+      if (!initialized)
+        {
+          initialized = true;
+          // Check for user preferences here.
+          default_dispatch_user = parse_default_method();
+        }
+    }
+  else if (now == 0)
+    {
+      // No registered threads anymore. The dispatch based on serial 
mode do
+      // not have any global state, so this effectively shuts down 
properly.
+      set_default_dispatch(dispatch_serialirr());
+    }
+
+  if (now == 1)
+    {
+      // Only one thread, so use a serializing method.
+      // ??? If we don't have a fast serial mode implementation, it 
might be
+      // better to use the global lock method set here.
+      if (default_dispatch_user)
+        set_default_dispatch(default_dispatch_user);
+      else
+        set_default_dispatch(dispatch_serialirr());
+    }
+  else if (now > 1 && previous <= 1)
+    {
+      // More than one thread, use the default method.
+      if (default_dispatch_user)
+        set_default_dispatch(default_dispatch_user);
+      else
+        set_default_dispatch(dispatch_serialirr_onwrite());
+    }
+}
Index: libitm/query.cc
===================================================================
--- libitm/query.cc	(.../trunk)	(revision 0)
+++ libitm/query.cc	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,70 @@ 
+/* Copyright (C) 2008, 2009, 2011 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"
+
+using namespace GTM;
+
+int ITM_REGPARM
+_ITM_versionCompatible (int version)
+{
+  return version == _ITM_VERSION_NO;
+}
+
+
+const char * ITM_REGPARM
+_ITM_libraryVersion (void)
+{
+  return "GNU libitm " _ITM_VERSION;
+}
+
+
+_ITM_howExecuting ITM_REGPARM
+_ITM_inTransaction (void)
+{
+  struct gtm_thread *tx = gtm_thr();
+  if (tx && (tx->nesting > 0))
+    {
+      if (tx->state & gtm_thread::STATE_IRREVOCABLE)
+	return inIrrevocableTransaction;
+      else
+	return inRetryableTransaction;
+    }
+  return outsideTransaction;
+}
+
+
+_ITM_transactionId_t ITM_REGPARM
+_ITM_getTransactionId (void)
+{
+  struct gtm_thread *tx = gtm_thr();
+  return (tx && (tx->nesting > 0)) ? tx->id : _ITM_noTransactionId;
+}
+
+
+void ITM_REGPARM ITM_NORETURN
+_ITM_error (const _ITM_srcLocation * loc UNUSED, int errorCode UNUSED)
+{
+  abort ();
+}
Index: libitm/beginend.cc
===================================================================
--- libitm/beginend.cc	(.../trunk)	(revision 0)
+++ libitm/beginend.cc	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,536 @@ 
+/* Copyright (C) 2008, 2009, 2011 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 <pthread.h>
+
+
+using namespace GTM;
+
+#if !defined(HAVE_ARCH_GTM_THREAD) || !defined(HAVE_ARCH_GTM_THREAD_DISP)
+extern __thread gtm_thread_tls _gtm_thr_tls;
+#endif
+
+gtm_rwlock GTM::gtm_thread::serial_lock;
+gtm_thread *GTM::gtm_thread::list_of_threads = 0;
+unsigned GTM::gtm_thread::number_of_threads = 0;
+
+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::gtm_spin_count_var = 1000;
+
+static _ITM_transactionId_t global_tid;
+
+// Provides a on-thread-exit callback used to release per-thread data.
+static pthread_key_t thr_release_key;
+static pthread_once_t thr_release_once = PTHREAD_ONCE_INIT;
+
+
+/* Allocate a transaction structure.  */
+void *
+GTM::gtm_thread::operator new (size_t s)
+{
+  void *tx;
+
+  assert(s == sizeof(gtm_thread));
+
+  tx = xmalloc (sizeof (gtm_thread), true);
+  memset (tx, 0, sizeof (gtm_thread));
+
+  return tx;
+}
+
+/* Free the given transaction. Raises an error if the transaction is still
+   in use.  */
+void
+GTM::gtm_thread::operator delete(void *tx)
+{
+  free(tx);
+}
+
+static void
+thread_exit_handler(void *)
+{
+  gtm_thread *thr = gtm_thr();
+  if (thr)
+    delete thr;
+  set_gtm_thr(0);
+}
+
+static void
+thread_exit_init()
+{
+  if (pthread_key_create(&thr_release_key, thread_exit_handler))
+    GTM_fatal("Creating thread release TLS key failed.");
+}
+
+
+GTM::gtm_thread::~gtm_thread()
+{
+  if (nesting > 0)
+    GTM_fatal("Thread exit while a transaction is still active.");
+
+  // Deregister this transaction.
+  serial_lock.write_lock ();
+  gtm_thread **prev = &list_of_threads;
+  for (; *prev; prev = &(*prev)->next_thread)
+    {
+      if (*prev == this)
+        {
+          *prev = (*prev)->next_thread;
+          break;
+        }
+    }
+  number_of_threads--;
+  number_of_threads_changed(number_of_threads + 1, number_of_threads);
+  serial_lock.write_unlock ();
+}
+
+GTM::gtm_thread::gtm_thread ()
+{
+  // This object's memory has been set to zero by operator new, so no need
+  // to initialize any of the other primitive-type members that do not have
+  // constructors.
+  shared_state = ~(typeof shared_state)0;
+
+  // Register this transaction with the list of all threads' transactions.
+  serial_lock.write_lock ();
+  next_thread = list_of_threads;
+  list_of_threads = this;
+  number_of_threads++;
+  number_of_threads_changed(number_of_threads - 1, number_of_threads);
+  serial_lock.write_unlock ();
+
+  if (pthread_once(&thr_release_once, thread_exit_init))
+    GTM_fatal("Initializing thread release TLS key failed.");
+  // Any non-null value is sufficient to trigger destruction of this
+  // transaction when the current thread terminates.
+  if (pthread_setspecific(thr_release_key, this))
+    GTM_fatal("Setting thread release TLS key failed.");
+}
+
+
+
+#ifndef HAVE_64BIT_SYNC_BUILTINS
+static pthread_mutex_t global_tid_lock = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static inline uint32_t choose_code_path(uint32_t prop, abi_dispatch *disp)
+{
+  if ((prop & pr_uninstrumentedCode) && 
disp->can_run_uninstrumented_code())
+    return a_runUninstrumentedCode;
+  else
+    return a_runInstrumentedCode;
+}
+
+uint32_t
+GTM::gtm_thread::begin_transaction (uint32_t prop, const gtm_jmpbuf *jb)
+{
+  static const _ITM_transactionId_t tid_block_size = 1 << 16;
+
+  gtm_thread *tx;
+  abi_dispatch *disp;
+  uint32_t ret;
+
+  // ??? pr_undoLogCode is not properly defined in the ABI. Are barriers
+  // omitted because they are not necessary (e.g., a transaction on thread-
+  // local data) or because the compiler thinks that some kind of global
+  // synchronization might perform better?
+  if (unlikely(prop & pr_undoLogCode))
+    GTM_fatal("pr_undoLogCode not supported");
+
+  tx = gtm_thr();
+  if (unlikely(tx == NULL))
+    {
+      // Create the thread object. The constructor will also set up 
automatic
+      // deletion on thread termination.
+      tx = new gtm_thread();
+      set_gtm_thr(tx);
+    }
+
+  if (tx->nesting > 0)
+    {
+      // This is a nested transaction.
+      // Check prop compatibility:
+      // The ABI requires pr_hasNoFloatUpdate, pr_hasNoVectorUpdate,
+      // pr_hasNoIrrevocable, pr_aWBarriersOmitted, 
pr_RaRBarriersOmitted, and
+      // pr_hasNoSimpleReads to hold for the full dynamic scope of a
+      // transaction. We could check that these are set for the nested
+      // transaction if they are also set for the parent transaction, 
but the
+      // ABI does not require these flags to be set if they could be set,
+      // so the check could be too strict.
+      // ??? For pr_readOnly, lexical or dynamic scope is unspecified.
+
+      if (prop & pr_hasNoAbort)
+        {
+          // We can use flat nesting, so elide this transaction.
+          if (!(prop & pr_instrumentedCode))
+            {
+              if (!(tx->state & STATE_SERIAL) ||
+                  !(tx->state & STATE_IRREVOCABLE))
+                tx->serialirr_mode();
+            }
+          // Increment nesting level after checking that we have a 
method that
+          // allows us to continue.
+          tx->nesting++;
+          return choose_code_path(prop, abi_disp());
+        }
+
+      // The transaction might abort, so use closed nesting if possible.
+      // pr_hasNoAbort has lexical scope, so the compiler should really 
have
+      // generated an instrumented code path.
+      assert(prop & pr_instrumentedCode);
+
+      // Create a checkpoint of the current transaction.
+      gtm_transaction_cp *cp = tx->parent_txns.push();
+      cp->save(tx);
+      new (&tx->alloc_actions) aa_tree<uintptr_t, gtm_alloc_action>();
+
+      // Check whether the current method actually supports closed nesting.
+      // If we can switch to another one, do so.
+      // If not, we assume that actual aborts are infrequent, and rather
+      // restart in _ITM_abortTransaction when we really have to.
+      disp = abi_disp();
+      if (!disp->closed_nesting())
+        {
+          // ??? Should we elide the transaction if there is no alternative
+          // method that supports closed nesting? If we do, we need to set
+          // some flag to prevent _ITM_abortTransaction from aborting the
+          // wrong transaction (i.e., some parent transaction).
+          abi_dispatch *cn_disp = disp->closed_nesting_alternative();
+          if (cn_disp)
+            {
+              disp = cn_disp;
+              set_abi_disp(disp);
+            }
+        }
+    }
+  else
+    {
+      // Outermost transaction
+      disp = tx->decide_begin_dispatch (prop);
+      if (disp == dispatch_serialirr() || disp == dispatch_serial())
+        {
+          tx->state = STATE_SERIAL;
+          if (disp == dispatch_serialirr())
+            tx->state |= STATE_IRREVOCABLE;
+          serial_lock.write_lock ();
+        }
+      else
+        serial_lock.read_lock (tx);
+
+      set_abi_disp (disp);
+    }
+
+  // Initialization that is common for outermost and nested transactions.
+  tx->prop = prop;
+  tx->nesting++;
+
+  tx->jb = *jb;
+
+  // As long as we have not exhausted a previously allocated block of TIDs,
+  // we can avoid an atomic operation on a shared cacheline.
+  if (tx->local_tid & (tid_block_size - 1))
+    tx->id = tx->local_tid++;
+  else
+    {
+#ifdef HAVE_64BIT_SYNC_BUILTINS
+      tx->id = __sync_add_and_fetch (&global_tid, tid_block_size);
+      tx->local_tid = tx->id + 1;
+#else
+      pthread_mutex_lock (&global_tid_lock);
+      global_tid += tid_block_size;
+      tx->id = global_tid;
+      tx->local_tid = tx->id + 1;
+      pthread_mutex_unlock (&global_tid_lock);
+#endif
+    }
+
+  // Run dispatch-specific restart code. Retry until we succeed.
+  GTM::gtm_restart_reason rr;
+  while ((rr = disp->begin_or_restart()) != NO_RESTART)
+    {
+      tx->decide_retry_strategy(rr);
+      disp = abi_disp();
+    }
+
+  // Determine the code path to run. Only irrevocable transactions 
cannot be
+  // restarted, so all other transactions need to save live variables.
+  ret = choose_code_path(prop, disp);
+  if (!(tx->state & STATE_IRREVOCABLE))
+    ret |= a_saveLiveVariables;
+  return ret;
+}
+
+
+void
+GTM::gtm_transaction_cp::save(gtm_thread* tx)
+{
+  // Save everything that we might have to restore on restarts or aborts.
+  jb = tx->jb;
+  undolog_size = tx->undolog.size();
+  memcpy(&alloc_actions, &tx->alloc_actions, sizeof(alloc_actions));
+  user_actions_size = tx->user_actions.size();
+  id = tx->id;
+  prop = tx->prop;
+  cxa_catch_count = tx->cxa_catch_count;
+  cxa_unthrown = tx->cxa_unthrown;
+  disp = abi_disp();
+  nesting = tx->nesting;
+}
+
+void
+GTM::gtm_transaction_cp::commit(gtm_thread* tx)
+{
+  // Restore state that is not persistent across commits. Exception 
handling,
+  // information, nesting level, and any logs do not need to be restored on
+  // commits of nested transactions. Allocation actions must be committed
+  // before committing the snapshot.
+  tx->jb = jb;
+  memcpy(&tx->alloc_actions, &alloc_actions, sizeof(alloc_actions));
+  tx->id = id;
+  tx->prop = prop;
+}
+
+
+void
+GTM::gtm_thread::rollback (gtm_transaction_cp *cp, bool aborting)
+{
+  // The undo log is special in that it used for both thread-local and 
shared
+  // data. Because of the latter, we have to roll it back before any
+  // dispatch-specific rollback (which handles synchronization with other
+  // transactions).
+  rollback_undolog (cp ? cp->undolog_size : 0);
+
+  // Perform dispatch-specific rollback.
+  abi_disp()->rollback (cp);
+
+  // Roll back all actions that are supposed to happen around the 
transaction.
+  rollback_user_actions (cp ? cp->user_actions_size : 0);
+  commit_allocations (true, (cp ? &cp->alloc_actions : 0));
+  revert_cpp_exceptions (cp);
+
+  if (cp)
+    {
+      // We do not yet handle restarts of nested transactions. To do 
that, we
+      // would have to restore some state (jb, id, prop, nesting) not 
to the
+      // checkpoint but to the transaction that was started from this
+      // checkpoint (e.g., nesting = cp->nesting + 1);
+      assert(aborting);
+      // Roll back the rest of the state to the checkpoint.
+      jb = cp->jb;
+      id = cp->id;
+      prop = cp->prop;
+      if (cp->disp != abi_disp())
+        set_abi_disp(cp->disp);
+      memcpy(&alloc_actions, &cp->alloc_actions, sizeof(alloc_actions));
+      nesting = cp->nesting;
+    }
+  else
+    {
+      // Roll back to the outermost transaction.
+      // Restore the jump buffer and transaction properties, which we will
+      // need for the longjmp used to restart or abort the transaction.
+      if (parent_txns.size() > 0)
+        {
+          jb = parent_txns[0].jb;
+          id = parent_txns[0].id;
+          prop = parent_txns[0].prop;
+        }
+      // Reset the transaction. Do not reset this->state, which is 
handled by
+      // the callers. Note that if we are not aborting, we reset the
+      // transaction to the point after having executed begin_transaction
+      // (we will return from it), so the nesting level must be one, 
not zero.
+      nesting = (aborting ? 0 : 1);
+      parent_txns.clear();
+    }
+
+  if (this->eh_in_flight)
+    {
+      _Unwind_DeleteException ((_Unwind_Exception *) this->eh_in_flight);
+      this->eh_in_flight = NULL;
+    }
+}
+
+void ITM_REGPARM
+_ITM_abortTransaction (_ITM_abortReason reason)
+{
+  gtm_thread *tx = gtm_thr();
+
+  assert (reason == userAbort || reason == (userAbort | outerAbort));
+  assert ((tx->prop & pr_hasNoAbort) == 0);
+
+  if (tx->state & gtm_thread::STATE_IRREVOCABLE)
+    abort ();
+
+  // Roll back to innermost transaction.
+  if (tx->parent_txns.size() > 0 && !(reason & outerAbort))
+    {
+      // If the current method does not support closed nesting but we are
+      // nested and must only roll back the innermost transaction, then
+      // restart with a method that supports closed nesting.
+      abi_dispatch *disp = abi_disp();
+      if (!disp->closed_nesting())
+        tx->restart(RESTART_CLOSED_NESTING);
+
+      // The innermost transaction is a closed nested transaction.
+      gtm_transaction_cp *cp = tx->parent_txns.pop();
+      uint32_t longjmp_prop = tx->prop;
+      gtm_jmpbuf longjmp_jb = tx->jb;
+
+      tx->rollback (cp, true);
+
+      // Jump to nested transaction (use the saved jump buffer).
+      GTM_longjmp (&longjmp_jb, a_abortTransaction | 
a_restoreLiveVariables,
+          longjmp_prop);
+    }
+  else
+    {
+      // There is no nested transaction or an abort of the outermost
+      // transaction was requested, so roll back to the outermost 
transaction.
+      tx->rollback (0, true);
+
+      // Aborting an outermost transaction finishes execution of the whole
+      // transaction. Therefore, reset transaction state.
+      if (tx->state & gtm_thread::STATE_SERIAL)
+        gtm_thread::serial_lock.write_unlock ();
+      else
+        gtm_thread::serial_lock.read_unlock (tx);
+      tx->state = 0;
+
+      GTM_longjmp (&tx->jb, a_abortTransaction | a_restoreLiveVariables,
+          tx->prop);
+    }
+}
+
+bool
+GTM::gtm_thread::trycommit ()
+{
+  nesting--;
+
+  // Skip any real commit for elided transactions.
+  if (nesting > 0 && (parent_txns.size() == 0 ||
+      nesting > parent_txns[parent_txns.size() - 1].nesting))
+    return true;
+
+  if (nesting > 0)
+    {
+      // Commit of a closed-nested transaction. Remove one checkpoint 
and add
+      // any effects of this transaction to the parent transaction.
+      gtm_transaction_cp *cp = parent_txns.pop();
+      commit_allocations(false, &cp->alloc_actions);
+      cp->commit(this);
+      return true;
+    }
+
+  // Commit of an outermost transaction.
+  gtm_word priv_time = 0;
+  if (abi_disp()->trycommit (priv_time))
+    {
+      // The transaction is now inactive. Everything that we still have 
to do
+      // will not synchronize with other transactions anymore.
+      if (state & gtm_thread::STATE_SERIAL)
+        gtm_thread::serial_lock.write_unlock ();
+      else
+        gtm_thread::serial_lock.read_unlock (this);
+      state = 0;
+
+      // We can commit the undo log after dispatch-specific commit and 
after
+      // making the transaction inactive because we only have to reset
+      // gtm_thread state.
+      commit_undolog ();
+      // Reset further transaction state.
+      cxa_catch_count = 0;
+      cxa_unthrown = NULL;
+      restart_total = 0;
+
+      // Ensure privatization safety, if necessary.
+      if (priv_time)
+        {
+          // TODO Don't just spin but also block using cond vars / futexes
+          // here. Should probably be integrated with the serial lock code.
+          // TODO For C++0x atomics, the loads of other threads' 
shared_state
+          // should have acquire semantics (together with releases for the
+          // respective updates). But is this unnecessary overhead because
+          // weaker barriers are sufficient?
+          for (gtm_thread *it = gtm_thread::list_of_threads; it != 0;
+              it = it->next_thread)
+            {
+              if (it == this) continue;
+              while (it->shared_state < priv_time)
+                cpu_relax();
+            }
+        }
+
+      // After ensuring privatization safety, we execute potentially
+      // privatizing actions (e.g., calling free()). User actions are 
first.
+      commit_user_actions ();
+      commit_allocations (false, 0);
+
+      return true;
+    }
+  return false;
+}
+
+void ITM_NORETURN
+GTM::gtm_thread::restart (gtm_restart_reason r)
+{
+  // Roll back to outermost transaction. Do not reset transaction state 
because
+  // we will continue executing this transaction.
+  rollback ();
+  decide_retry_strategy (r);
+
+  // Run dispatch-specific restart code. Retry until we succeed.
+  abi_dispatch* disp = abi_disp();
+  GTM::gtm_restart_reason rr;
+  while ((rr = disp->begin_or_restart()) != NO_RESTART)
+    {
+      decide_retry_strategy(rr);
+      disp = abi_disp();
+    }
+
+  GTM_longjmp (&jb,
+      choose_code_path(prop, disp) | a_restoreLiveVariables, prop);
+}
+
+void ITM_REGPARM
+_ITM_commitTransaction(void)
+{
+  gtm_thread *tx = gtm_thr();
+  if (!tx->trycommit ())
+    tx->restart (RESTART_VALIDATE_COMMIT);
+}
+
+void ITM_REGPARM
+_ITM_commitTransactionEH(void *exc_ptr)
+{
+  gtm_thread *tx = gtm_thr();
+  if (!tx->trycommit ())
+    {
+      tx->eh_in_flight = exc_ptr;
+      tx->restart (RESTART_VALIDATE_COMMIT);
+    }
+}
Index: libitm/useraction.cc
===================================================================
--- libitm/useraction.cc	(.../trunk)	(revision 0)
+++ libitm/useraction.cc	(.../branches/transactional-memory)	(revision 
180773)
@@ -0,0 +1,81 @@ 
+/* 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 {
+
+void
+gtm_thread::rollback_user_actions(size_t until_size)
+{
+  for (size_t s = user_actions.size(); s > until_size; s--)
+    {
+      user_action *a = user_actions.pop();
+      if (!a->on_commit)
+        a->fn (a->arg);
+    }
+}
+
+
+void
+gtm_thread::commit_user_actions()
+{
+  for (vector<user_action>::iterator i = user_actions.begin(),
+      ie = user_actions.end(); i != ie; i++)
+    {
+      if (i->on_commit)
+        i->fn (i->arg);
+    }
+  user_actions.clear();
+}
+
+} // namespace GTM
+
+using namespace GTM;
+
+void ITM_REGPARM
+_ITM_addUserCommitAction(_ITM_userCommitFunction fn,
+			 _ITM_transactionId_t tid, void *arg)
+{
+  gtm_thread *tx = gtm_thr();
+  if (tid != _ITM_noTransactionId)
+    GTM_fatal("resumingTransactionId in _ITM_addUserCommitAction must be "
+              "_ITM_noTransactionId");
+  gtm_thread::user_action *a = tx->user_actions.push();
+  a->fn = fn;
+  a->arg = arg;
+  a->on_commit = true;
+  a->resuming_id = tid;
+}
+
+
+void ITM_REGPARM
+_ITM_addUserUndoAction(_ITM_userUndoFunction fn, void * arg)
+{
+  gtm_thread *tx = gtm_thr();
+  gtm_thread::user_action *a = tx->user_actions.push();
+  a->fn = fn;
+  a->arg = arg;
+  a->on_commit = false;
+}
Index: libitm/config.h.in
===================================================================
--- libitm/config.h.in	(.../trunk)	(revision 0)
+++ libitm/config.h.in	(.../branches/transactional-memory)	(revision 180773)
@@ -0,0 +1,159 @@ 
+/* 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 64-bit __sync_*_compare_and_swap */
+#undef HAVE_64BIT_SYNC_BUILTINS
+
+/* Define to 1 if the target supports __attribute__((alias(...))). */
+#undef HAVE_ATTRIBUTE_ALIAS
+
+/* Define to 1 if the target supports __attribute__((dllexport)). */
+#undef HAVE_ATTRIBUTE_DLLEXPORT
+
+/* Define to 1 if the target supports __attribute__((visibility(...))). */
+#undef HAVE_ATTRIBUTE_VISIBILITY
+
+/* Define if the POSIX Semaphores do not work on your system. */
+#undef HAVE_BROKEN_POSIX_SEMAPHORES
+
+/* Define to 1 if the target assembler supports thread-local storage. */
+#undef HAVE_CC_TLS
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the `memalign' function. */
+#undef HAVE_MEMALIGN
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if mmap with MAP_ANON(YMOUS) works. */
+#undef HAVE_MMAP_ANON
+
+/* Define if mmap of /dev/zero works. */
+#undef HAVE_MMAP_DEV_ZERO
+
+/* Define if read-only mmap of a plain file works. */
+#undef HAVE_MMAP_FILE
+
+/* Define to 1 if you have the `posix_memalign' function. */
+#undef HAVE_POSIX_MEMALIGN
+
+/* Define to 1 if you have the <semaphore.h> header file. */
+#undef HAVE_SEMAPHORE_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strtoull' function. */
+#undef HAVE_STRTOULL
+
+/* Define to 1 if the target supports __sync_*_compare_and_swap */
+#undef HAVE_SYNC_BUILTINS
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if the target supports thread-local storage. */
+#undef HAVE_TLS
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if GNU symbol versioning is used for libitm. */
+#undef LIBITM_GNU_SYMBOL_VERSIONING
+
+/* Define to the sub-directory in which libtool stores uninstalled 
libraries.
+   */
+#undef LT_OBJDIR
+
+/* Define to the letter to which size_t is mangled. */
+#undef MANGLE_SIZE_T
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be 
sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of `char', as computed by sizeof. */
+#undef SIZEOF_CHAR
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of `void *', as computed by sizeof. */
+#undef SIZEOF_VOID_P
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you can safely include both <string.h> and <strings.h>. */
+#undef STRING_WITH_STRINGS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* 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
Index: libitm/stmlock.h
===================================================================
--- libitm/stmlock.h	(.../trunk)	(revision 0)
+++ libitm/stmlock.h	(.../branches/transactional-memory)	(revision 180773)
@@ -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