mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
os: tweak LightEvent codegen
This commit is contained in:
parent
632b6b3330
commit
c7634c66c4
1 changed files with 29 additions and 1 deletions
|
@ -72,8 +72,36 @@ namespace ams::os::impl {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE s32 LoadAcquireExclusiveForLightEvent(s32 *p) {
|
||||||
|
s32 v;
|
||||||
|
__asm__ __volatile__("ldaxr %w[v], %[p]" : [v]"=&r"(v) : [p]"Q"(*p) : "memory");
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool StoreReleaseExclusiveForLightEvent(s32 *p, s32 v) {
|
||||||
|
int result;
|
||||||
|
__asm__ __volatile__("stlxr %w[result], %w[v], %[p]" : [result]"=&r"(result) : [v]"r"(v), [p]"Q"(*p) : "memory");
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE void ClearExclusiveForLightEvent() {
|
||||||
|
__asm__ __volatile__("clrex" ::: "memory");
|
||||||
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE bool CompareAndSwap(std::atomic<s32> *state, s32 expected, s32 desired) {
|
ALWAYS_INLINE bool CompareAndSwap(std::atomic<s32> *state, s32 expected, s32 desired) {
|
||||||
return state->compare_exchange_strong(expected, desired);
|
/* NOTE: This works around gcc not emitting clrex on ldaxr fail. */
|
||||||
|
s32 * const state_ptr = reinterpret_cast<s32 *>(GetAddressOfAtomicInteger(state));
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (AMS_UNLIKELY(LoadAcquireExclusiveForLightEvent(state_ptr) != expected)) {
|
||||||
|
ClearExclusiveForLightEvent();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AMS_LIKELY(StoreReleaseExclusiveForLightEvent(state_ptr, desired))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue