1 // Copyright 2009 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4
5 // IWYU pragma: private, include "Common/Atomic.h"
6
7 #pragma once
8
9 #include "Common/Common.h"
10 #include "Common/CommonTypes.h"
11
12 // Atomic operations are performed in a single step by the CPU. It is
13 // impossible for other threads to see the operation "half-done."
14 //
15 // Some atomic operations can be combined with different types of memory
16 // barriers called "Acquire semantics" and "Release semantics", defined below.
17 //
18 // Acquire semantics: Future memory accesses cannot be relocated to before the
19 // operation.
20 //
21 // Release semantics: Past memory accesses cannot be relocated to after the
22 // operation.
23 //
24 // These barriers affect not only the compiler, but also the CPU.
25
26 namespace Common
27 {
AtomicAdd(volatile u32 & target,u32 value)28 inline void AtomicAdd(volatile u32& target, u32 value)
29 {
30 __sync_add_and_fetch(&target, value);
31 }
32
AtomicAnd(volatile u32 & target,u32 value)33 inline void AtomicAnd(volatile u32& target, u32 value)
34 {
35 __sync_and_and_fetch(&target, value);
36 }
37
AtomicDecrement(volatile u32 & target)38 inline void AtomicDecrement(volatile u32& target)
39 {
40 __sync_add_and_fetch(&target, -1);
41 }
42
AtomicIncrement(volatile u32 & target)43 inline void AtomicIncrement(volatile u32& target)
44 {
45 __sync_add_and_fetch(&target, 1);
46 }
47
AtomicOr(volatile u32 & target,u32 value)48 inline void AtomicOr(volatile u32& target, u32 value)
49 {
50 __sync_or_and_fetch(&target, value);
51 }
52
53 #ifndef __ATOMIC_RELAXED
54 #error __ATOMIC_RELAXED not defined; your compiler version is too old.
55 #endif
56
57 template <typename T>
AtomicLoad(volatile T & src)58 inline T AtomicLoad(volatile T& src)
59 {
60 return __atomic_load_n(&src, __ATOMIC_RELAXED);
61 }
62
63 template <typename T>
AtomicLoadAcquire(volatile T & src)64 inline T AtomicLoadAcquire(volatile T& src)
65 {
66 return __atomic_load_n(&src, __ATOMIC_ACQUIRE);
67 }
68
69 template <typename T, typename U>
AtomicStore(volatile T & dest,U value)70 inline void AtomicStore(volatile T& dest, U value)
71 {
72 __atomic_store_n(&dest, value, __ATOMIC_RELAXED);
73 }
74
75 template <typename T, typename U>
AtomicStoreRelease(volatile T & dest,U value)76 inline void AtomicStoreRelease(volatile T& dest, U value)
77 {
78 __atomic_store_n(&dest, value, __ATOMIC_RELEASE);
79 }
80
81 template <typename T, typename U>
AtomicExchangeAcquire(T * volatile & loc,U newval)82 inline T* AtomicExchangeAcquire(T* volatile& loc, U newval)
83 {
84 return __atomic_exchange_n(&loc, newval, __ATOMIC_ACQ_REL);
85 }
86 } // namespace Common
87