1 //===-- sanitizer_atomic_clang_mips.h ---------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
11 // Not intended for direct inclusion. Include sanitizer_atomic.h.
13 //===----------------------------------------------------------------------===//
15 #ifndef SANITIZER_ATOMIC_CLANG_MIPS_H
16 #define SANITIZER_ATOMIC_CLANG_MIPS_H
18 namespace __sanitizer {
20 // MIPS32 does not support atomics > 4 bytes. To address this lack of
21 // functionality, the sanitizer library provides helper methods which use an
22 // internal spin lock mechanism to emulate atomic oprations when the size is
24 static void __spin_lock(volatile int *lock) {
25 while (__sync_lock_test_and_set(lock, 1))
30 static void __spin_unlock(volatile int *lock) { __sync_lock_release(lock); }
32 // Make sure the lock is on its own cache line to prevent false sharing.
33 // Put it inside a struct that is aligned and padded to the typical MIPS
34 // cacheline which is 32 bytes.
37 char pad[32 - sizeof(int)];
38 } __attribute__((aligned(32))) lock = {0, {0}};
41 INLINE atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr,
42 atomic_uint64_t::Type val,
45 (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst));
46 DCHECK(!((uptr)ptr % sizeof(*ptr)));
48 atomic_uint64_t::Type ret;
50 __spin_lock(&lock.lock);
51 ret = *(const_cast<atomic_uint64_t::Type volatile *>(&ptr->val_dont_use));
52 ptr->val_dont_use = ret + val;
53 __spin_unlock(&lock.lock);
59 INLINE atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr,
60 atomic_uint64_t::Type val,
62 return atomic_fetch_add(ptr, -val, mo);
66 INLINE bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr,
67 atomic_uint64_t::Type *cmp,
68 atomic_uint64_t::Type xchg,
71 (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst));
72 DCHECK(!((uptr)ptr % sizeof(*ptr)));
74 typedef atomic_uint64_t::Type Type;
79 __spin_lock(&lock.lock);
80 prev = *(const_cast<Type volatile *>(&ptr->val_dont_use));
83 ptr->val_dont_use = xchg;
85 __spin_unlock(&lock.lock);
91 INLINE atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr,
94 (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst));
95 DCHECK(!((uptr)ptr % sizeof(*ptr)));
97 atomic_uint64_t::Type zero = 0;
98 volatile atomic_uint64_t *Newptr =
99 const_cast<volatile atomic_uint64_t *>(ptr);
100 return atomic_fetch_add(Newptr, zero, mo);
104 INLINE void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v,
107 (memory_order_relaxed | memory_order_releasae | memory_order_seq_cst));
108 DCHECK(!((uptr)ptr % sizeof(*ptr)));
110 __spin_lock(&lock.lock);
111 ptr->val_dont_use = v;
112 __spin_unlock(&lock.lock);
115 } // namespace __sanitizer
117 #endif // SANITIZER_ATOMIC_CLANG_MIPS_H