URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/tags/gnu-dev/fsf-gcc-snapshot-1-mar-12/or1k-gcc/libitm/config
- from Rev 737 to Rev 783
- ↔ Reverse comparison
Rev 737 → Rev 783
/arm/sjlj.S
0,0 → 1,164
/* Copyright (C) 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 "hwcap.h" |
#include "asmcfi.h" |
|
.syntax unified |
|
#if defined(__thumb2__) |
# define PC_OFS 4 |
.thumb |
.thumb_func |
#else |
# define PC_OFS 8 |
#endif |
|
#if defined (__thumb2__) && defined(__ARM_ARCH_6T2__) |
# define HAVE_MOVT |
.arch armv6t2 |
#elif defined (__ARM_ARCH_7A__) |
# define HAVE_MOVT |
.arch armv7-a |
#elif defined (__ARM_ARCH_7R__) |
# define HAVE_MOVT |
.arch armv7-r |
#elif defined (__ARM_ARCH_7M__) |
# define HAVE_MOVT |
.arch armv7-m |
#endif |
|
#if defined(HAVE_MOVT) && defined(PIC) |
.macro ldaddr reg, addr |
movw \reg, #:lower16:(\addr - (98f + PC_OFS)) |
movt \reg, #:upper16:(\addr - (98f + PC_OFS)) |
98: add \reg, \reg, pc |
.endm |
#elif defined(HAVE_MOVT) |
.macro ldaddr reg, addr |
movw \reg, #:lower16:\addr |
movt \reg, #:upper16:\addr |
.endm |
#elif defined(PIC) |
.macro ldaddr reg, addr |
ldr \reg, 99f |
98: add \reg, \reg, pc |
.subsection 1 |
.align 2 |
99: .word \addr - (98b + PC_OFS) |
.subsection 0 |
.endm |
#else |
.macro ldaddr reg, addr |
ldr \reg, =\addr |
.endm |
#endif |
|
.text |
.align 2 |
.global _ITM_beginTransaction |
.type _ITM_beginTransaction, %function |
|
_ITM_beginTransaction: |
.fnstart |
cfi_startproc |
mov ip, sp |
push { r4-r11, ip, lr } |
.save { lr } |
.pad #(9*4) |
cfi_adjust_cfa_offset(40) |
cfi_rel_offset(lr, 36) |
sub sp, sp, #(14*8) |
.pad #(14*8) |
cfi_adjust_cfa_offset(14*8) |
|
ldaddr r2, GTM_hwcap |
ldr r2, [r2] |
|
/* Store the VFP registers. Don't use VFP instructions directly |
because this code is used in non-VFP multilibs. */ |
tst r2, #HWCAP_ARM_VFP |
beq 1f |
stc p11, cr8, [sp], {16} /* vstm sp, {d8-d15} */ |
1: |
/* Save the call-preserved iWMMXt registers. */ |
tst r2, #HWCAP_ARM_IWMMXT |
beq 1f |
stcl p1, cr10, [sp, #64] /* wstrd wr10, [sp, #64] */ |
stcl p1, cr11, [sp, #72] |
stcl p1, cr12, [sp, #80] |
stcl p1, cr13, [sp, #88] |
stcl p1, cr14, [sp, #96] |
stcl p1, cr15, [sp, #104] |
1: |
/* Invoke GTM_begin_transaction with the struct we just built. */ |
mov r1, sp |
bl GTM_begin_transaction |
|
/* Return; we don't need to restore any of the call-saved regs. */ |
add sp, sp, #(14*8 + 9*4) |
cfi_adjust_cfa_offset(-(14*8 + 9*4)) |
pop { pc } |
.fnend |
cfi_endproc |
.size _ITM_beginTransaction, . - _ITM_beginTransaction |
|
.align 2 |
.global GTM_longjmp |
.hidden GTM_longjmp |
.type GTM_longjmp, %function |
|
GTM_longjmp: |
cfi_startproc |
ldaddr r2, GTM_hwcap |
ldr r2, [r2] |
|
tst r2, #HWCAP_ARM_VFP |
beq 1f |
ldc p11, cr8, [r1], {16} /* vldmia r1, {d8-d15} */ |
1: |
tst r2, #HWCAP_ARM_IWMMXT |
beq 1f |
ldcl p1, cr10, [r1, #64] /* wldrd wr10, [r1, #64] */ |
ldcl p1, cr11, [r1, #72] |
ldcl p1, cr12, [r1, #80] |
ldcl p1, cr13, [r1, #88] |
ldcl p1, cr14, [r1, #96] |
ldcl p1, cr15, [r1, #104] |
1: |
add r1, r1, #(14*8) /* Skip both VFP and iWMMXt blocks */ |
#ifdef __thumb2__ |
ldm r1, { r4-r11, ip, lr } |
cfi_def_cfa(ip, 0) |
mov sp, ip |
bx lr |
#else |
ldm r1, { r4-r11, sp, pc } |
#endif |
cfi_endproc |
.size GTM_longjmp, . - GTM_longjmp |
|
#ifdef __linux__ |
.section .note.GNU-stack, "", %progbits |
#endif |
/arm/hwcap.cc
0,0 → 1,67
/* Copyright (C) 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/>. */ |
|
/* This file initializes GTM_hwcap in some os-specific way to indicate |
what ISA extensions are present for ARM. */ |
|
#include "libitm_i.h" |
#include "hwcap.h" |
|
/* Begin by defaulting to whatever options were given to the compiler. */ |
int GTM_hwcap HIDDEN = 0 |
#ifdef __VFP_FP__ |
| HWCAP_ARM_VFP |
#endif |
#ifdef __IWMMXT__ |
| HWCAP_ARM_IWMMXT |
#endif |
; |
|
#ifdef __linux__ |
#include <unistd.h> |
#include <sys/fcntl.h> |
#include <elf.h> |
|
static void __attribute__((constructor)) |
init_gtm_hwcap(void) |
{ |
int fd = open ("/proc/self/auxv", O_RDONLY); |
if (fd < 0) |
return; |
|
Elf32_auxv_t pairs[512]; |
ssize_t rlen = read (fd, pairs, sizeof(pairs)); |
close (fd); |
if (rlen < 0) |
return; |
|
size_t n = (size_t)rlen / sizeof(pairs[0]); |
for (size_t i = 0; i < n; ++i) |
if (pairs[i].a_type == AT_HWCAP) |
{ |
GTM_hwcap = pairs[i].a_un.a_val; |
return; |
} |
} |
#endif |
/arm/hwcap.h
0,0 → 1,41
/* Copyright (C) 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/>. */ |
|
/* The following must match the kernel's <asm/procinfo.h>. */ |
#define HWCAP_ARM_SWP 1 |
#define HWCAP_ARM_HALF 2 |
#define HWCAP_ARM_THUMB 4 |
#define HWCAP_ARM_26BIT 8 |
#define HWCAP_ARM_FAST_MULT 16 |
#define HWCAP_ARM_FPA 32 |
#define HWCAP_ARM_VFP 64 |
#define HWCAP_ARM_EDSP 128 |
#define HWCAP_ARM_JAVA 256 |
#define HWCAP_ARM_IWMMXT 512 |
#define HWCAP_ARM_CRUNCH 1024 |
#define HWCAP_ARM_THUMBEE 2048 |
#define HWCAP_ARM_NEON 4096 |
#define HWCAP_ARM_VFPv3 8192 |
#define HWCAP_ARM_VFPv3D16 16384 |
|
/arm/target.h
0,0 → 1,53
/* Copyright (C) 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/>. */ |
|
namespace GTM HIDDEN { |
|
typedef struct gtm_jmpbuf |
{ |
unsigned long long vfp[8]; /* d8-d15 */ |
unsigned long long iwmmxt[6]; /* cr10-cr15 */ |
unsigned long gr[8]; /* r4-r11 */ |
void *cfa; |
unsigned long pc; |
} gtm_jmpbuf; |
|
/* ARM generally uses a fixed page size of 4K. */ |
#define PAGE_SIZE 4096 |
#define FIXED_PAGE_SIZE 1 |
|
/* ??? The size of one line in hardware caches (in bytes). */ |
#define HW_CACHELINE_SIZE 64 |
|
static inline void |
cpu_relax (void) |
{ |
/* ??? The kernel uses the condition |
#if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327) |
Given that we're actually just waiting, it doesn't seem like it |
hurts to simply use a full barrier all the time. */ |
__sync_synchronize (); |
} |
|
} // namespace GTM |
/linux/powerpc/futex_bits.h
0,0 → 1,54
/* Copyright (C) 2012 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 <sys/syscall.h> |
|
static inline long |
sys_futex0 (std::atomic<int> *addr, int op, int val) |
{ |
register long int r0 __asm__ ("r0"); |
register long int r3 __asm__ ("r3"); |
register long int r4 __asm__ ("r4"); |
register long int r5 __asm__ ("r5"); |
register long int r6 __asm__ ("r6"); |
|
r0 = SYS_futex; |
r3 = (long) addr; |
r4 = op; |
r5 = val; |
r6 = 0; |
|
/* ??? The powerpc64 sysdep.h file clobbers ctr; the powerpc32 sysdep.h |
doesn't. It doesn't much matter for us. In the interest of unity, |
go ahead and clobber it always. */ |
|
__asm volatile ("sc; mfcr %0" |
: "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6) |
: "r"(r0), "r"(r3), "r"(r4), "r"(r5), "r"(r6) |
: "r7", "r8", "r9", "r10", "r11", "r12", |
"cr0", "ctr", "memory"); |
if (__builtin_expect (r0 & (1 << 28), 0)) |
return r3; |
return 0; |
} |
/linux/futex.cc
0,0 → 1,83
/* 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/>. */ |
|
/* Provide access to the futex system call. */ |
|
#include "libitm_i.h" |
#include "futex.h" |
#include <futex_bits.h> |
#include <errno.h> |
|
namespace GTM HIDDEN { |
|
#define FUTEX_WAIT 0 |
#define FUTEX_WAKE 1 |
#define FUTEX_PRIVATE_FLAG 128L |
|
|
static long int gtm_futex_wait = FUTEX_WAIT | FUTEX_PRIVATE_FLAG; |
static long int gtm_futex_wake = FUTEX_WAKE | FUTEX_PRIVATE_FLAG; |
|
|
void |
futex_wait (std::atomic<int> *addr, int val) |
{ |
long res; |
|
res = sys_futex0 (addr, gtm_futex_wait, val); |
if (__builtin_expect (res == -ENOSYS, 0)) |
{ |
gtm_futex_wait = FUTEX_WAIT; |
gtm_futex_wake = FUTEX_WAKE; |
res = sys_futex0 (addr, FUTEX_WAIT, val); |
} |
if (__builtin_expect (res < 0, 0)) |
{ |
if (res == -EWOULDBLOCK || res == -ETIMEDOUT) |
; |
else if (res == -EFAULT) |
GTM_fatal ("futex failed (EFAULT %p)", addr); |
else |
GTM_fatal ("futex failed (%s)", strerror(-res)); |
} |
} |
|
|
long |
futex_wake (std::atomic<int> *addr, int count) |
{ |
long res = sys_futex0 (addr, gtm_futex_wake, count); |
if (__builtin_expect (res == -ENOSYS, 0)) |
{ |
gtm_futex_wait = FUTEX_WAIT; |
gtm_futex_wake = FUTEX_WAKE; |
res = sys_futex0 (addr, FUTEX_WAKE, count); |
} |
if (__builtin_expect (res < 0, 0)) |
GTM_fatal ("futex failed (%s)", strerror(-res)); |
else |
return res; |
} |
|
} // namespace GTM |
/linux/futex.h
0,0 → 1,39
/* 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/>. */ |
|
/* Provide access to the futex system call. */ |
|
#ifndef GTM_FUTEX_H |
#define GTM_FUTEX_H 1 |
|
#include "local_atomic" |
|
namespace GTM HIDDEN { |
|
extern void futex_wait (std::atomic<int> *addr, int val); |
extern long futex_wake (std::atomic<int> *addr, int count); |
|
} |
|
#endif /* GTM_FUTEX_H */ |
/linux/futex_bits.h
0,0 → 1,39
/* Copyright (C) 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/>. */ |
|
/* Provide target-independant access to the futex system call. */ |
|
/* Note for ARM: |
There are two styles of syscall, and in the eabi style the syscall |
number goes into the thumb frame pointer. We need to either write |
this in pure assembler or just defer entirely to libc. */ |
|
#include <unistd.h> |
#include <sys/syscall.h> |
|
static inline long |
sys_futex0 (std::atomic<int> *addr, long op, long val) |
{ |
return syscall (SYS_futex, (int*) addr, op, val, 0); |
} |
/linux/alpha/futex_bits.h
0,0 → 1,56
/* 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/>. */ |
|
/* Provide target-specific access to the futex system call. */ |
|
#ifndef SYS_futex |
#define SYS_futex 394 |
#endif |
|
static inline long |
sys_futex0 (std::atomic<int> *addr, long op, long val) |
{ |
register long sc_0 __asm__("$0"); |
register long sc_16 __asm__("$16"); |
register long sc_17 __asm__("$17"); |
register long sc_18 __asm__("$18"); |
register long sc_19 __asm__("$19"); |
long res; |
|
sc_0 = SYS_futex; |
sc_16 = (long) addr; |
sc_17 = op; |
sc_18 = val; |
sc_19 = 0; |
__asm volatile ("callsys" |
: "=r" (sc_0), "=r"(sc_19) |
: "0"(sc_0), "r" (sc_16), "r"(sc_17), "r"(sc_18), "1"(sc_19) |
: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", |
"$22", "$23", "$24", "$25", "$27", "$28", "memory"); |
|
res = sc_0; |
if (__builtin_expect (sc_19, 0)) |
res = -res; |
return res; |
} |
/linux/x86/futex_bits.h
0,0 → 1,82
/* 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/>. */ |
|
#ifdef __x86_64__ |
# ifndef SYS_futex |
# define SYS_futex 202 |
# endif |
|
static inline long |
sys_futex0 (std::atomic<int> *addr, long op, long val) |
{ |
register long r10 __asm__("%r10") = 0; |
long res; |
|
__asm volatile ("syscall" |
: "=a" (res) |
: "0" (SYS_futex), "D" (addr), "S" (op), "d" (val), "r" (r10) |
: "r11", "rcx", "memory"); |
|
return res; |
} |
|
#else |
# ifndef SYS_futex |
# define SYS_futex 240 |
# endif |
|
# ifdef __PIC__ |
|
static inline long |
sys_futex0 (std::atomic<int> *addr, int op, int val) |
{ |
long res; |
|
__asm volatile ("xchgl\t%%ebx, %2\n\t" |
"int\t$0x80\n\t" |
"xchgl\t%%ebx, %2" |
: "=a" (res) |
: "0"(SYS_futex), "r" (addr), "c"(op), |
"d"(val), "S"(0) |
: "memory"); |
return res; |
} |
|
# else |
|
static inline long |
sys_futex0 (std::atomic<int> *addr, int op, int val) |
{ |
long res; |
|
__asm volatile ("int $0x80" |
: "=a" (res) |
: "0"(SYS_futex), "b" (addr), "c"(op), |
"d"(val), "S"(0) |
: "memory"); |
return res; |
} |
|
# endif /* __PIC__ */ |
#endif /* __x86_64__ */ |
/linux/x86/tls.h
0,0 → 1,105
/* 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/>. */ |
|
#ifndef LIBITM_X86_TLS_H |
#define LIBITM_X86_TLS_H 1 |
|
#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10) |
/* Use slots in the TCB head rather than __thread lookups. |
GLIBC has reserved words 10 through 13 for TM. */ |
#define HAVE_ARCH_GTM_THREAD 1 |
#define HAVE_ARCH_GTM_THREAD_DISP 1 |
#endif |
|
#include "config/generic/tls.h" |
|
#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 10) |
namespace GTM HIDDEN { |
|
#ifdef __x86_64__ |
#ifdef __LP64__ |
# define SEG_READ(OFS) "movq\t%%fs:(" #OFS "*8),%0" |
# define SEG_WRITE(OFS) "movq\t%0,%%fs:(" #OFS "*8)" |
# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \ |
"rorq\t$17,%0\n\t" \ |
"xorq\t%%fs:48,%0" |
# define SEG_ENCODE_WRITE(OFS) "xorq\t%%fs:48,%0\n\t" \ |
"rolq\t$17,%0\n\t" \ |
SEG_WRITE(OFS) |
#else |
// For X32. |
# define SEG_READ(OFS) "movl\t%%fs:(" #OFS "*4),%0" |
# define SEG_WRITE(OFS) "movl\t%0,%%fs:(" #OFS "*4)" |
# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \ |
"rorl\t$9,%0\n\t" \ |
"xorl\t%%fs:24,%0" |
# define SEG_ENCODE_WRITE(OFS) "xorl\t%%fs:24,%0\n\t" \ |
"roll\t$9,%0\n\t" \ |
SEG_WRITE(OFS) |
#endif |
#else |
# define SEG_READ(OFS) "movl\t%%gs:(" #OFS "*4),%0" |
# define SEG_WRITE(OFS) "movl\t%0,%%gs:(" #OFS "*4)" |
# define SEG_DECODE_READ(OFS) SEG_READ(OFS) "\n\t" \ |
"rorl\t$9,%0\n\t" \ |
"xorl\t%%gs:24,%0" |
# define SEG_ENCODE_WRITE(OFS) "xorl\t%%gs:24,%0\n\t" \ |
"roll\t$9,%0\n\t" \ |
SEG_WRITE(OFS) |
#endif |
|
static inline struct gtm_thread *gtm_thr(void) |
{ |
struct gtm_thread *r; |
asm volatile (SEG_READ(10) : "=r"(r)); |
return r; |
} |
|
static inline void set_gtm_thr(struct gtm_thread *x) |
{ |
asm volatile (SEG_WRITE(10) : : "r"(x)); |
} |
|
static inline struct abi_dispatch *abi_disp(void) |
{ |
struct abi_dispatch *r; |
asm volatile (SEG_DECODE_READ(11) : "=r"(r)); |
return r; |
} |
|
static inline void set_abi_disp(struct abi_dispatch *x) |
{ |
void *scratch; |
asm volatile (SEG_ENCODE_WRITE(11) : "=r"(scratch) : "0"(x)); |
} |
|
#undef SEG_READ |
#undef SEG_WRITE |
#undef SEG_DECODE_READ |
#undef SEG_ENCODE_WRITE |
|
} // namespace GTM |
#endif /* >= GLIBC 2.10 */ |
|
#endif // LIBITM_X86_TLS_H |
/linux/rwlock.cc
0,0 → 1,256
/* Copyright (C) 2011 Free Software Foundation, Inc. |
Contributed by Torvald Riegel <triegel@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 "futex.h" |
#include <limits.h> |
|
namespace GTM HIDDEN { |
|
// Acquire a RW lock for reading. |
|
void |
gtm_rwlock::read_lock (gtm_thread *tx) |
{ |
for (;;) |
{ |
// Fast path: first announce our intent to read, then check for |
// conflicting intents to write. The fence ensures that this happens |
// in exactly this order. |
tx->shared_state.store (0, memory_order_relaxed); |
atomic_thread_fence (memory_order_seq_cst); |
if (likely (writers.load (memory_order_relaxed) == 0)) |
return; |
|
// There seems to be an active, waiting, or confirmed writer, so enter |
// the futex-based slow path. |
|
// Before waiting, we clear our read intent check whether there are any |
// writers that might potentially wait for readers. If so, wake them. |
// We need the barrier here for the same reason that we need it in |
// read_unlock(). |
// TODO Potentially too many wake-ups. See comments in read_unlock(). |
tx->shared_state.store (-1, memory_order_relaxed); |
atomic_thread_fence (memory_order_seq_cst); |
if (writer_readers.load (memory_order_relaxed) > 0) |
{ |
writer_readers.store (0, memory_order_relaxed); |
futex_wake(&writer_readers, 1); |
} |
|
// Signal that there are waiting readers and wait until there is no |
// writer anymore. |
// TODO Spin here on writers for a while. Consider whether we woke |
// any writers before? |
while (writers.load (memory_order_relaxed)) |
{ |
// An active writer. Wait until it has finished. To avoid lost |
// wake-ups, we need to use Dekker-like synchronization. |
// Note that we cannot reset readers to zero when we see that there |
// are no writers anymore after the barrier because this pending |
// store could then lead to lost wake-ups at other readers. |
readers.store (1, memory_order_relaxed); |
atomic_thread_fence (memory_order_seq_cst); |
if (writers.load (memory_order_relaxed)) |
futex_wait(&readers, 1); |
} |
|
// And we try again to acquire a read lock. |
} |
} |
|
|
// Acquire a RW lock for writing. Generic version that also works for |
// upgrades. |
// Note that an upgrade might fail (and thus waste previous work done during |
// this transaction) if there is another thread that tried to go into serial |
// mode earlier (i.e., upgrades do not have higher priority than pure writers). |
// However, this seems rare enough to not consider it further as we need both |
// a non-upgrade writer and a writer to happen to switch to serial mode |
// concurrently. If we'd want to handle this, a writer waiting for readers |
// would have to coordinate with later arriving upgrades and hand over the |
// lock to them, including the the reader-waiting state. We can try to support |
// this if this will actually happen often enough in real workloads. |
|
bool |
gtm_rwlock::write_lock_generic (gtm_thread *tx) |
{ |
// Try to acquire the write lock. |
int w = 0; |
if (unlikely (!writers.compare_exchange_strong (w, 1))) |
{ |
// If this is an upgrade, we must not wait for other writers or |
// upgrades. |
if (tx != 0) |
return false; |
|
// There is already a writer. If there are no other waiting writers, |
// switch to contended mode. We need seq_cst memory order to make the |
// Dekker-style synchronization work. |
if (w != 2) |
w = writers.exchange (2); |
while (w != 0) |
{ |
futex_wait(&writers, 2); |
w = writers.exchange (2); |
} |
} |
|
// We have acquired the writer side of the R/W lock. Now wait for any |
// readers that might still be active. |
// We don't need an extra barrier here because the CAS and the xchg |
// operations have full barrier semantics already. |
// TODO In the worst case, this requires one wait/wake pair for each |
// active reader. Reduce this! |
for (gtm_thread *it = gtm_thread::list_of_threads; it != 0; |
it = it->next_thread) |
{ |
if (it == tx) |
continue; |
// Use a loop here to check reader flags again after waiting. |
while (it->shared_state.load (memory_order_relaxed) |
!= ~(typeof it->shared_state)0) |
{ |
// An active reader. Wait until it has finished. To avoid lost |
// wake-ups, we need to use Dekker-like synchronization. |
// Note that we can reset writer_readers to zero when we see after |
// the barrier that the reader has finished in the meantime; |
// however, this is only possible because we are the only writer. |
// TODO Spin for a while on this reader flag. |
writer_readers.store (1, memory_order_relaxed); |
atomic_thread_fence (memory_order_seq_cst); |
if (it->shared_state.load (memory_order_relaxed) |
!= ~(typeof it->shared_state)0) |
futex_wait(&writer_readers, 1); |
else |
writer_readers.store (0, memory_order_relaxed); |
} |
} |
|
return true; |
} |
|
// Acquire a RW lock for writing. |
|
void |
gtm_rwlock::write_lock () |
{ |
write_lock_generic (0); |
} |
|
|
// Upgrade a RW lock that has been locked for reading to a writing lock. |
// Do this without possibility of another writer incoming. Return false |
// if this attempt fails (i.e. another thread also upgraded). |
|
bool |
gtm_rwlock::write_upgrade (gtm_thread *tx) |
{ |
return write_lock_generic (tx); |
} |
|
|
// Has to be called iff the previous upgrade was successful and after it is |
// safe for the transaction to not be marked as a reader anymore. |
|
void |
gtm_rwlock::write_upgrade_finish (gtm_thread *tx) |
{ |
// We are not a reader anymore. This is only safe to do after we have |
// acquired the writer lock. |
tx->shared_state.store (-1, memory_order_release); |
} |
|
|
// Release a RW lock from reading. |
|
void |
gtm_rwlock::read_unlock (gtm_thread *tx) |
{ |
// We only need release memory order here because of privatization safety |
// (this ensures that marking the transaction as inactive happens after |
// any prior data accesses by this transaction, and that neither the |
// compiler nor the hardware order this store earlier). |
// ??? We might be able to avoid this release here if the compiler can't |
// merge the release fence with the subsequent seq_cst fence. |
tx->shared_state.store (-1, memory_order_release); |
|
// If there is a writer waiting for readers, wake it up. We need the fence |
// to avoid lost wake-ups. Furthermore, the privatization safety |
// implementation in gtm_thread::try_commit() relies on the existence of |
// this seq_cst fence. |
// ??? We might not be the last active reader, so the wake-up might happen |
// too early. How do we avoid this without slowing down readers too much? |
// Each reader could scan the list of txns for other active readers but |
// this can result in many cache misses. Use combining instead? |
// TODO Sends out one wake-up for each reader in the worst case. |
atomic_thread_fence (memory_order_seq_cst); |
if (unlikely (writer_readers.load (memory_order_relaxed) > 0)) |
{ |
// No additional barrier needed here (see write_unlock()). |
writer_readers.store (0, memory_order_relaxed); |
futex_wake(&writer_readers, 1); |
} |
} |
|
|
// Release a RW lock from writing. |
|
void |
gtm_rwlock::write_unlock () |
{ |
// This needs to have seq_cst memory order. |
if (writers.fetch_sub (1) == 2) |
{ |
// There might be waiting writers, so wake them. |
writers.store (0, memory_order_relaxed); |
if (futex_wake(&writers, 1) == 0) |
{ |
// If we did not wake any waiting writers, we might indeed be the |
// last writer (this can happen because write_lock_generic() |
// exchanges 0 or 1 to 2 and thus might go to contended mode even if |
// no other thread holds the write lock currently). Therefore, we |
// have to wake up readers here as well. Execute a barrier after |
// the previous relaxed reset of writers (Dekker-style), and fall |
// through to the normal reader wake-up code. |
atomic_thread_fence (memory_order_seq_cst); |
} |
else |
return; |
} |
// No waiting writers, so wake up all waiting readers. |
// Because the fetch_and_sub is a full barrier already, we don't need |
// another barrier here (as in read_unlock()). |
if (readers.load (memory_order_relaxed) > 0) |
{ |
// No additional barrier needed here. The previous load must be in |
// modification order because of the coherency constraints. Late stores |
// by a reader are not a problem because readers do Dekker-style |
// synchronization on writers. |
readers.store (0, memory_order_relaxed); |
futex_wake(&readers, INT_MAX); |
} |
} |
|
} // namespace GTM |
/linux/rwlock.h
0,0 → 1,68
/* Copyright (C) 2011 Free Software Foundation, Inc. |
Contributed by Torvald Riegel <triegel@redhat.com>. |
|
This file is part of the GNU Transactional Memory Library (libitm). |
|
Libitm is free software; you can redistribute it and/or modify it |
under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 3 of the License, or |
(at your option) any later version. |
|
Libitm is distributed in the hope that it will be useful, but WITHOUT ANY |
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
more details. |
|
Under Section 7 of GPL version 3, you are granted additional |
permissions described in the GCC Runtime Library Exception, version |
3.1, as published by the Free Software Foundation. |
|
You should have received a copy of the GNU General Public License and |
a copy of the GCC Runtime Library Exception along with this program; |
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
<http://www.gnu.org/licenses/>. */ |
|
#ifndef GTM_RWLOCK_H |
#define GTM_RWLOCK_H |
|
#include "local_atomic" |
#include "common.h" |
|
namespace GTM HIDDEN { |
|
struct gtm_thread; |
|
// This datastructure is the blocking, futex-based version of the Dekker-style |
// reader-writer lock used to provide mutual exclusion between active and |
// serial transactions. |
// See libitm's documentation for further details. |
// |
// In this implementation, writers are given highest priority access but |
// read-to-write upgrades do not have a higher priority than writers. |
|
class gtm_rwlock |
{ |
// TODO Put futexes on different cachelines? |
std::atomic<int> writers; // Writers' futex. |
std::atomic<int> writer_readers;// A confirmed writer waits here for readers. |
std::atomic<int> readers; // Readers wait here for writers (iff true). |
|
public: |
gtm_rwlock() : writers(0), writer_readers(0), readers(0) {}; |
|
void read_lock (gtm_thread *tx); |
void read_unlock (gtm_thread *tx); |
|
void write_lock (); |
void write_unlock (); |
|
bool write_upgrade (gtm_thread *tx); |
void write_upgrade_finish (gtm_thread *tx); |
|
protected: |
bool write_lock_generic (gtm_thread *tx); |
}; |
|
} // namespace GTM |
|
#endif // GTM_RWLOCK_H |
/linux/sparc/futex_bits.h
0,0 → 1,62
/* Copyright (C) 2012 Free Software Foundation, Inc. |
|
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 <sys/syscall.h> |
|
static inline long |
sys_futex0 (std::atomic<int> *addr, int op, int val) |
{ |
register long int g1 __asm__ ("g1"); |
register long int o0 __asm__ ("o0"); |
register long int o1 __asm__ ("o1"); |
register long int o2 __asm__ ("o2"); |
register long int o3 __asm__ ("o3"); |
long res; |
|
g1 = SYS_futex; |
o0 = (long) addr; |
o1 = op; |
o2 = val; |
o3 = 0; |
|
#ifdef __arch64__ |
__asm volatile ("ta 0x6d" |
#else |
__asm volatile ("ta 0x10" |
#endif |
: "=r"(g1), "=r"(o0) |
: "0"(g1), "1"(o0), "r"(o1), "r"(o2), "r"(o3) |
: "g2", "g3", "g4", "g5", "g6", |
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", |
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", |
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", |
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", |
"f32", "f34", "f36", "f38", "f40", "f42", "f44", "f46", |
"f48", "f50", "f52", "f54", "f56", "f58", "f60", "f62", |
"cc", "memory"); |
|
res = o0; |
if (__builtin_expect ((unsigned long) res >= -515UL, 0)) |
res =- res; |
return res; |
} |
/linux/sh/futex_bits.h
0,0 → 1,50
/* Copyright (C) 2011 Free Software Foundation, Inc. |
|
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/>. */ |
|
/* Provide target-specific access to the futex system call. */ |
|
#include <sys/syscall.h> |
|
/* 4 instruction cycles not accessing cache and TLB are needed after |
trapa instruction to avoid an SH-4 silicon bug. */ |
|
#define SYSCALL_WITH_INST_PAD "\ |
trapa #0x14; or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0" |
|
static inline long |
sys_futex0 (std::atomic<int> *addr, long op, long val) |
{ |
int __status; |
register long __r3 asm ("r3") = SYS_futex; |
register long __r4 asm ("r4") = (long) addr; |
register long __r5 asm ("r5") = op; |
register long __r6 asm ("r6") = val; |
register long __r7 asm ("r7") = 0; |
|
__asm __volatile (SYSCALL_WITH_INST_PAD |
: "=z" (__status) |
: "r" (__r3), "r" (__r4), "r" (__r5), |
"r" (__r6), "r" (__r7) |
: "memory", "t"); |
return __status; |
} |
/powerpc/cacheline.h
0,0 → 1,42
/* Copyright (C) 2012 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_POWERPC_CACHELINE_H |
#define LIBITM_POWERPC_CACHELINE_H 1 |
|
// A cacheline is the smallest unit with which locks are associated. |
// The current implementation of the _ITM_[RW] barriers assumes that |
// all data types can fit (aligned) within a cachline, which means |
// in practice sizeof(complex long double) is the smallest cacheline size. |
// It ought to be small enough for efficient manipulation of the |
// modification mask, below. |
#if defined (__powerpc64__) || defined (__ppc64__) |
# define CACHELINE_SIZE 64 |
#else |
# define CACHELINE_SIZE 32 |
#endif |
|
#include "config/generic/cacheline.h" |
|
#endif // LIBITM_POWERPC_CACHELINE_H |
/powerpc/sjlj.S
0,0 → 1,411
/* Copyright (C) 2012 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/>. */ |
|
.text |
|
#include "asmcfi.h" |
|
#if defined(__powerpc64__) && defined(__ELF__) |
.macro FUNC name |
.globl \name, .\name |
.section ".opd","aw" |
.align 3 |
\name: |
.quad .\name, .TOC.@tocbase, 0 |
.size \name, 24 |
.type .\name, @function |
.text |
.\name: |
.endm |
.macro END name |
.size .\name, . - .\name |
.endm |
.macro HIDDEN name |
.hidden \name, .\name |
.endm |
.macro CALL name |
bl \name |
nop |
.endm |
#elif defined(__ELF__) |
.macro FUNC name |
.globl \name |
.type \name, @function |
\name: |
.endm |
.macro END name |
.size \name, . - \name |
.endm |
.macro HIDDEN name |
.hidden \name |
.endm |
.macro CALL name |
bl \name |
.endm |
#elif defined(_CALL_DARWIN) |
.macro FUNC name |
.globl _$0 |
_$0: |
.endmacro |
.macro END name |
.endmacro |
.macro HIDDEN name |
.private_extern _$0 |
.endmacro |
.macro CALL name |
bl _$0 |
.endmacro |
# ifdef __ppc64__ |
.machine ppc64 |
# else |
.machine ppc7400 |
# endif |
#else |
#error "unsupported system" |
#endif |
|
/* Parameterize the naming of registers. */ |
#if defined(__ELF__) |
# define r(N) %r##N |
# define f(N) %f##N |
# define v(N) %v##N |
#elif defined(__MACH__) |
# define r(N) r##N |
# define f(N) f##N |
# define v(N) v##N |
#else |
# define r(N) N |
# define f(N) N |
# define v(N) N |
#endif |
|
/* Parameterize the code for 32-bit vs 64-bit. */ |
#if defined(__powerpc64__) || defined(__ppc64__) |
#define ldreg ld |
#define streg std |
#define stregu stdu |
#define WS 8 |
#else |
#define ldreg lwz |
#define streg stw |
#define stregu stwu |
#define WS 4 |
#endif |
|
/* Parameterize the code for call frame constants. */ |
#if defined(_CALL_AIXDESC) |
# define BASE 6*WS |
# define LR_SAVE 2*WS |
#elif defined(_CALL_SYSV) |
# define BASE 2*WS |
# define LR_SAVE 1*WS |
#elif defined(_CALL_DARWIN) |
# define BASE (6*WS + 2*WS) |
# define LR_SAVE 2*WS |
#else |
# error "unsupported system" |
#endif |
|
#if defined(__ALTIVEC__) || defined(__VSX__) |
# define OFS_VR 0 |
# define OFS_VSCR 12*16 |
# define OFS_VR_END OFS_VSCR + 8 |
#else |
# define OFS_VR_END 0 |
#endif |
#ifndef _SOFT_FLOAT |
# define OFS_FR OFS_VR_END |
# define OFS_FPSCR OFS_FR + 18*8 |
# define OFS_FR_END OFS_FPSCR + 8 |
#else |
# define OFS_FR_END OFS_VR_END |
#endif |
#define OFS_GR OFS_FR_END |
#define OFS_CFA OFS_GR + 18*WS |
#define OFS_LR OFS_CFA + WS |
#define OFS_TOC OFS_LR + WS |
#define OFS_CR OFS_TOC + WS |
#define OFS_END (((OFS_CR + WS + 15) / 16) * 16) |
|
#define FRAME (((BASE + OFS_END + 15) / 16) * 16) |
#define VRSAVE 256 |
|
.align 4 |
FUNC _ITM_beginTransaction |
cfi_startproc |
mflr r(0) |
mfcr r(5) |
addi r(4), r(1), -OFS_END |
mr r(6), r(1) |
streg r(0), LR_SAVE(r(1)) |
stregu r(1), -FRAME(r(1)) |
cfi_def_cfa_offset(FRAME) |
cfi_offset(65, LR_SAVE) |
streg r(6), OFS_CFA(r(4)) |
streg r(0), OFS_LR(r(4)) |
#ifdef _CALL_DARWIN |
streg r(13), OFS_TOC(r(4)) |
#else |
streg r(2), OFS_TOC(r(4)) |
#endif |
streg r(5), OFS_CR(r(4)) |
streg r(14), 0*WS+OFS_GR(r(4)) |
streg r(15), 1*WS+OFS_GR(r(4)) |
streg r(16), 2*WS+OFS_GR(r(4)) |
streg r(17), 3*WS+OFS_GR(r(4)) |
streg r(18), 4*WS+OFS_GR(r(4)) |
streg r(19), 5*WS+OFS_GR(r(4)) |
streg r(20), 6*WS+OFS_GR(r(4)) |
streg r(21), 7*WS+OFS_GR(r(4)) |
streg r(22), 8*WS+OFS_GR(r(4)) |
streg r(23), 9*WS+OFS_GR(r(4)) |
streg r(24), 10*WS+OFS_GR(r(4)) |
streg r(25), 11*WS+OFS_GR(r(4)) |
streg r(26), 12*WS+OFS_GR(r(4)) |
streg r(27), 13*WS+OFS_GR(r(4)) |
streg r(28), 14*WS+OFS_GR(r(4)) |
streg r(29), 15*WS+OFS_GR(r(4)) |
streg r(30), 16*WS+OFS_GR(r(4)) |
streg r(31), 17*WS+OFS_GR(r(4)) |
|
#ifndef _SOFT_FLOAT |
/* ??? Determine when FPRs not present. */ |
/* ??? Test r(3) for pr_hasNoFloatUpdate and skip the fp save. |
This is not yet set by the compiler. */ |
mffs f(0) |
stfd f(14), 0+OFS_FR(r(4)) |
stfd f(15), 8+OFS_FR(r(4)) |
stfd f(16), 16+OFS_FR(r(4)) |
stfd f(17), 24+OFS_FR(r(4)) |
stfd f(18), 32+OFS_FR(r(4)) |
stfd f(19), 40+OFS_FR(r(4)) |
stfd f(20), 48+OFS_FR(r(4)) |
stfd f(21), 56+OFS_FR(r(4)) |
stfd f(22), 64+OFS_FR(r(4)) |
stfd f(23), 72+OFS_FR(r(4)) |
stfd f(24), 80+OFS_FR(r(4)) |
stfd f(25), 88+OFS_FR(r(4)) |
stfd f(26), 96+OFS_FR(r(4)) |
stfd f(27),104+OFS_FR(r(4)) |
stfd f(28),112+OFS_FR(r(4)) |
stfd f(29),120+OFS_FR(r(4)) |
stfd f(30),128+OFS_FR(r(4)) |
stfd f(31),136+OFS_FR(r(4)) |
stfd f(0), OFS_FPSCR(r(4)) |
#endif |
|
#if defined(__ALTIVEC__) |
/* ??? Determine when VRs not present. */ |
/* ??? Test r(3) for pr_hasNoVectorUpdate and skip the vr save. |
This is not yet set by the compiler. */ |
addi r(5), r(4), OFS_VR |
addi r(6), r(4), OFS_VR+16 |
mfspr r(0), VRSAVE |
stvx v(20), 0, r(5) |
addi r(5), r(5), 32 |
stvx v(21), 0, r(6) |
addi r(6), r(6), 32 |
stvx v(22), 0, r(5) |
addi r(5), r(5), 32 |
stvx v(23), 0, r(6) |
addi r(6), r(6), 32 |
stvx v(25), 0, r(5) |
addi r(5), r(5), 32 |
stvx v(26), 0, r(6) |
addi r(6), r(6), 32 |
stvx v(26), 0, r(5) |
addi r(5), r(5), 32 |
stvx v(27), 0, r(6) |
addi r(6), r(6), 32 |
stvx v(28), 0, r(5) |
addi r(5), r(5), 32 |
stvx v(29), 0, r(6) |
addi r(6), r(6), 32 |
stvx v(30), 0, r(5) |
stvx v(31), 0, r(6) |
streg r(0), OFS_VSCR(r(4)) |
#endif |
|
CALL GTM_begin_transaction |
|
ldreg r(0), LR_SAVE+FRAME(r(1)) |
mtlr r(0) |
addi r(1), r(1), FRAME |
cfi_def_cfa_offset(0) |
cfi_restore(65) |
blr |
cfi_endproc |
END _ITM_beginTransaction |
|
.align 4 |
HIDDEN GTM_longjmp |
FUNC GTM_longjmp |
cfi_startproc |
#if defined(__ALTIVEC__) || defined(__VSX__) |
/* ??? Determine when VRs not present. */ |
/* ??? Test r(5) for pr_hasNoVectorUpdate and skip the vr restore. |
This is not yet set by the compiler. */ |
addi r(6), r(4), OFS_VR |
addi r(7), r(4), OFS_VR+16 |
ldreg r(0), OFS_VSCR(r(4)) |
cfi_undefined(v(20)) |
cfi_undefined(v(21)) |
cfi_undefined(v(22)) |
cfi_undefined(v(23)) |
cfi_undefined(v(24)) |
cfi_undefined(v(25)) |
cfi_undefined(v(26)) |
cfi_undefined(v(27)) |
cfi_undefined(v(28)) |
cfi_undefined(v(29)) |
cfi_undefined(v(30)) |
cfi_undefined(v(31)) |
lvx v(20), 0, r(6) |
addi r(6), r(6), 32 |
lvx v(21), 0, r(7) |
addi r(7), r(7), 32 |
lvx v(22), 0, r(6) |
addi r(6), r(6), 32 |
lvx v(23), 0, r(7) |
addi r(7), r(7), 32 |
lvx v(24), 0, r(6) |
addi r(6), r(6), 32 |
lvx v(25), 0, r(7) |
addi r(7), r(7), 32 |
lvx v(26), 0, r(6) |
addi r(6), r(6), 32 |
lvx v(27), 0, r(7) |
addi r(7), r(7), 32 |
lvx v(28), 0, r(6) |
addi r(6), r(6), 32 |
lvx v(29), 0, r(7) |
addi r(7), r(7), 32 |
lvx v(30), 0, r(6) |
lvx v(31), 0, r(7) |
mtspr VRSAVE, r(0) |
#endif |
|
#ifndef _SOFT_FLOAT |
/* ??? Determine when FPRs not present. */ |
/* ??? Test r(5) for pr_hasNoFloatUpdate and skip the fp load. |
This is not yet set by the compiler. */ |
lfd f(0), OFS_FPSCR(r(4)) |
cfi_undefined(f(14)) |
cfi_undefined(f(15)) |
cfi_undefined(f(16)) |
cfi_undefined(f(17)) |
cfi_undefined(f(18)) |
cfi_undefined(f(19)) |
cfi_undefined(f(20)) |
cfi_undefined(f(21)) |
cfi_undefined(f(22)) |
cfi_undefined(f(23)) |
cfi_undefined(f(24)) |
cfi_undefined(f(25)) |
cfi_undefined(f(26)) |
cfi_undefined(f(27)) |
cfi_undefined(f(28)) |
cfi_undefined(f(29)) |
cfi_undefined(f(30)) |
cfi_undefined(f(31)) |
lfd f(14), 0+OFS_FR(r(4)) |
lfd f(15), 8+OFS_FR(r(4)) |
lfd f(16), 16+OFS_FR(r(4)) |
lfd f(17), 24+OFS_FR(r(4)) |
lfd f(18), 32+OFS_FR(r(4)) |
lfd f(19), 40+OFS_FR(r(4)) |
lfd f(20), 48+OFS_FR(r(4)) |
lfd f(21), 56+OFS_FR(r(4)) |
lfd f(22), 64+OFS_FR(r(4)) |
lfd f(23), 72+OFS_FR(r(4)) |
lfd f(24), 80+OFS_FR(r(4)) |
lfd f(25), 88+OFS_FR(r(4)) |
lfd f(26), 96+OFS_FR(r(4)) |
lfd f(27),104+OFS_FR(r(4)) |
lfd f(28),112+OFS_FR(r(4)) |
lfd f(29),120+OFS_FR(r(4)) |
lfd f(30),128+OFS_FR(r(4)) |
lfd f(31),136+OFS_FR(r(4)) |
mtfsf 0xff, f(0) |
#endif |
|
ldreg r(6), OFS_CFA(r(4)) |
ldreg r(0), OFS_LR(r(4)) |
#ifdef _CALL_DARWIN |
ldreg r(13), OFS_TOC(r(4)) |
#else |
ldreg r(2), OFS_TOC(r(4)) |
#endif |
ldreg r(7), OFS_CR(r(4)) |
/* At the instant we restore the LR, the only coherent view of |
the world we have is into the new stack frame. Define the |
CFA in terms of the not-yet-restored stack pointer. This will |
last until the end of the function. */ |
mtlr r(0) |
cfi_def_cfa(r(6), 0) |
cfi_undefined(r(14)) |
cfi_undefined(r(15)) |
cfi_undefined(r(16)) |
cfi_undefined(r(17)) |
cfi_undefined(r(18)) |
cfi_undefined(r(19)) |
cfi_undefined(r(20)) |
cfi_undefined(r(21)) |
cfi_undefined(r(22)) |
cfi_undefined(r(23)) |
cfi_undefined(r(24)) |
cfi_undefined(r(25)) |
cfi_undefined(r(26)) |
cfi_undefined(r(27)) |
cfi_undefined(r(28)) |
cfi_undefined(r(29)) |
cfi_undefined(r(30)) |
cfi_undefined(r(31)) |
mtcr r(7) |
ldreg r(14), 0*WS+OFS_GR(r(4)) |
ldreg r(15), 1*WS+OFS_GR(r(4)) |
ldreg r(16), 2*WS+OFS_GR(r(4)) |
ldreg r(17), 3*WS+OFS_GR(r(4)) |
ldreg r(18), 4*WS+OFS_GR(r(4)) |
ldreg r(19), 5*WS+OFS_GR(r(4)) |
ldreg r(20), 6*WS+OFS_GR(r(4)) |
ldreg r(21), 7*WS+OFS_GR(r(4)) |
ldreg r(22), 8*WS+OFS_GR(r(4)) |
ldreg r(23), 9*WS+OFS_GR(r(4)) |
ldreg r(24), 10*WS+OFS_GR(r(4)) |
ldreg r(25), 11*WS+OFS_GR(r(4)) |
ldreg r(26), 12*WS+OFS_GR(r(4)) |
ldreg r(27), 13*WS+OFS_GR(r(4)) |
ldreg r(28), 14*WS+OFS_GR(r(4)) |
ldreg r(29), 15*WS+OFS_GR(r(4)) |
ldreg r(30), 16*WS+OFS_GR(r(4)) |
ldreg r(31), 17*WS+OFS_GR(r(4)) |
mr r(1), r(6) |
blr |
cfi_endproc |
END GTM_longjmp |
|
#ifdef __linux__ |
.section .note.GNU-stack, "", @progbits |
#endif |
/powerpc/target.h
0,0 → 1,58
/* Copyright (C) 2012 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/>. */ |
|
namespace GTM HIDDEN { |
|
typedef int v128 __attribute__((vector_size(16), may_alias, aligned(16))); |
typedef struct gtm_jmpbuf |
{ |
#if defined(__ALTIVEC__) || defined(__VSX__) |
v128 vr[12]; /* vr20-vr31 */ |
unsigned long long vscr; /* long long for padding only */ |
#endif |
#ifndef _SOFT_FLOAT |
double fr[18]; /* f14-f31 */ |
double fpscr; |
#endif |
unsigned long gr[18]; /* r14-r31 */ |
void *cfa; |
unsigned long pc; |
unsigned long toc; /* r2 on aix, r13 on darwin */ |
unsigned long cr; |
} gtm_jmpbuf; |
|
/* The size of one line in hardware caches (in bytes). */ |
#if defined (__powerpc64__) || defined (__ppc64__) |
# define HW_CACHELINE_SIZE 128 |
#else |
# define HW_CACHELINE_SIZE 32 |
#endif |
|
static inline void |
cpu_relax (void) |
{ |
__asm volatile ("" : : : "memory"); |
} |
|
} // namespace GTM |
/posix/rwlock.cc
0,0 → 1,307
/* 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" |
|
namespace GTM HIDDEN { |
|
// Initialize a new RW lock. |
// ??? Move this back to the header file when constexpr is implemented. |
|
gtm_rwlock::gtm_rwlock() |
: mutex (PTHREAD_MUTEX_INITIALIZER), |
c_readers (PTHREAD_COND_INITIALIZER), |
c_writers (PTHREAD_COND_INITIALIZER), |
c_confirmed_writers (PTHREAD_COND_INITIALIZER), |
summary (0), |
a_readers (0), |
w_readers (0), |
w_writers (0) |
{ } |
|
gtm_rwlock::~gtm_rwlock() |
{ |
pthread_mutex_destroy (&this->mutex); |
pthread_cond_destroy (&this->c_readers); |
pthread_cond_destroy (&this->c_writers); |
} |
|
// Acquire a RW lock for reading. |
|
void |
gtm_rwlock::read_lock (gtm_thread *tx) |
{ |
// Fast path: first announce our intent to read, then check for conflicting |
// intents to write. The fence ensure that this happens in exactly this |
// order. |
tx->shared_state.store (0, memory_order_relaxed); |
atomic_thread_fence (memory_order_seq_cst); |
unsigned int sum = this->summary.load (memory_order_relaxed); |
if (likely(!(sum & (a_writer | w_writer)))) |
return; |
|
// There seems to be an active, waiting, or confirmed writer, so enter the |
// mutex-based slow path. To try to keep the number of readers small that |
// the writer will see, we clear our read flag right away before entering |
// the critical section. Otherwise, the writer would have to wait for us to |
// get into the critical section. (Note that for correctness, this only has |
// to happen before we leave the slow path and before we wait for any |
// writer). |
// ??? Add a barrier to enforce early visibility of this? |
tx->shared_state.store(-1, memory_order_relaxed); |
|
pthread_mutex_lock (&this->mutex); |
|
// Read summary again after acquiring the mutex because it might have |
// changed during waiting for the mutex to become free. |
sum = this->summary.load (memory_order_relaxed); |
|
// If there is a writer waiting for readers, wake it up. Only do that if we |
// might be the last reader that could do the wake-up, otherwise skip the |
// wake-up but decrease a_readers to show that we have entered the slow path. |
// This has to happen before we wait for any writers or upgraders. |
// See write_lock_generic() for further explanations. |
if (this->a_readers > 0) |
{ |
this->a_readers--; |
if (this->a_readers == 0) |
pthread_cond_signal(&this->c_confirmed_writers); |
} |
|
// If there is an active or waiting writer, we must wait. |
while (sum & (a_writer | w_writer)) |
{ |
this->summary.store (sum | w_reader, memory_order_relaxed); |
this->w_readers++; |
pthread_cond_wait (&this->c_readers, &this->mutex); |
sum = this->summary.load (memory_order_relaxed); |
if (--this->w_readers == 0) |
sum &= ~w_reader; |
} |
|
// Otherwise we can acquire the lock for read. |
tx->shared_state.store(0, memory_order_relaxed); |
|
pthread_mutex_unlock(&this->mutex); |
} |
|
|
// Acquire a RW lock for writing. Generic version that also works for |
// upgrades. |
// Note that an upgrade might fail (and thus waste previous work done during |
// this transaction) if there is another thread that tried to go into serial |
// mode earlier (i.e., upgrades do not have higher priority than pure writers). |
// However, this seems rare enough to not consider it further as we need both |
// a non-upgrade writer and a writer to happen to switch to serial mode |
// concurrently. If we'd want to handle this, a writer waiting for readers |
// would have to coordinate with later arriving upgrades and hand over the |
// lock to them, including the the reader-waiting state. We can try to support |
// this if this will actually happen often enough in real workloads. |
|
bool |
gtm_rwlock::write_lock_generic (gtm_thread *tx) |
{ |
pthread_mutex_lock (&this->mutex); |
|
unsigned int sum = this->summary.load (memory_order_relaxed); |
|
// If there is an active writer, wait. |
while (sum & a_writer) |
{ |
if (tx != 0) |
{ |
// If this is an upgrade, we must not wait for other writers or |
// upgrades that already have gone in |
pthread_mutex_unlock (&this->mutex); |
return false; |
} |
|
this->summary.store (sum | w_writer, memory_order_relaxed); |
this->w_writers++; |
pthread_cond_wait (&this->c_writers, &this->mutex); |
sum = this->summary.load (memory_order_relaxed); |
if (--this->w_writers == 0) |
sum &= ~w_writer; |
} |
|
// Otherwise we can acquire the lock for write. As a writer, we have |
// priority, so we don't need to take this back. |
this->summary.store (sum | a_writer, memory_order_relaxed); |
|
// We still need to wait for active readers to finish. The barrier makes |
// sure that we first set our write intent and check for active readers |
// after that, in strictly this order (similar to the barrier in the fast |
// path of read_lock()). |
atomic_thread_fence(memory_order_seq_cst); |
|
// Count the number of active readers to be able to decrease the number of |
// wake-ups and wait calls that are necessary. |
// |
// This number is an upper bound of the number of readers that actually |
// are still active and which we need to wait for: |
// - We set our write flag before checking the reader flags, and readers |
// check our write flag after clearing their read flags in read_unlock(). |
// Therefore, they will enter the slow path whenever we have seen them. |
// - Readers will have cleared their read flags before leaving the slow |
// path in read_lock() (prevents lost wake-ups), and before waiting for |
// any writer (prevents deadlocks). |
// |
// However, this number is also just a lower bound of the number of readers |
// that will actually enter the slow path in read_unlock() or read_lock(): |
// - Because the read flag is cleared outside of a critical section, writers |
// can see it as cleared while the reader still goes into the slow path. |
// |
// Therefore, readers can skip (lower bound - 1) wake-ups, but we do need |
// the following loop to check that the readers that we wanted to wait for |
// are actually those that entered the slow path so far (and either skipped |
// or sent a wake-up). |
// |
// ??? Do we need to optimize further? (The writer could publish a list of |
// readers that it suspects to be active. Readers could check this list and |
// only decrement a_readers if they are in this list.) |
for (;;) |
{ |
// ??? Keep a list of active readers that we saw and update it on the |
// next retry instead? This might reduce the number of cache misses that |
// we get when checking reader flags. |
int readers = 0; |
for (gtm_thread *it = gtm_thread::list_of_threads; it != 0; |
it = it->next_thread) |
{ |
// Don't count ourself if this is an upgrade. |
if (it == tx) |
continue; |
if (it->shared_state.load(memory_order_relaxed) != (gtm_word)-1) |
readers++; |
} |
|
// If we have not seen any readers, we will not wait. |
if (readers == 0) |
break; |
|
// We've seen a number of readers, so we publish this number and wait. |
this->a_readers = readers; |
pthread_cond_wait (&this->c_confirmed_writers, &this->mutex); |
} |
|
pthread_mutex_unlock (&this->mutex); |
return true; |
} |
|
// Acquire a RW lock for writing. |
|
void |
gtm_rwlock::write_lock () |
{ |
write_lock_generic (0); |
} |
|
|
// Upgrade a RW lock that has been locked for reading to a writing lock. |
// Do this without possibility of another writer incoming. Return false |
// if this attempt fails (i.e. another thread also upgraded). |
|
bool |
gtm_rwlock::write_upgrade (gtm_thread *tx) |
{ |
return write_lock_generic (tx); |
} |
|
|
// Has to be called iff the previous upgrade was successful and after it is |
// safe for the transaction to not be marked as a reader anymore. |
|
void |
gtm_rwlock::write_upgrade_finish (gtm_thread *tx) |
{ |
// We are not a reader anymore. This is only safe to do after we have |
// acquired the writer lock. |
tx->shared_state.store (-1, memory_order_release); |
} |
|
|
// Release a RW lock from reading. |
|
void |
gtm_rwlock::read_unlock (gtm_thread *tx) |
{ |
// We only need release memory order here because of privatization safety |
// (this ensures that marking the transaction as inactive happens after |
// any prior data accesses by this transaction, and that neither the |
// compiler nor the hardware order this store earlier). |
// ??? We might be able to avoid this release here if the compiler can't |
// merge the release fence with the subsequent seq_cst fence. |
tx->shared_state.store (-1, memory_order_release); |
// We need this seq_cst fence here to avoid lost wake-ups. Furthermore, |
// the privatization safety implementation in gtm_thread::try_commit() |
// relies on the existence of this seq_cst fence. |
atomic_thread_fence (memory_order_seq_cst); |
unsigned int sum = this->summary.load (memory_order_relaxed); |
if (likely(!(sum & (a_writer | w_writer)))) |
return; |
|
// There is a writer, either active or waiting for other readers or writers. |
// Thus, enter the mutex-based slow path. |
pthread_mutex_lock (&this->mutex); |
|
// If there is a writer waiting for readers, wake it up. Only do that if we |
// might be the last reader that could do the wake-up, otherwise skip the |
// wake-up and decrease a_readers to publish that we have entered the slow |
// path but skipped the wake-up. |
if (this->a_readers > 0) |
{ |
this->a_readers--; |
if (this->a_readers == 0) |
pthread_cond_signal(&this->c_confirmed_writers); |
} |
|
// We don't need to wake up any writers waiting for other writers. Active |
// writers will take care of that. |
|
pthread_mutex_unlock (&this->mutex); |
} |
|
|
// Release a RW lock from writing. |
|
void |
gtm_rwlock::write_unlock () |
{ |
pthread_mutex_lock (&this->mutex); |
|
unsigned int sum = this->summary.load (memory_order_relaxed); |
this->summary.store (sum & ~a_writer, memory_order_relaxed); |
|
// If there is a waiting writer, wake it. |
if (unlikely (sum & w_writer)) |
pthread_cond_signal (&this->c_writers); |
|
// If there are waiting readers, wake them. |
else if (unlikely (sum & w_reader)) |
pthread_cond_broadcast (&this->c_readers); |
|
pthread_mutex_unlock (&this->mutex); |
} |
|
} // namespace GTM |
/posix/rwlock.h
0,0 → 1,83
/* 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/>. */ |
|
#ifndef GTM_RWLOCK_H |
#define GTM_RWLOCK_H |
|
#include <pthread.h> |
#include "local_atomic" |
|
namespace GTM HIDDEN { |
|
struct gtm_thread; |
|
// This datastructure is the blocking, mutex-based side of the Dekker-style |
// reader-writer lock used to provide mutual exclusion between active and |
// serial transactions. It has similarities to POSIX pthread_rwlock_t except |
// that we also provide for upgrading a reader->writer lock, with a |
// positive indication of failure (another writer acquired the lock |
// before we were able to acquire). While the writer flag (a_writer below) is |
// global and protected by the mutex, there are per-transaction reader flags, |
// which are stored in a transaction's shared state. |
// See libitm's documentation for further details. |
// |
// In this implementation, writers are given highest priority access but |
// read-to-write upgrades do not have a higher priority than writers. |
|
class gtm_rwlock |
{ |
pthread_mutex_t mutex; // Held if manipulating any field. |
pthread_cond_t c_readers; // Readers wait here |
pthread_cond_t c_writers; // Writers wait here for writers |
pthread_cond_t c_confirmed_writers; // Writers wait here for readers |
|
static const unsigned a_writer = 1; // An active writer. |
static const unsigned w_writer = 2; // The w_writers field != 0 |
static const unsigned w_reader = 4; // The w_readers field != 0 |
|
std::atomic<unsigned int> summary; // Bitmask of the above. |
unsigned int a_readers; // Nr active readers as observed by a writer |
unsigned int w_readers; // Nr waiting readers |
unsigned int w_writers; // Nr waiting writers |
|
public: |
gtm_rwlock(); |
~gtm_rwlock(); |
|
void read_lock (gtm_thread *tx); |
void read_unlock (gtm_thread *tx); |
|
void write_lock (); |
void write_unlock (); |
|
bool write_upgrade (gtm_thread *tx); |
void write_upgrade_finish (gtm_thread *tx); |
|
protected: |
bool write_lock_generic (gtm_thread *tx); |
}; |
|
} // namespace GTM |
|
#endif // GTM_RWLOCK_H |
/alpha/cacheline.h
0,0 → 1,38
/* 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/>. */ |
|
#ifndef LIBITM_ALPHA_CACHELINE_H |
#define LIBITM_ALPHA_CACHELINE_H 1 |
|
// A cacheline is the smallest unit with which locks are associated. |
// The current implementation of the _ITM_[RW] barriers assumes that |
// all data types can fit (aligned) within a cachline, which means |
// in practice sizeof(complex long double) is the smallest cacheline size. |
// It ought to be small enough for efficient manipulation of the |
// modification mask, below. |
#define CACHELINE_SIZE 64 |
|
#include "config/generic/cacheline.h" |
|
#endif // LIBITM_ALPHA_CACHELINE_H |
/alpha/sjlj.S
0,0 → 1,112
/* 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/>. */ |
|
.text |
.align 4 |
.globl _ITM_beginTransaction |
.ent _ITM_beginTransaction |
|
#define FRAME 144 |
|
_ITM_beginTransaction: |
ldgp $29, 0($27) |
subq $30, FRAME, $30 |
.frame $30, FRAME, $26, 0 |
.mask 0x04000000, 0 |
stq $26, 0($30) |
.prologue 1 |
|
stq $9, 8($30) |
stq $10, 16($30) |
addq $30, FRAME, $0 |
stq $11, 24($30) |
|
stq $12, 32($30) |
stq $13, 40($30) |
stq $14, 48($30) |
stq $15, 56($30) |
|
stq $0, 64($30) |
stt $f2, 72($30) |
stt $f3, 80($30) |
stt $f4, 88($30) |
|
stt $f5, 96($30) |
stt $f6, 104($30) |
stt $f7, 112($30) |
stt $f8, 120($30) |
|
stt $f9, 128($30) |
mov $30, $17 |
#ifdef __PIC__ |
unop |
bsr $26, GTM_begin_transaction !samegp |
#else |
jsr $26, GTM_begin_transaction |
ldgp $29, 0($26) |
#endif |
|
ldq $26, 0($30) |
addq $30, FRAME, $30 |
ret |
.end _ITM_beginTransaction |
|
.align 4 |
.globl GTM_longjmp |
#ifdef __ELF__ |
.hidden GTM_longjmp |
#endif |
.ent GTM_longjmp |
|
GTM_longjmp: |
.prologue 0 |
ldq $26, 0($17) |
ldq $9, 8($17) |
ldq $10, 16($17) |
ldq $11, 24($17) |
|
ldq $12, 32($17) |
ldq $13, 40($17) |
ldq $14, 48($17) |
ldq $15, 56($17) |
|
ldq $1, 64($17) |
ldt $f2, 72($17) |
ldt $f3, 80($17) |
ldt $f4, 88($17) |
|
ldt $f5, 96($17) |
ldt $f6, 104($17) |
ldt $f7, 112($17) |
ldt $f8, 120($17) |
|
ldt $f9, 128($17) |
mov $16, $0 |
mov $1, $30 |
ret |
.end GTM_longjmp |
|
#ifdef __linux__ |
.section .note.GNU-stack, "", @progbits |
#endif |
/alpha/target.h
0,0 → 1,48
/* 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/>. */ |
|
namespace GTM HIDDEN { |
|
typedef struct gtm_jmpbuf |
{ |
unsigned long pc; |
unsigned long s[7]; |
void *cfa; |
unsigned long f[8]; |
} gtm_jmpbuf; |
|
/* Alpha generally uses a fixed page size of 8K. */ |
#define PAGE_SIZE 8192 |
#define FIXED_PAGE_SIZE 1 |
|
/* The size of one line in hardware caches (in bytes). */ |
#define HW_CACHELINE_SIZE 64 |
|
static inline void |
cpu_relax (void) |
{ |
__asm volatile ("" : : : "memory"); |
} |
|
} // namespace GTM |
/x86/cacheline.h
0,0 → 1,125
/* 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/>. */ |
|
#ifndef LIBITM_CACHELINE_H |
#define LIBITM_CACHELINE_H 1 |
|
// Minimum cacheline size is 32, due to both complex long double and __m256. |
// There's no requirement that 64-bit use a 64-byte cacheline size, but do |
// so for now to make sure everything is parameterized properly. |
#ifdef __x86_64__ |
# define CACHELINE_SIZE 64 |
#else |
# define CACHELINE_SIZE 32 |
#endif |
|
namespace GTM HIDDEN { |
|
// A gtm_cacheline_mask stores a modified bit for every modified byte |
// in the cacheline with which it is associated. |
typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask; |
|
union gtm_cacheline |
{ |
// Byte access to the cacheline. |
unsigned char b[CACHELINE_SIZE] __attribute__((aligned(CACHELINE_SIZE))); |
|
// Larger sized access to the cacheline. |
uint16_t u16[CACHELINE_SIZE / sizeof(uint16_t)]; |
uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)]; |
uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)]; |
gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)]; |
|
#ifdef __MMX__ |
__m64 m64[CACHELINE_SIZE / sizeof(__m64)]; |
#endif |
#ifdef __SSE__ |
__m128 m128[CACHELINE_SIZE / sizeof(__m128)]; |
#endif |
#ifdef __SSE2__ |
__m128i m128i[CACHELINE_SIZE / sizeof(__m128i)]; |
#endif |
#ifdef __AVX__ |
__m256 m256[CACHELINE_SIZE / sizeof(__m256)]; |
__m256i m256i[CACHELINE_SIZE / sizeof(__m256i)]; |
#endif |
|
#if defined(__SSE__) || defined(__AVX__) |
// Copy S to D; only bother defining if we can do this more efficiently |
// than the compiler-generated default implementation. |
gtm_cacheline& operator= (const gtm_cacheline &s); |
#endif // SSE, AVX |
}; |
|
#if defined(__SSE__) || defined(__AVX__) |
inline gtm_cacheline& ALWAYS_INLINE |
gtm_cacheline::operator= (const gtm_cacheline & __restrict s) |
{ |
#ifdef __AVX__ |
# define CP m256 |
# define TYPE __m256 |
#else |
# define CP m128 |
# define TYPE __m128 |
#endif |
|
TYPE w, x, y, z; |
|
// ??? Wouldn't it be nice to have a pragma to tell the compiler |
// to completely unroll a given loop? |
switch (CACHELINE_SIZE / sizeof(TYPE)) |
{ |
case 1: |
this->CP[0] = s.CP[0]; |
break; |
case 2: |
x = s.CP[0]; |
y = s.CP[1]; |
this->CP[0] = x; |
this->CP[1] = y; |
break; |
case 4: |
w = s.CP[0]; |
x = s.CP[1]; |
y = s.CP[2]; |
z = s.CP[3]; |
this->CP[0] = w; |
this->CP[1] = x; |
this->CP[2] = y; |
this->CP[3] = z; |
break; |
default: |
__builtin_trap (); |
} |
|
return *this; |
|
#undef CP |
#undef TYPE |
} |
#endif |
|
} // namespace GTM |
|
#endif // LIBITM_CACHELINE_H |
/x86/x86_sse.cc
0,0 → 1,43
/* 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" |
#include "dispatch.h" |
|
// ??? Use memcpy for now, until we have figured out how to best instantiate |
// these loads/stores. |
CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M64, GTM::abi_disp()->, ) |
CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M128, GTM::abi_disp()->, ) |
|
void ITM_REGPARM |
_ITM_LM64 (const _ITM_TYPE_M64 *ptr) |
{ |
GTM::GTM_LB (ptr, sizeof (*ptr)); |
} |
|
void ITM_REGPARM |
_ITM_LM128 (const _ITM_TYPE_M128 *ptr) |
{ |
GTM::GTM_LB (ptr, sizeof (*ptr)); |
} |
/x86/sjlj.S
0,0 → 1,148
/* 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 "asmcfi.h" |
|
#define CONCAT1(a, b) CONCAT2(a, b) |
#define CONCAT2(a, b) a ## b |
|
#ifdef __USER_LABEL_PREFIX__ |
# define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x) |
#else |
# define SYM(x) x |
#endif |
|
#ifdef __ELF__ |
# define TYPE(x) .type SYM(x), @function |
# define SIZE(x) .size SYM(x), . - SYM(x) |
# ifdef HAVE_ATTRIBUTE_VISIBILITY |
# define HIDDEN(x) .hidden SYM(x) |
# else |
# define HIDDEN(x) |
# endif |
#else |
# define TYPE(x) |
# define SIZE(x) |
# ifdef __MACH__ |
# define HIDDEN(x) .private_extern SYM(x) |
# else |
# define HIDDEN(x) |
# endif |
#endif |
|
.text |
|
.align 4 |
.globl SYM(_ITM_beginTransaction) |
|
SYM(_ITM_beginTransaction): |
cfi_startproc |
#ifdef __x86_64__ |
leaq 8(%rsp), %rax |
subq $56, %rsp |
cfi_def_cfa_offset(64) |
movq %rax, (%rsp) |
movq %rbx, 8(%rsp) |
movq %rbp, 16(%rsp) |
movq %r12, 24(%rsp) |
movq %r13, 32(%rsp) |
movq %r14, 40(%rsp) |
movq %r15, 48(%rsp) |
movq %rsp, %rsi |
call SYM(GTM_begin_transaction) |
addq $56, %rsp |
cfi_def_cfa_offset(8) |
ret |
#else |
leal 4(%esp), %ecx |
movl 4(%esp), %eax |
subl $28, %esp |
cfi_def_cfa_offset(32) |
movl %ecx, 8(%esp) |
movl %ebx, 12(%esp) |
movl %esi, 16(%esp) |
movl %edi, 20(%esp) |
movl %ebp, 24(%esp) |
leal 8(%esp), %edx |
#if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__ |
call SYM(GTM_begin_transaction) |
#elif defined __ELF__ |
call 1f |
1: popl %ebx |
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx |
call SYM(GTM_begin_transaction)@PLT |
movl 12(%esp), %ebx |
#else |
# error "Unsupported PIC sequence" |
#endif |
addl $28, %esp |
cfi_def_cfa_offset(4) |
ret |
#endif |
cfi_endproc |
|
TYPE(_ITM_beginTransaction) |
SIZE(_ITM_beginTransaction) |
|
.align 4 |
.globl SYM(GTM_longjmp) |
|
SYM(GTM_longjmp): |
cfi_startproc |
#ifdef __x86_64__ |
movq (%rsi), %rcx |
movq 8(%rsi), %rbx |
movq 16(%rsi), %rbp |
movq 24(%rsi), %r12 |
movq 32(%rsi), %r13 |
movq 40(%rsi), %r14 |
movq 48(%rsi), %r15 |
movl %edi, %eax |
cfi_def_cfa(%rsi, 0) |
cfi_offset(%rip, 56) |
cfi_register(%rsp, %rcx) |
movq %rcx, %rsp |
jmp *56(%rsi) |
#else |
movl (%edx), %ecx |
movl 4(%edx), %ebx |
movl 8(%edx), %esi |
movl 12(%edx), %edi |
movl 16(%edx), %ebp |
cfi_def_cfa(%edx, 0) |
cfi_offset(%eip, 20) |
cfi_register(%esp, %ecx) |
movl %ecx, %esp |
jmp *20(%edx) |
#endif |
cfi_endproc |
|
TYPE(GTM_longjmp) |
HIDDEN(GTM_longjmp) |
SIZE(GTM_longjmp) |
|
#ifdef __linux__ |
.section .note.GNU-stack, "", @progbits |
#endif |
/x86/x86_avx.cc
0,0 → 1,91
/* 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 "config.h" |
|
#include "libitm_i.h" |
#include "dispatch.h" |
|
extern "C" { |
|
#ifndef HAVE_AS_AVX |
// If we don't have an AVX capable assembler, we didn't set -mavx on the |
// command-line either, which means that libitm.h defined neither this type |
// nor the functions in this file. Define the type and unconditionally |
// wrap the file in extern "C" to make up for the lack of pre-declaration. |
typedef float _ITM_TYPE_M256 __attribute__((vector_size(32), may_alias)); |
#endif |
|
// Re-define the memcpy implementations so that we can frob the |
// interface to deal with possibly missing AVX instruction set support. |
|
#ifdef HAVE_AS_AVX |
#define RETURN(X) return X |
#define STORE(X,Y) X = Y |
#define OUTPUT(T) _ITM_TYPE_##T |
#define INPUT(T,X) , _ITM_TYPE_##T X |
#else |
/* Emit vmovaps (%rax),%ymm0. */ |
#define RETURN(X) \ |
asm volatile(".byte 0xc5,0xfc,0x28,0x00" : "=m"(X) : "a"(&X)) |
/* Emit vmovaps %ymm0,(%rax); vzeroupper. */ |
#define STORE(X,Y) \ |
asm volatile(".byte 0xc5,0xfc,0x29,0x00,0xc5,0xf8,0x77" : "=m"(X) : "a"(&X)) |
#define OUTPUT(T) void |
#define INPUT(T,X) |
#endif |
|
#undef ITM_READ_MEMCPY |
#define ITM_READ_MEMCPY(T, LSMOD, TARGET, M2) \ |
OUTPUT(T) ITM_REGPARM _ITM_##LSMOD##T (const _ITM_TYPE_##T *ptr) \ |
{ \ |
_ITM_TYPE_##T v; \ |
TARGET memtransfer##M2(&v, ptr, sizeof(_ITM_TYPE_##T), false, \ |
GTM::abi_dispatch::NONTXNAL, \ |
GTM::abi_dispatch::LSMOD); \ |
RETURN(v); \ |
} |
|
#undef ITM_WRITE_MEMCPY |
#define ITM_WRITE_MEMCPY(T, LSMOD, TARGET, M2) \ |
void ITM_REGPARM _ITM_##LSMOD##T (_ITM_TYPE_##T *ptr INPUT(T,in)) \ |
{ \ |
_ITM_TYPE_##T v; \ |
STORE(v, in); \ |
TARGET memtransfer##M2(ptr, &v, sizeof(_ITM_TYPE_##T), false, \ |
GTM::abi_dispatch::LSMOD, \ |
GTM::abi_dispatch::NONTXNAL); \ |
} |
|
// ??? Use memcpy for now, until we have figured out how to best instantiate |
// these loads/stores. |
CREATE_DISPATCH_FUNCTIONS_T_MEMCPY(M256, GTM::abi_disp()->, ) |
|
void ITM_REGPARM |
_ITM_LM256 (const _ITM_TYPE_M256 *ptr) |
{ |
GTM::GTM_LB (ptr, sizeof (*ptr)); |
} |
|
} // extern "C" |
/x86/target.h
0,0 → 1,84
/* 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/>. */ |
|
namespace GTM HIDDEN { |
|
#ifdef __x86_64__ |
/* ??? This doesn't work for Win64. */ |
typedef struct gtm_jmpbuf |
{ |
void *cfa; |
unsigned long rbx; |
unsigned long rbp; |
unsigned long r12; |
unsigned long r13; |
unsigned long r14; |
unsigned long r15; |
unsigned long rip; |
} gtm_jmpbuf; |
#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 |
|
/* x86 doesn't require strict alignment for the basic types. */ |
#define STRICT_ALIGNMENT 0 |
|
/* x86 uses a fixed page size of 4K. */ |
#define PAGE_SIZE 4096 |
#define FIXED_PAGE_SIZE 1 |
|
/* The size of one line in hardware caches (in bytes). */ |
#define HW_CACHELINE_SIZE 64 |
|
|
static inline void |
cpu_relax (void) |
{ |
__asm volatile ("rep; nop" : : : "memory"); |
} |
|
} // namespace GTM |
|
// We'll be using some of the cpu builtins, and their associated types. |
#ifndef __cplusplus |
/* ??? It's broken for C++. */ |
#include <x86intrin.h> |
#else |
# ifdef __SSE2__ |
# include <emmintrin.h> |
# elif defined(__SSE__) |
# include <xmmintrin.h> |
# endif |
# ifdef __AVX__ |
# include <immintrin.h> |
# endif |
#endif |
/sparc/cacheline.h
0,0 → 1,41
/* Copyright (C) 2012 Free Software Foundation, Inc. |
|
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_SPARC_CACHELINE_H |
#define LIBITM_SPARC_CACHELINE_H 1 |
|
// A cacheline is the smallest unit with which locks are associated. |
// The current implementation of the _ITM_[RW] barriers assumes that |
// all data types can fit (aligned) within a cachline, which means |
// in practice sizeof(complex long double) is the smallest cacheline size. |
// It ought to be small enough for efficient manipulation of the |
// modification mask, below. |
#ifdef __arch64__ |
# define CACHELINE_SIZE 64 |
#else |
# define CACHELINE_SIZE 32 |
#endif |
|
#include "config/generic/cacheline.h" |
|
#endif // LIBITM_SPARC_CACHELINE_H |
/sparc/sjlj.S
0,0 → 1,97
/* Copyright (C) 2012 Free Software Foundation, Inc. |
|
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 "asmcfi.h" |
|
#ifdef __arch64__ |
# define WORD_SIZE 8 |
# define MIN_FRAME_SIZE 176 |
# define STACK_BIAS 2047 |
# define load ldx |
# define store stx |
#else |
# define WORD_SIZE 4 |
# define MIN_FRAME_SIZE 96 |
# define STACK_BIAS 0 |
# define load ld |
# define store st |
#endif |
|
/* Fields of the JmpBuf structure. */ |
#define JB_CFA 0 |
#define JB_PC 1 |
#define OFFSET(FIELD) ((FIELD) * WORD_SIZE) |
|
/* The frame size must be a multiple of the double-word size. */ |
#define FRAME_SIZE (MIN_FRAME_SIZE + 2 * WORD_SIZE) |
#define JB_OFFSET (STACK_BIAS + MIN_FRAME_SIZE) |
|
.text |
.align 4 |
.globl _ITM_beginTransaction |
.type _ITM_beginTransaction, #function |
.proc 016 |
_ITM_beginTransaction: |
cfi_startproc |
add %sp, STACK_BIAS, %g1 |
sub %sp, FRAME_SIZE, %sp |
cfi_def_cfa_offset(STACK_BIAS + FRAME_SIZE) |
store %g1, [%sp + JB_OFFSET + OFFSET (JB_CFA)] |
store %o7, [%sp + JB_OFFSET + OFFSET (JB_PC)] |
/* ??? This triggers an internal error in GDB. */ |
cfi_offset(%o7, -WORD_SIZE) |
call GTM_begin_transaction |
add %sp, JB_OFFSET, %o1 |
load [%sp + JB_OFFSET + OFFSET (JB_PC)], %o7 |
jmp %o7+8 |
add %sp, FRAME_SIZE, %sp |
cfi_def_cfa_offset(STACK_BIAS) |
cfi_endproc |
.size _ITM_beginTransaction, . - _ITM_beginTransaction |
|
.align 4 |
.globl GTM_longjmp |
#ifdef HAVE_ATTRIBUTE_VISIBILITY |
.hidden GTM_longjmp |
#endif |
.type GTM_longjmp, #function |
.proc 016 |
GTM_longjmp: |
cfi_startproc |
flushw |
#if STACK_BIAS |
load [%o1 + OFFSET (JB_CFA)], %g1 |
sub %g1, STACK_BIAS, %fp |
#else |
load [%o1 + OFFSET (JB_CFA)], %fp |
#endif |
cfi_def_cfa(%fp, STACK_BIAS) |
load [%o1 + OFFSET (JB_PC)], %o7 |
jmp %o7+8 |
restore %g0, %o0, %o0 |
cfi_endproc |
.size GTM_longjmp, . - GTM_longjmp |
|
#ifdef __linux__ |
.section .note.GNU-stack, "", @progbits |
#endif |
/sparc/target.h
0,0 → 1,46
/* Copyright (C) 2012 Free Software Foundation, Inc. |
|
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/>. */ |
|
namespace GTM HIDDEN { |
|
typedef struct gtm_jmpbuf |
{ |
void *cfa; |
unsigned long pc; |
} gtm_jmpbuf; |
|
/* UltraSPARC processors generally use a fixed page size of 8K. */ |
#define PAGE_SIZE 8192 |
#define FIXED_PAGE_SIZE 1 |
|
/* The size of one line in hardware caches (in bytes). We use the primary |
cache line size documented for the UltraSPARC T1/T2. */ |
#define HW_CACHELINE_SIZE 16 |
|
static inline void |
cpu_relax (void) |
{ |
__asm volatile ("rd %%ccr, %%g0" : : : "memory"); |
} |
|
} // namespace GTM |
/sh/sjlj.S
0,0 → 1,122
/* Copyright (C) 2011 Free Software Foundation, Inc. |
|
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 "asmcfi.h" |
|
.text |
.align 2 |
.global _ITM_beginTransaction |
.type _ITM_beginTransaction, %function |
|
_ITM_beginTransaction: |
cfi_startproc |
mov r15, r1 |
#ifdef __SH_FPU_ANY__ |
fmov.s fr15, @-r15 |
fmov.s fr14, @-r15 |
fmov.s fr13, @-r15 |
fmov.s fr12, @-r15 |
sts.l fpscr, @-r15 |
#endif /* __SH_FPU_ANY__ */ |
stc.l gbr, @-r15 |
sts.l pr, @-r15 |
mov.l r1, @-r15 |
mov.l r14, @-r15 |
mov.l r13, @-r15 |
mov.l r12, @-r15 |
mov.l r11, @-r15 |
mov.l r10, @-r15 |
mov.l r9, @-r15 |
mov.l r8, @-r15 |
#ifdef __SH_FPU_ANY__ |
cfi_def_cfa_offset (4*15) |
#else |
cfi_def_cfa_offset (4*10) |
#endif |
#if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__ |
mov.l .Lbegin, r1 |
jsr @r1 |
mov r15, r5 |
#else |
mova .Lgot, r0 |
mov.l .Lgot, r12 |
add r0, r12 |
mov.l .Lbegin, r1 |
bsrf r1 |
mov r15, r5 |
.Lbegin0: |
mov.l @(4*4,r15), r12 |
#endif |
mov.l @(8*4,r15), r1 |
lds r1, pr |
#ifdef __SH_FPU_ANY__ |
add #(15*4), r15 |
#else |
add #(10*5), r15 |
#endif |
cfi_def_cfa_offset (0) |
rts |
nop |
cfi_endproc |
|
.align 2 |
.Lgot: |
.long _GLOBAL_OFFSET_TABLE_ |
.Lbegin: |
#if defined HAVE_ATTRIBUTE_VISIBILITY || !defined __PIC__ |
.long GTM_begin_transaction |
#else |
.long GTM_begin_transaction@PLT-(.Lbegin0-.) |
#endif |
.size _ITM_beginTransaction, . - _ITM_beginTransaction |
|
.global GTM_longjmp |
.hidden GTM_longjmp |
.type GTM_longjmp, %function |
|
GTM_longjmp: |
mov.l @r5+, r8 |
mov.l @r5+, r9 |
mov.l @r5+, r10 |
mov.l @r5+, r11 |
mov.l @r5+, r12 |
mov.l @r5+, r13 |
mov.l @r5+, r14 |
mov.l @r5+, r15 |
lds.l @r5+, pr |
ldc.l @r5+, gbr |
#ifdef __SH_FPU_ANY__ |
lds.l @r5+, fpscr |
fmov.s @r5+, fr12 |
fmov.s @r5+, fr13 |
fmov.s @r5+, fr14 |
fmov.s @r5+, fr15 |
#endif |
rts |
mov r4, r0 |
|
.size GTM_longjmp, . - GTM_longjmp |
|
#ifdef __linux__ |
.section .note.GNU-stack, "", %progbits |
#endif |
/sh/target.h
0,0 → 1,51
/* Copyright (C) 2011 Free Software Foundation, Inc. |
|
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/>. */ |
|
namespace GTM HIDDEN { |
|
typedef struct gtm_jmpbuf |
{ |
unsigned long s[7]; /* r8-r14 */ |
void *cfa; |
unsigned long pc; |
unsigned long gbr; |
#ifdef __SH_FPU_ANY__ |
unsigned long fpscr; |
unsigned long f[4]; /* fr12-fr15 */ |
#endif |
} gtm_jmpbuf; |
|
/* SH generally uses a fixed page size of 4K. */ |
#define PAGE_SIZE 4096 |
#define FIXED_PAGE_SIZE 1 |
|
/* ??? The size of one line in hardware caches (in bytes). */ |
#define HW_CACHELINE_SIZE 32 |
|
static inline void |
cpu_relax (void) |
{ |
__asm volatile ("" : : : "memory"); |
} |
|
} // namespace GTM |
/generic/cacheline.h
0,0 → 1,58
/* 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/>. */ |
|
#ifndef LIBITM_CACHELINE_H |
#define LIBITM_CACHELINE_H 1 |
|
namespace GTM HIDDEN { |
|
// A cacheline is the smallest unit with which locks are associated. |
// The current implementation of the _ITM_[RW] barriers assumes that |
// all data types can fit (aligned) within a cachline, which means |
// in practice sizeof(complex long double) is the smallest cacheline size. |
// It ought to be small enough for efficient manipulation of the |
// modification mask, below. |
#ifndef CACHELINE_SIZE |
# define CACHELINE_SIZE 32 |
#endif |
|
// A gtm_cacheline_mask stores a modified bit for every modified byte |
// in the cacheline with which it is associated. |
typedef sized_integral<CACHELINE_SIZE / 8>::type gtm_cacheline_mask; |
|
union gtm_cacheline |
{ |
// Byte access to the cacheline. |
unsigned char b[CACHELINE_SIZE] __attribute__((aligned(CACHELINE_SIZE))); |
|
// Larger sized access to the cacheline. |
uint16_t u16[CACHELINE_SIZE / sizeof(uint16_t)]; |
uint32_t u32[CACHELINE_SIZE / sizeof(uint32_t)]; |
uint64_t u64[CACHELINE_SIZE / sizeof(uint64_t)]; |
gtm_word w[CACHELINE_SIZE / sizeof(gtm_word)]; |
}; |
|
} // namespace GTM |
|
#endif // LIBITM_CACHELINE_H |
/generic/tls.cc
0,0 → 1,40
/* Copyright (C) 2010, 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 { |
|
#if !defined(HAVE_ARCH_GTM_THREAD) || !defined(HAVE_ARCH_GTM_THREAD_DISP) |
__thread gtm_thread_tls _gtm_thr_tls; |
#endif |
|
// See tls.h for comments. |
void * __attribute__((noinline)) |
mask_stack_bottom(gtm_thread *tx) |
{ |
return (uint8_t*)__builtin_dwarf_cfa() - 256; |
} |
|
} // namespace GTM |
/generic/asmcfi.h
0,0 → 1,53
/* Copyright (C) 2011, 2012 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 "config.h" |
|
#ifdef HAVE_AS_CFI_PSEUDO_OP |
|
#define cfi_startproc .cfi_startproc |
#define cfi_endproc .cfi_endproc |
#define cfi_adjust_cfa_offset(n) .cfi_adjust_cfa_offset n |
#define cfi_def_cfa_offset(n) .cfi_def_cfa_offset n |
#define cfi_def_cfa(r,n) .cfi_def_cfa r, n |
#define cfi_rel_offset(r,o) .cfi_rel_offset r, o |
#define cfi_register(o,n) .cfi_register o, n |
#define cfi_offset(r,o) .cfi_offset r, o |
#define cfi_restore(r) .cfi_restore r |
#define cfi_undefined(r) .cfi_undefined r |
|
#else |
|
#define cfi_startproc |
#define cfi_endproc |
#define cfi_adjust_cfa_offset(n) |
#define cfi_def_cfa_offset(n) |
#define cfi_def_cfa(r,n) |
#define cfi_rel_offset(r,o) |
#define cfi_register(o,n) |
#define cfi_offset(r,o) |
#define cfi_restore(r) |
#define cfi_undefined(r) |
|
#endif /* HAVE_AS_CFI_PSEUDO_OP */ |
/generic/tls.h
0,0 → 1,82
/* 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/>. */ |
|
#ifndef LIBITM_TLS_H |
#define LIBITM_TLS_H 1 |
|
namespace GTM HIDDEN { |
|
#if !defined(HAVE_ARCH_GTM_THREAD) || !defined(HAVE_ARCH_GTM_THREAD_DISP) |
// Provides a single place to store all this libraries thread-local data. |
struct gtm_thread_tls |
{ |
#ifndef HAVE_ARCH_GTM_THREAD |
// The currently active transaction. Elided if the target provides |
// some efficient mechanism for storing this. |
gtm_thread *thr; |
#endif |
#ifndef HAVE_ARCH_GTM_THREAD_DISP |
// The dispatch table for the STM implementation currently in use. Elided |
// if the target provides some efficient mechanism for storing this. |
abi_dispatch *disp; |
#endif |
}; |
|
extern __thread gtm_thread_tls _gtm_thr_tls; |
#endif |
|
#ifndef HAVE_ARCH_GTM_THREAD |
// If the target does not provide optimized access to the thread-local |
// data, simply access the TLS variable defined above. |
static inline gtm_thread *gtm_thr() { return _gtm_thr_tls.thr; } |
static inline void set_gtm_thr(gtm_thread *x) { _gtm_thr_tls.thr = x; } |
#endif |
|
#ifndef HAVE_ARCH_GTM_THREAD_DISP |
// If the target does not provide optimized access to the currently |
// active dispatch table, simply access via GTM_THR. |
static inline abi_dispatch * abi_disp() { return _gtm_thr_tls.disp; } |
static inline void set_abi_disp(abi_dispatch *x) { _gtm_thr_tls.disp = x; } |
#endif |
|
#ifndef HAVE_ARCH_GTM_MASK_STACK |
// To filter out any updates that overlap the libitm stack, we define |
// gtm_mask_stack_top to the entry point to the library and |
// gtm_mask_stack_bottom to below the calling function (enforced with the |
// noinline attribute). This definition should be fine for all |
// stack-grows-down architectures. |
// FIXME We fake the bottom to be lower so that we are safe even if we might |
// call further functions (compared to where we called gtm_mask_stack_bottom |
// in the call hierarchy) to actually undo or redo writes (e.g., memcpy). |
// This is a completely arbitrary value; can we instead ensure that there are |
// no such calls, or can we determine a future-proof value otherwise? |
static inline void * |
mask_stack_top(gtm_thread *tx) { return tx->jb.cfa; } |
void * __attribute__((noinline)) |
mask_stack_bottom(gtm_thread *tx); |
#endif |
|
} // namespace GTM |
|
#endif // LIBITM_TLS_H |