-/* Copyright (C) 2008, 2009, 2011 Free Software Foundation, Inc.
+/* Copyright (C) 2008-2013 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>.
This file is part of the GNU Transactional Memory Library (libitm).
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
+// We'll be using some of the cpu builtins, and their associated types.
+#include <x86intrin.h>
+#include <cpuid.h>
+
namespace GTM HIDDEN {
-#ifdef __x86_64__
/* ??? This doesn't work for Win64. */
typedef struct gtm_jmpbuf
{
void *cfa;
- unsigned long rip;
- unsigned long rbx;
- unsigned long rbp;
- unsigned long r12;
- unsigned long r13;
- unsigned long r14;
- unsigned long r15;
-} gtm_jmpbuf;
+#ifdef __x86_64__
+ unsigned long long rbx;
+ unsigned long long rbp;
+ unsigned long long r12;
+ unsigned long long r13;
+ unsigned long long r14;
+ unsigned long long r15;
+ unsigned long long rip;
#else
-typedef struct gtm_jmpbuf
-{
- void *cfa;
unsigned long ebx;
unsigned long esi;
unsigned long edi;
unsigned long ebp;
unsigned long eip;
-} gtm_jmpbuf;
#endif
+} gtm_jmpbuf;
/* x86 doesn't require strict alignment for the basic types. */
#define STRICT_ALIGNMENT 0
static inline void
cpu_relax (void)
{
- __asm volatile ("rep; nop" : : : "memory");
+ __builtin_ia32_pause ();
}
-static inline void
-atomic_read_barrier (void)
+// Use Intel RTM if supported by the assembler.
+// See gtm_thread::begin_transaction for how these functions are used.
+#ifdef HAVE_AS_RTM
+#define USE_HTM_FASTPATH
+
+static inline bool
+htm_available ()
+{
+ const unsigned cpuid_rtm = bit_RTM;
+ if (__get_cpuid_max (0, NULL) >= 7)
+ {
+ unsigned a, b, c, d;
+ __cpuid_count (7, 0, a, b, c, d);
+ if (b & cpuid_rtm)
+ return true;
+ }
+ return false;
+}
+
+static inline uint32_t
+htm_init ()
+{
+ // Maximum number of times we try to execute a transaction as a HW
+ // transaction.
+ // ??? Why 2? Any offline or runtime tuning necessary?
+ return htm_available () ? 2 : 0;
+}
+
+static inline uint32_t
+htm_begin ()
+{
+ return _xbegin();
+}
+
+static inline bool
+htm_begin_success (uint32_t begin_ret)
{
- /* x86 is a strong memory ordering machine. */
- __asm volatile ("" : : : "memory");
+ return begin_ret == _XBEGIN_STARTED;
}
static inline void
-atomic_write_barrier (void)
+htm_commit ()
{
- /* x86 is a strong memory ordering machine. */
- __asm volatile ("" : : : "memory");
+ _xend();
}
-} // namespace GTM
+static inline void
+htm_abort ()
+{
+ // ??? According to a yet unpublished ABI rule, 0xff is reserved and
+ // supposed to signal a busy lock. Source: andi.kleen@intel.com
+ _xabort(0xff);
+}
-// We'll be using some of the cpu builtins, and their associated types.
-#ifndef __cplusplus
-/* ??? It's broken for C++. */
-#include <x86intrin.h>
-#else
-# ifdef __SSE2__
-# include <emmintrin.h>
-# elif defined(__SSE__)
-# include <xmmintrin.h>
-# endif
-# ifdef __AVX__
-# include <immintrin.h>
-# endif
+static inline bool
+htm_abort_should_retry (uint32_t begin_ret)
+{
+ return begin_ret & _XABORT_RETRY;
+}
#endif
+
+
+} // namespace GTM