about summary refs log tree commit diff
path: root/sysdeps/tile/atomic-machine.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/tile/atomic-machine.h')
-rw-r--r--sysdeps/tile/atomic-machine.h51
1 files changed, 40 insertions, 11 deletions
diff --git a/sysdeps/tile/atomic-machine.h b/sysdeps/tile/atomic-machine.h
index 32277c960f..58ce76ccc9 100644
--- a/sysdeps/tile/atomic-machine.h
+++ b/sysdeps/tile/atomic-machine.h
@@ -16,20 +16,12 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* The sub-architecture headers provide definitions for these macros
-   that work for "int" and "long" size values only:
-
-   atomic_compare_and_exchange_val_acq()
-   atomic_exchange_acq()
-   atomic_exchange_and_add()
-   atomic_and_val()
-   atomic_or_val()
-   atomic_decrement_if_positive() [tilegx only]
-
-   Here we provide generic definitions true for all Tilera chips.  */
+#ifndef _ATOMIC_MACHINE_H
+#define _ATOMIC_MACHINE_H       1
 
 #include <stdint.h>
 #include <features.h>
+#include <arch/spr_def.h>
 
 typedef int32_t atomic32_t;
 typedef uint32_t uatomic32_t;
@@ -46,6 +38,41 @@ typedef uintptr_t uatomicptr_t;
 typedef intmax_t atomic_max_t;
 typedef uintmax_t uatomic_max_t;
 
+#ifdef _LP64
+# define __HAVE_64B_ATOMICS 1
+#else
+/* tilegx32 does have 64-bit atomics, but assumptions in the semaphore
+   code mean that unaligned 64-bit atomics will be used if this symbol
+   is true, and unaligned atomics are not supported on tile.  */
+# define __HAVE_64B_ATOMICS 0
+#endif
+
+#define USE_ATOMIC_COMPILER_BUILTINS 0
+#define ATOMIC_EXCHANGE_USES_CAS 0
+
+/* Pick appropriate 8- or 4-byte instruction. */
+#define __atomic_update(mem, v, op)                                     \
+  ((__typeof (*(mem))) (__typeof (*(mem) - *(mem)))                     \
+   ((sizeof (*(mem)) == 8) ?                                            \
+    __insn_##op ((void *) (mem), (int64_t) (__typeof((v) - (v))) (v)) : \
+    (sizeof (*(mem)) == 4) ?                                            \
+    __insn_##op##4 ((void *) (mem), (int32_t) (__typeof ((v) - (v))) (v)) : \
+    __atomic_error_bad_argument_size()))
+
+#define atomic_compare_and_exchange_val_acq(mem, n, o)                  \
+  ({ __insn_mtspr (SPR_CMPEXCH_VALUE, (int64_t) (__typeof ((o) - (o))) (o)); \
+     __atomic_update (mem, n, cmpexch); })
+#define atomic_exchange_acq(mem, newvalue) \
+  __atomic_update (mem, newvalue, exch)
+#define atomic_exchange_and_add(mem, value) \
+  __atomic_update (mem, value, fetchadd)
+#define atomic_and_val(mem, mask) \
+  __atomic_update (mem, mask, fetchand)
+#define atomic_or_val(mem, mask) \
+  __atomic_update (mem, mask, fetchor)
+#define atomic_decrement_if_positive(mem) \
+  __atomic_update (mem, -1, fetchaddgez)
+
 /* Barrier macro. */
 #define atomic_full_barrier() __sync_synchronize()
 
@@ -79,3 +106,5 @@ typedef uintmax_t uatomic_max_t;
  */
 extern int __atomic_error_bad_argument_size(void)
   __attribute__ ((warning ("bad sizeof atomic argument")));
+
+#endif /* _ATOMIC_MACHINE_H  */