Atomic.h
5.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#pragma once
#include <stdint.h>
#include "utils/NonCopyable.h"
#include "c-api/Atomic-c-api.h"
namespace il2cpp
{
namespace os
{
class Atomic : public il2cpp::utils::NonCopyable
{
public:
// All 32bit atomics must be performed on 4-byte aligned addresses. All 64bit atomics must be
// performed on 8-byte aligned addresses.
// Add and Add64 return the *result* of the addition, not the old value! (i.e. they work like
// InterlockedAdd and __sync_add_and_fetch).
static inline void FullMemoryBarrier();
static inline int32_t Add(volatile int32_t* location1, int32_t value)
{
return UnityPalAdd(location1, value);
}
static inline uint32_t Add(volatile uint32_t* location1, uint32_t value)
{
return (uint32_t)Add((volatile int32_t*)location1, (int32_t)value);
}
#if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT
static inline int64_t Add64(volatile int64_t* location1, int64_t value)
{
return UnityPalAdd64(location1, value);
}
#endif
template<typename T>
static inline T* CompareExchangePointer(T* volatile* dest, T* newValue, T* oldValue)
{
return static_cast<T*>(UnityPalCompareExchangePointer((void*volatile*)dest, newValue, oldValue));
}
template<typename T>
static inline T* ExchangePointer(T* volatile* dest, T* newValue)
{
return static_cast<T*>(UnityPalExchangePointer((void*volatile*)dest, newValue));
}
static inline int64_t Read64(volatile int64_t* addr)
{
return UnityPalRead64(addr);
}
static inline uint64_t Read64(volatile uint64_t* addr)
{
return (uint64_t)Read64((volatile int64_t*)addr);
}
template<typename T>
static inline T* ReadPointer(T* volatile* pointer)
{
#if IL2CPP_SIZEOF_VOID_P == 4
return reinterpret_cast<T*>(Add(reinterpret_cast<volatile int32_t*>(pointer), 0));
#else
return reinterpret_cast<T*>(Read64(reinterpret_cast<volatile int64_t*>(pointer)));
#endif
}
static inline int32_t Increment(volatile int32_t* value)
{
return UnityPalIncrement(value);
}
static inline uint32_t Increment(volatile uint32_t* value)
{
return (uint32_t)Increment((volatile int32_t*)value);
}
#if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT
static inline int64_t Increment64(volatile int64_t* value)
{
return UnityPalIncrement64(value);
}
static inline uint64_t Increment64(volatile uint64_t* value)
{
return (uint64_t)Increment64((volatile int64_t*)value);
}
#endif
static inline int32_t Decrement(volatile int32_t* value)
{
return UnityPalDecrement(value);
}
static inline uint32_t Decrement(volatile uint32_t* value)
{
return (uint32_t)Decrement((volatile int32_t*)value);
}
#if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT
static inline int64_t Decrement64(volatile int64_t* value)
{
return UnityPalDecrement64(value);
}
static inline uint64_t Decrement64(volatile uint64_t* value)
{
return (uint64_t)Decrement64((volatile int64_t*)value);
}
#endif
static inline int32_t CompareExchange(volatile int32_t* dest, int32_t exchange, int32_t comparand)
{
return UnityPalCompareExchange(dest, exchange, comparand);
}
static inline uint32_t CompareExchange(volatile uint32_t* value, uint32_t newValue, uint32_t oldValue)
{
return (uint32_t)CompareExchange((volatile int32_t*)value, newValue, oldValue);
}
static inline int64_t CompareExchange64(volatile int64_t* dest, int64_t exchange, int64_t comparand)
{
return UnityPalCompareExchange64(dest, exchange, comparand);
}
static inline uint64_t CompareExchange64(volatile uint64_t* value, uint64_t newValue, uint64_t oldValue)
{
return (uint64_t)CompareExchange64((volatile int64_t*)value, newValue, oldValue);
}
static inline int32_t Exchange(volatile int32_t* dest, int32_t exchange)
{
return UnityPalExchange(dest, exchange);
}
static inline uint32_t Exchange(volatile uint32_t* value, uint32_t newValue)
{
return (uint32_t)Exchange((volatile int32_t*)value, newValue);
}
#if IL2CPP_ENABLE_INTERLOCKED_64_REQUIRED_ALIGNMENT
static inline int64_t Exchange64(volatile int64_t* dest, int64_t exchange)
{
return UnityPalExchange64(dest, exchange);
}
static inline uint64_t Exchange64(volatile uint64_t* value, uint64_t newValue)
{
return (uint64_t)Exchange64((volatile int64_t*)value, newValue);
}
#endif
};
}
}
#if !IL2CPP_SUPPORT_THREADS
namespace il2cpp
{
namespace os
{
inline void Atomic::FullMemoryBarrier()
{
// Do nothing.
}
}
}
#elif IL2CPP_TARGET_WINDOWS
#include "os/Win32/AtomicImpl.h"
#elif IL2CPP_TARGET_PS4
#include "os/AtomicImpl.h" // has to come earlier than posix
#elif IL2CPP_TARGET_PSP2
#include "os/PSP2/AtomicImpl.h"
#elif IL2CPP_TARGET_POSIX
#include "os/Posix/AtomicImpl.h"
#else
#include "os/AtomicImpl.h"
#endif