diff options
| author | Simon Dardis <simon.dardis@mips.com> | 2017-12-22 20:31:07 +0000 |
|---|---|---|
| committer | Simon Dardis <simon.dardis@mips.com> | 2017-12-22 20:31:07 +0000 |
| commit | 92365cae1cfe345a3c7ee3b0c725087c12b8c61f (patch) | |
| tree | d5d6ed43be2bf06e0512c4e18b279cb864d8cb17 /compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h | |
| parent | ca741a87f25d96f86b381f927ac84f8e0a2c6ed0 (diff) | |
| download | bcm5719-llvm-92365cae1cfe345a3c7ee3b0c725087c12b8c61f.tar.gz bcm5719-llvm-92365cae1cfe345a3c7ee3b0c725087c12b8c61f.zip | |
Reland "[mips][compiler-rt] Provide 64bit atomic add and sub"
r318733 introduced a build failure for native MIPS32 systems for xray due
to the lack of __sync_fetch_and_add / __syn_fetch_and_sub support. This patch
extends the existing support providing atomics so that xray can be
successfully built.
The initial patch was reverted in r321292, as I suspected it may have caused the
buildbot failure. Another patch in the updates the bot fetched caused the test
failures which was reverted.
Reviewers: atanasyan, dberris
Differential Revision: https://reviews.llvm.org/D40385
llvm-svn: 321383
Diffstat (limited to 'compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h')
| -rw-r--r-- | compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h new file mode 100644 index 00000000000..c64e6e54279 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_atomic_clang_mips.h @@ -0,0 +1,118 @@ +//===-- sanitizer_atomic_clang_mips.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of ThreadSanitizer/AddressSanitizer runtime. +// Not intended for direct inclusion. Include sanitizer_atomic.h. +// +//===----------------------------------------------------------------------===// + +#ifndef SANITIZER_ATOMIC_CLANG_MIPS_H +#define SANITIZER_ATOMIC_CLANG_MIPS_H + +namespace __sanitizer { + +// MIPS32 does not support atomics > 4 bytes. To address this lack of +// functionality, the sanitizer library provides helper methods which use an +// internal spin lock mechanism to emulate atomic oprations when the size is +// 8 bytes. +static void __spin_lock(volatile int *lock) { + while (__sync_lock_test_and_set(lock, 1)) + while (*lock) { + } +} + +static void __spin_unlock(volatile int *lock) { __sync_lock_release(lock); } + +// Make sure the lock is on its own cache line to prevent false sharing. +// Put it inside a struct that is aligned and padded to the typical MIPS +// cacheline which is 32 bytes. +static struct { + int lock; + char pad[32 - sizeof(int)]; +} __attribute__((aligned(32))) lock = {0, {0}}; + +template <> +INLINE atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr, + atomic_uint64_t::Type val, + memory_order mo) { + DCHECK(mo & + (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); + DCHECK(!((uptr)ptr % sizeof(*ptr))); + + atomic_uint64_t::Type ret; + + __spin_lock(&lock.lock); + ret = *(const_cast<atomic_uint64_t::Type volatile *>(&ptr->val_dont_use)); + ptr->val_dont_use = ret + val; + __spin_unlock(&lock.lock); + + return ret; +} + +template <> +INLINE atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr, + atomic_uint64_t::Type val, + memory_order mo) { + return atomic_fetch_add(ptr, -val, mo); +} + +template <> +INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr, + atomic_uint64_t::Type *cmp, + atomic_uint64_t::Type xchg, + memory_order mo) { + DCHECK(mo & + (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); + DCHECK(!((uptr)ptr % sizeof(*ptr))); + + typedef atomic_uint64_t::Type Type; + Type cmpv = *cmp; + Type prev; + bool ret = false; + + __spin_lock(&lock.lock); + prev = *(const_cast<Type volatile *>(&ptr->val_dont_use)); + if (prev == cmpv) { + ret = true; + ptr->val_dont_use = xchg; + } + __spin_unlock(&lock.lock); + + return ret; +} + +template <> +INLINE atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr, + memory_order mo) { + DCHECK(mo & + (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); + DCHECK(!((uptr)ptr % sizeof(*ptr))); + + atomic_uint64_t::Type zero = 0; + volatile atomic_uint64_t *Newptr = + const_cast<volatile atomic_uint64_t *>(ptr); + return atomic_fetch_add(Newptr, zero, mo); +} + +template <> +INLINE void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v, + memory_order mo) { + DCHECK(mo & + (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst)); + DCHECK(!((uptr)ptr % sizeof(*ptr))); + + __spin_lock(&lock.lock); + ptr->val_dont_use = v; + __spin_unlock(&lock.lock); +} + +} // namespace __sanitizer + +#endif // SANITIZER_ATOMIC_CLANG_MIPS_H + |

