OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.