atomic_ops.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <cstring>
  6. #include <memory>
  7. #include "common/common_types.h"
  8. #if _MSC_VER
  9. #include <intrin.h>
  10. #endif
  11. namespace Common {
  12. #if _MSC_VER
  13. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
  14. const u8 result =
  15. _InterlockedCompareExchange8(reinterpret_cast<volatile char*>(pointer), value, expected);
  16. return result == expected;
  17. }
  18. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
  19. const u16 result =
  20. _InterlockedCompareExchange16(reinterpret_cast<volatile short*>(pointer), value, expected);
  21. return result == expected;
  22. }
  23. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
  24. const u32 result =
  25. _InterlockedCompareExchange(reinterpret_cast<volatile long*>(pointer), value, expected);
  26. return result == expected;
  27. }
  28. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
  29. const u64 result = _InterlockedCompareExchange64(reinterpret_cast<volatile __int64*>(pointer),
  30. value, expected);
  31. return result == expected;
  32. }
  33. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected) {
  34. return _InterlockedCompareExchange128(reinterpret_cast<volatile __int64*>(pointer), value[1],
  35. value[0],
  36. reinterpret_cast<__int64*>(expected.data())) != 0;
  37. }
  38. #else
  39. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {
  40. return __sync_bool_compare_and_swap(pointer, expected, value);
  41. }
  42. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) {
  43. return __sync_bool_compare_and_swap(pointer, expected, value);
  44. }
  45. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) {
  46. return __sync_bool_compare_and_swap(pointer, expected, value);
  47. }
  48. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) {
  49. return __sync_bool_compare_and_swap(pointer, expected, value);
  50. }
  51. [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected) {
  52. unsigned __int128 value_a;
  53. unsigned __int128 expected_a;
  54. std::memcpy(&value_a, value.data(), sizeof(u128));
  55. std::memcpy(&expected_a, expected.data(), sizeof(u128));
  56. return __sync_bool_compare_and_swap((unsigned __int128*)pointer, expected_a, value_a);
  57. }
  58. #endif
  59. } // namespace Common