Atomic.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. //===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements atomic operations.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Support/Atomic.h"
  14. #include "llvm/Config/llvm-config.h"
  15. using namespace llvm;
  16. #if defined(_MSC_VER)
  17. #include <Intrin.h>
  18. #include <windows.h>
  19. #undef MemoryFence
  20. #endif
  21. #if defined(__GNUC__) || (defined(__IBMCPP__) && __IBMCPP__ >= 1210)
  22. #define GNU_ATOMICS
  23. #endif
  24. void sys::MemoryFence() {
  25. #if LLVM_HAS_ATOMICS == 0
  26. return;
  27. #else
  28. # if defined(GNU_ATOMICS)
  29. __sync_synchronize();
  30. # elif defined(_MSC_VER)
  31. MemoryBarrier();
  32. # else
  33. # error No memory fence implementation for your platform!
  34. # endif
  35. #endif
  36. }
  37. sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
  38. sys::cas_flag new_value,
  39. sys::cas_flag old_value) {
  40. #if LLVM_HAS_ATOMICS == 0
  41. sys::cas_flag result = *ptr;
  42. if (result == old_value)
  43. *ptr = new_value;
  44. return result;
  45. #elif defined(GNU_ATOMICS)
  46. return __sync_val_compare_and_swap(ptr, old_value, new_value);
  47. #elif defined(_MSC_VER)
  48. return InterlockedCompareExchange(ptr, new_value, old_value);
  49. #else
  50. # error No compare-and-swap implementation for your platform!
  51. #endif
  52. }
  53. sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) {
  54. #if LLVM_HAS_ATOMICS == 0
  55. ++(*ptr);
  56. return *ptr;
  57. #elif defined(GNU_ATOMICS)
  58. return __sync_add_and_fetch(ptr, 1);
  59. #elif defined(_MSC_VER)
  60. return InterlockedIncrement(ptr);
  61. #else
  62. # error No atomic increment implementation for your platform!
  63. #endif
  64. }
  65. sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) {
  66. #if LLVM_HAS_ATOMICS == 0
  67. --(*ptr);
  68. return *ptr;
  69. #elif defined(GNU_ATOMICS)
  70. return __sync_sub_and_fetch(ptr, 1);
  71. #elif defined(_MSC_VER)
  72. return InterlockedDecrement(ptr);
  73. #else
  74. # error No atomic decrement implementation for your platform!
  75. #endif
  76. }
  77. sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) {
  78. #if LLVM_HAS_ATOMICS == 0
  79. *ptr += val;
  80. return *ptr;
  81. #elif defined(GNU_ATOMICS)
  82. return __sync_add_and_fetch(ptr, val);
  83. #elif defined(_MSC_VER)
  84. return InterlockedExchangeAdd(ptr, val) + val;
  85. #else
  86. # error No atomic add implementation for your platform!
  87. #endif
  88. }
  89. sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) {
  90. sys::cas_flag original, result;
  91. do {
  92. original = *ptr;
  93. result = original * val;
  94. } while (sys::CompareAndSwap(ptr, result, original) != original);
  95. return result;
  96. }
  97. sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) {
  98. sys::cas_flag original, result;
  99. do {
  100. original = *ptr;
  101. result = original / val;
  102. } while (sys::CompareAndSwap(ptr, result, original) != original);
  103. return result;
  104. }