summaryrefslogtreecommitdiff
path: root/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits')
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h114
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h16
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h5
3 files changed, 66 insertions, 69 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h
index 49a935a52..b0586ea1e 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h
@@ -37,61 +37,21 @@ typedef uintmax_t uatomic_max_t;
void __arm_link_error (void);
-#ifdef __thumb__
-
-/* Note that to allow efficient implementation the arguemtns are reversed
- relative to atomic_exchange_acq. */
-int __thumb_swpb (int newvalue, void *mem)
- attribute_hidden;
-unsigned int __thumb_swp (unsigned int newvalue, void *mem)
- attribute_hidden;
-unsigned int __thumb_cmpxchg (unsigned int oldval, unsigned int newval, void *mem)
- attribute_hidden;
-
-#define atomic_exchange_acq(mem, newvalue) \
- ({ __typeof (*mem) result; \
- if (sizeof (*mem) == 1) \
- result = __thumb_swpb (newvalue, mem); \
- else if (sizeof (*mem) == 4) \
- result = __thumb_swp (newvalue, mem); \
- else \
- { \
- result = 0; \
- abort (); \
- } \
- result; })
-
-#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \
- ({ __arm_link_error (); oldval; })
-
-#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
- ({ __arm_link_error (); oldval; })
-
-#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
- ((__typeof (oldval)) __thumb_cmpxchg (oldval, newval, mem))
-
-#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
- ({ __arm_link_error (); oldval; })
-
+#ifdef __thumb2__
+#define atomic_full_barrier() \
+ __asm__ __volatile__ \
+ ("movw\tip, #0x0fa0\n\t" \
+ "movt\tip, #0xffff\n\t" \
+ "blx\tip" \
+ : : : "ip", "lr", "cc", "memory");
#else
-/* ARM mode. */
-
-#define atomic_exchange_acq(mem, newvalue) \
- ({ __typeof (*mem) _xchg_result; \
- if (sizeof (*mem) == 1) \
- __asm__ __volatile__ ("swpb %0, %1, [%2]" \
- : "=&r,&r" (_xchg_result) \
- : "r,0" (newvalue), "r,r" (mem) : "memory"); \
- else if (sizeof (*mem) == 4) \
- __asm__ __volatile__ ("swp %0, %1, [%2]" \
- : "=&r,&r" (_xchg_result) \
- : "r,0" (newvalue), "r,r" (mem) : "memory"); \
- else \
- { \
- _xchg_result = 0; \
- abort (); \
- } \
- _xchg_result; })
+#define atomic_full_barrier() \
+ __asm__ __volatile__ \
+ ("mov\tip, #0xffff0fff\n\t" \
+ "mov\tlr, pc\n\t" \
+ "add\tpc, ip, #(0xffff0fa0 - 0xffff0fff)" \
+ : : : "ip", "lr", "cc", "memory");
+#endif
/* Atomic compare and exchange. This sequence relies on the kernel to
provide a compare and exchange operation which is atomic on the
@@ -108,6 +68,9 @@ unsigned int __thumb_cmpxchg (unsigned int oldval, unsigned int newval, void *me
specify one to work around GCC PR rtl-optimization/21223. Otherwise
it may cause a_oldval or a_tmp to be moved to a different register. */
+#ifdef __thumb2__
+/* Thumb-2 has ldrex/strex. However it does not have barrier instructions,
+ so we still need to use the kernel helper. */
#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
({ register __typeof (oldval) a_oldval asm ("r0"); \
register __typeof (oldval) a_newval asm ("r1") = (newval); \
@@ -115,22 +78,45 @@ unsigned int __thumb_cmpxchg (unsigned int oldval, unsigned int newval, void *me
register __typeof (oldval) a_tmp asm ("r3"); \
register __typeof (oldval) a_oldval2 asm ("r4") = (oldval); \
__asm__ __volatile__ \
- ("0:\tldr\t%1,[%3]\n\t" \
- "cmp\t%1, %4\n\t" \
+ ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \
+ "cmp\t%[tmp], %[old2]\n\t" \
"bne\t1f\n\t" \
- "mov\t%0, %4\n\t" \
- "mov\t%1, #0xffff0fff\n\t" \
+ "mov\t%[old], %[old2]\n\t" \
+ "movw\t%[tmp], #0x0fc0\n\t" \
+ "movt\t%[tmp], #0xffff\n\t" \
+ "blx\t%[tmp]\n\t" \
+ "bcc\t0b\n\t" \
+ "mov\t%[tmp], %[old2]\n\t" \
+ "1:" \
+ : [old] "=&r" (a_oldval), [tmp] "=&r" (a_tmp) \
+ : [new] "r" (a_newval), [ptr] "r" (a_ptr), \
+ [old2] "r" (a_oldval2) \
+ : "ip", "lr", "cc", "memory"); \
+ a_tmp; })
+#else
+#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
+ ({ register __typeof (oldval) a_oldval asm ("r0"); \
+ register __typeof (oldval) a_newval asm ("r1") = (newval); \
+ register __typeof (mem) a_ptr asm ("r2") = (mem); \
+ register __typeof (oldval) a_tmp asm ("r3"); \
+ register __typeof (oldval) a_oldval2 asm ("r4") = (oldval); \
+ __asm__ __volatile__ \
+ ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \
+ "cmp\t%[tmp], %[old2]\n\t" \
+ "bne\t1f\n\t" \
+ "mov\t%[old], %[old2]\n\t" \
+ "mov\t%[tmp], #0xffff0fff\n\t" \
"mov\tlr, pc\n\t" \
- "add\tpc, %1, #(0xffff0fc0 - 0xffff0fff)\n\t" \
+ "add\tpc, %[tmp], #(0xffff0fc0 - 0xffff0fff)\n\t" \
"bcc\t0b\n\t" \
- "mov\t%1, %4\n\t" \
+ "mov\t%[tmp], %[old2]\n\t" \
"1:" \
- : "=&r" (a_oldval), "=&r" (a_tmp) \
- : "r" (a_newval), "r" (a_ptr), "r" (a_oldval2) \
+ : [old] "=&r" (a_oldval), [tmp] "=&r" (a_tmp) \
+ : [new] "r" (a_newval), [ptr] "r" (a_ptr), \
+ [old2] "r" (a_oldval2) \
: "ip", "lr", "cc", "memory"); \
a_tmp; })
+#endif
#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \
({ __arm_link_error (); oldval; })
-
-#endif /* __thumb__ */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h
index ea8d6a2f0..e1b115c8c 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h
@@ -19,6 +19,8 @@
#ifndef _BITS_PTHREADTYPES_H
#define _BITS_PTHREADTYPES_H 1
+#include <endian.h>
+
#define __SIZEOF_PTHREAD_ATTR_T 36
#define __SIZEOF_PTHREAD_MUTEX_T 24
#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
@@ -126,9 +128,21 @@ typedef union
unsigned int __writer_wakeup;
unsigned int __nr_readers_queued;
unsigned int __nr_writers_queued;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned char __pad1;
+ unsigned char __pad2;
+ unsigned char __shared;
+ /* FLAGS must stay at this position in the structure to maintain
+ binary compatibility. */
+ unsigned char __flags;
+#else
/* FLAGS must stay at this position in the structure to maintain
binary compatibility. */
- unsigned int __flags;
+ unsigned char __flags;
+ unsigned char __shared;
+ unsigned char __pad1;
+ unsigned char __pad2;
+#endif
int __writer;
} __data;
char __size[__SIZEOF_PTHREAD_RWLOCK_T];
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h
index 3fc647d31..dadfac2af 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -27,9 +27,6 @@
/* Value returned if `sem_open' failed. */
#define SEM_FAILED ((sem_t *) 0)
-/* Maximum value the semaphore can have. */
-#define SEM_VALUE_MAX ((int) ((~0u) >> 1))
-
typedef union
{