sanitizer_atomic_clang_mips.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //===-- sanitizer_atomic_clang_mips.h ---------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
  10. // Not intended for direct inclusion. Include sanitizer_atomic.h.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef SANITIZER_ATOMIC_CLANG_MIPS_H
  14. #define SANITIZER_ATOMIC_CLANG_MIPS_H
  15. namespace __sanitizer {
  16. // MIPS32 does not support atomics > 4 bytes. To address this lack of
  17. // functionality, the sanitizer library provides helper methods which use an
  18. // internal spin lock mechanism to emulate atomic operations when the size is
  19. // 8 bytes.
  20. static void __spin_lock(volatile int *lock) {
  21. while (__sync_lock_test_and_set(lock, 1))
  22. while (*lock) {
  23. }
  24. }
  25. static void __spin_unlock(volatile int *lock) { __sync_lock_release(lock); }
  26. // Make sure the lock is on its own cache line to prevent false sharing.
  27. // Put it inside a struct that is aligned and padded to the typical MIPS
  28. // cacheline which is 32 bytes.
  29. static struct {
  30. int lock;
  31. char pad[32 - sizeof(int)];
  32. } __attribute__((aligned(32))) lock = {0, {0}};
  33. template <>
  34. inline atomic_uint64_t::Type atomic_fetch_add(volatile atomic_uint64_t *ptr,
  35. atomic_uint64_t::Type val,
  36. memory_order mo) {
  37. DCHECK(mo &
  38. (memory_order_relaxed | memory_order_release | memory_order_seq_cst));
  39. DCHECK(!((uptr)ptr % sizeof(*ptr)));
  40. atomic_uint64_t::Type ret;
  41. __spin_lock(&lock.lock);
  42. ret = *(const_cast<atomic_uint64_t::Type volatile *>(&ptr->val_dont_use));
  43. ptr->val_dont_use = ret + val;
  44. __spin_unlock(&lock.lock);
  45. return ret;
  46. }
  47. template <>
  48. inline atomic_uint64_t::Type atomic_fetch_sub(volatile atomic_uint64_t *ptr,
  49. atomic_uint64_t::Type val,
  50. memory_order mo) {
  51. return atomic_fetch_add(ptr, -val, mo);
  52. }
  53. template <>
  54. inline bool atomic_compare_exchange_strong(volatile atomic_uint64_t *ptr,
  55. atomic_uint64_t::Type *cmp,
  56. atomic_uint64_t::Type xchg,
  57. memory_order mo) {
  58. DCHECK(mo &
  59. (memory_order_relaxed | memory_order_release | memory_order_seq_cst));
  60. DCHECK(!((uptr)ptr % sizeof(*ptr)));
  61. typedef atomic_uint64_t::Type Type;
  62. Type cmpv = *cmp;
  63. Type prev;
  64. bool ret = false;
  65. __spin_lock(&lock.lock);
  66. prev = *(const_cast<Type volatile *>(&ptr->val_dont_use));
  67. if (prev == cmpv) {
  68. ret = true;
  69. ptr->val_dont_use = xchg;
  70. }
  71. __spin_unlock(&lock.lock);
  72. return ret;
  73. }
  74. template <>
  75. inline atomic_uint64_t::Type atomic_load(const volatile atomic_uint64_t *ptr,
  76. memory_order mo) {
  77. DCHECK(mo &
  78. (memory_order_relaxed | memory_order_release | memory_order_seq_cst));
  79. DCHECK(!((uptr)ptr % sizeof(*ptr)));
  80. atomic_uint64_t::Type zero = 0;
  81. volatile atomic_uint64_t *Newptr =
  82. const_cast<volatile atomic_uint64_t *>(ptr);
  83. return atomic_fetch_add(Newptr, zero, mo);
  84. }
  85. template <>
  86. inline void atomic_store(volatile atomic_uint64_t *ptr, atomic_uint64_t::Type v,
  87. memory_order mo) {
  88. DCHECK(mo &
  89. (memory_order_relaxed | memory_order_release | memory_order_seq_cst));
  90. DCHECK(!((uptr)ptr % sizeof(*ptr)));
  91. __spin_lock(&lock.lock);
  92. ptr->val_dont_use = v;
  93. __spin_unlock(&lock.lock);
  94. }
  95. } // namespace __sanitizer
  96. #endif // SANITIZER_ATOMIC_CLANG_MIPS_H