diff --git a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp index 78f3460f4..694e05e65 100644 --- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp +++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp @@ -60,19 +60,18 @@ static void PPCInterpreter_STWCX(PPCInterpreter_t* hCPU, uint32 Opcode) if (hCPU->reservedMemAddr == ea) { uint32be reservedValue = hCPU->reservedMemValue; // this is the value we expect in memory (if it does not match, STWCX fails) - uint32be* wordPtr; + std::atomic* wordPtr; if constexpr(ppcItpCtrl::allowSupervisorMode) { - wordPtr = reinterpret_cast(memory_base + ppcItpCtrl::ppcMem_translateVirtualDataToPhysicalAddr(hCPU, ea)); + wordPtr = _rawPtrToAtomic((uint32be*)(memory_base + ppcItpCtrl::ppcMem_translateVirtualDataToPhysicalAddr(hCPU, ea))); DSI_EXIT(); } else { - wordPtr = reinterpret_cast(memory_getPointerFromVirtualOffset(ea)); + wordPtr = _rawPtrToAtomic((uint32be*)memory_getPointerFromVirtualOffset(ea)); } - auto word = rawPtrToAtomicRef(wordPtr); uint32be newValue = hCPU->gpr[rS]; - if (!word.compare_exchange_strong(reservedValue, newValue)) + if (!wordPtr->compare_exchange_strong(reservedValue, newValue)) { // failed ppc_setCRBit(hCPU, CR_BIT_LT, 0); diff --git a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp index 0a80acfdf..167911b6a 100644 --- a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp +++ b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp @@ -583,12 +583,13 @@ LatteCMDPtr LatteCP_itMemSemaphore(LatteCMDPtr cmd, uint32 nWords) uint32 semaphoreControl = LatteReadCMD(); uint8 SEM_SIGNAL = (semaphoreControl >> 29) & 7; - auto semaphoreData = rawPtrToAtomicRef(reinterpret_cast(memory_getPointerFromPhysicalOffset(semaphorePhysicalAddress))); + std::atomic* semaphoreData = _rawPtrToAtomic((uint64le*)memory_getPointerFromPhysicalOffset(semaphorePhysicalAddress)); + static_assert(sizeof(std::atomic) == sizeof(uint64le)); if (SEM_SIGNAL == 6) { // signal - semaphoreData.fetch_add(1); + semaphoreData->fetch_add(1); } else if(SEM_SIGNAL == 7) { @@ -596,7 +597,7 @@ LatteCMDPtr LatteCP_itMemSemaphore(LatteCMDPtr cmd, uint32 nWords) size_t loopCount = 0; while (true) { - uint64le oldVal = semaphoreData.load(); + uint64le oldVal = semaphoreData->load(); if (oldVal == 0) { loopCount++; @@ -604,7 +605,7 @@ LatteCMDPtr LatteCP_itMemSemaphore(LatteCMDPtr cmd, uint32 nWords) std::this_thread::yield(); continue; } - if (semaphoreData.compare_exchange_strong(oldVal, oldVal - 1)) + if (semaphoreData->compare_exchange_strong(oldVal, oldVal - 1)) break; } } diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Atomic.cpp b/src/Cafe/OS/libs/coreinit/coreinit_Atomic.cpp index bf24b4028..accce5523 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Atomic.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Atomic.cpp @@ -6,44 +6,40 @@ namespace coreinit { /* 32bit atomic operations */ - uint32 OSSwapAtomic(uint32be* mem, uint32 newValue) + uint32 OSSwapAtomic(std::atomic* mem, uint32 newValue) { - const auto ref = rawPtrToAtomicRef(mem); uint32be _newValue = newValue; - uint32be previousValue = ref.exchange(_newValue); + uint32be previousValue = mem->exchange(_newValue); return previousValue; } - bool OSCompareAndSwapAtomic(uint32be* mem, uint32 compareValue, uint32 swapValue) + bool OSCompareAndSwapAtomic(std::atomic* mem, uint32 compareValue, uint32 swapValue) { // seen in GTA3 homebrew port - const auto ref = rawPtrToAtomicRef(mem); uint32be _compareValue = compareValue; uint32be _swapValue = swapValue; - return ref.compare_exchange_strong(_compareValue, _swapValue); + return mem->compare_exchange_strong(_compareValue, _swapValue); } - bool OSCompareAndSwapAtomicEx(uint32be* mem, uint32 compareValue, uint32 swapValue, uint32be* previousValue) + bool OSCompareAndSwapAtomicEx(std::atomic* mem, uint32 compareValue, uint32 swapValue, uint32be* previousValue) { // seen in GTA3 homebrew port - const auto ref = rawPtrToAtomicRef(mem); uint32be _compareValue = compareValue; uint32be _swapValue = swapValue; - bool r = ref.compare_exchange_strong(_compareValue, _swapValue); + bool r = mem->compare_exchange_strong(_compareValue, _swapValue); *previousValue = _compareValue; return r; } - uint32 OSAddAtomic(uint32be* mem, uint32 adder) + uint32 OSAddAtomic(std::atomic* mem, uint32 adder) { // used by SDL Wii U port - const auto ref = rawPtrToAtomicRef(mem); uint32be knownValue; while (true) { - knownValue = ref.load(); + knownValue = mem->load(); uint32be newValue = knownValue + adder; - if (ref.compare_exchange_strong(knownValue, newValue)) + if (mem->compare_exchange_strong(knownValue, newValue)) break; } return knownValue; @@ -51,80 +47,74 @@ namespace coreinit /* 64bit atomic operations */ - uint64 OSSwapAtomic64(uint64be* mem, uint64 newValue) + uint64 OSSwapAtomic64(std::atomic* mem, uint64 newValue) { - const auto ref = rawPtrToAtomicRef(mem); uint64be _newValue = newValue; - uint64be previousValue = ref.exchange(_newValue); + uint64be previousValue = mem->exchange(_newValue); return previousValue; } - uint64 OSSetAtomic64(uint64be* mem, uint64 newValue) + uint64 OSSetAtomic64(std::atomic* mem, uint64 newValue) { return OSSwapAtomic64(mem, newValue); } - uint64 OSGetAtomic64(uint64be* mem) + uint64 OSGetAtomic64(std::atomic* mem) { - return rawPtrToAtomicRef(mem).load(); + return mem->load(); } - uint64 OSAddAtomic64(uint64be* mem, uint64 adder) + uint64 OSAddAtomic64(std::atomic* mem, uint64 adder) { - const auto ref = rawPtrToAtomicRef(mem); uint64be knownValue; while (true) { - knownValue = ref.load(); + knownValue = mem->load(); uint64be newValue = knownValue + adder; - if (ref.compare_exchange_strong(knownValue, newValue)) + if (mem->compare_exchange_strong(knownValue, newValue)) break; } return knownValue; } - uint64 OSAndAtomic64(uint64be* mem, uint64 val) + uint64 OSAndAtomic64(std::atomic* mem, uint64 val) { - const auto ref = rawPtrToAtomicRef(mem); uint64be knownValue; while (true) { - knownValue = ref.load(); + knownValue = mem->load(); uint64be newValue = knownValue & val; - if (ref.compare_exchange_strong(knownValue, newValue)) + if (mem->compare_exchange_strong(knownValue, newValue)) break; } return knownValue; } - uint64 OSOrAtomic64(uint64be* mem, uint64 val) + uint64 OSOrAtomic64(std::atomic* mem, uint64 val) { - const auto ref = rawPtrToAtomicRef(mem); uint64be knownValue; while (true) { - knownValue = ref.load(); + knownValue = mem->load(); uint64be newValue = knownValue | val; - if (ref.compare_exchange_strong(knownValue, newValue)) + if (mem->compare_exchange_strong(knownValue, newValue)) break; } return knownValue; } - bool OSCompareAndSwapAtomic64(uint64be* mem, uint64 compareValue, uint64 swapValue) + bool OSCompareAndSwapAtomic64(std::atomic* mem, uint64 compareValue, uint64 swapValue) { - const auto ref = rawPtrToAtomicRef(mem); uint64be _compareValue = compareValue; uint64be _swapValue = swapValue; - return ref.compare_exchange_strong(_compareValue, _swapValue); + return mem->compare_exchange_strong(_compareValue, _swapValue); } - bool OSCompareAndSwapAtomicEx64(uint64be* mem, uint64 compareValue, uint64 swapValue, uint64be* previousValue) + bool OSCompareAndSwapAtomicEx64(std::atomic* mem, uint64 compareValue, uint64 swapValue, uint64be* previousValue) { - const auto ref = rawPtrToAtomicRef(mem); uint64be _compareValue = compareValue; uint64be _swapValue = swapValue; - bool r = ref.compare_exchange_strong(_compareValue, _swapValue); + bool r = mem->compare_exchange_strong(_compareValue, _swapValue); *previousValue = _compareValue; return r; } diff --git a/src/Cafe/OS/libs/coreinit/coreinit_Atomic.h b/src/Cafe/OS/libs/coreinit/coreinit_Atomic.h index 635afe599..317c20cee 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Atomic.h +++ b/src/Cafe/OS/libs/coreinit/coreinit_Atomic.h @@ -3,19 +3,19 @@ namespace coreinit { - uint32 OSSwapAtomic(uint32be* mem, uint32 newValue); - bool OSCompareAndSwapAtomic(uint32be* mem, uint32 compareValue, uint32 swapValue); - bool OSCompareAndSwapAtomicEx(uint32be* mem, uint32 compareValue, uint32 swapValue, uint32be* previousValue); - uint32 OSAddAtomic(uint32be* mem, uint32 adder); + uint32 OSSwapAtomic(std::atomic* mem, uint32 newValue); + bool OSCompareAndSwapAtomic(std::atomic* mem, uint32 compareValue, uint32 swapValue); + bool OSCompareAndSwapAtomicEx(std::atomic* mem, uint32 compareValue, uint32 swapValue, uint32be* previousValue); + uint32 OSAddAtomic(std::atomic* mem, uint32 adder); - uint64 OSSwapAtomic64(uint64be* mem, uint64 newValue); - uint64 OSSetAtomic64(uint64be* mem, uint64 newValue); - uint64 OSGetAtomic64(uint64be* mem); - uint64 OSAddAtomic64(uint64be* mem, uint64 adder); - uint64 OSAndAtomic64(uint64be* mem, uint64 val); - uint64 OSOrAtomic64(uint64be* mem, uint64 val); - bool OSCompareAndSwapAtomic64(uint64be* mem, uint64 compareValue, uint64 swapValue); - bool OSCompareAndSwapAtomicEx64(uint64be* mem, uint64 compareValue, uint64 swapValue, uint64be* previousValue); + uint64 OSSwapAtomic64(std::atomic* mem, uint64 newValue); + uint64 OSSetAtomic64(std::atomic* mem, uint64 newValue); + uint64 OSGetAtomic64(std::atomic* mem); + uint64 OSAddAtomic64(std::atomic* mem, uint64 adder); + uint64 OSAndAtomic64(std::atomic* mem, uint64 val); + uint64 OSOrAtomic64(std::atomic* mem, uint64 val); + bool OSCompareAndSwapAtomic64(std::atomic* mem, uint64 compareValue, uint64 swapValue); + bool OSCompareAndSwapAtomicEx64(std::atomic* mem, uint64 compareValue, uint64 swapValue, uint64be* previousValue); void InitializeAtomic(); } \ No newline at end of file diff --git a/src/Cafe/OS/libs/dmae/dmae.cpp b/src/Cafe/OS/libs/dmae/dmae.cpp index 1a8b5e1d4..6b3e8d0d4 100644 --- a/src/Cafe/OS/libs/dmae/dmae.cpp +++ b/src/Cafe/OS/libs/dmae/dmae.cpp @@ -79,17 +79,17 @@ void dmaeExport_DMAESemaphore(PPCInterpreter_t* hCPU) uint32 actionType = hCPU->gpr[4]; - auto semaphore = rawPtrToAtomicRef(reinterpret_cast(memory_getPointerFromVirtualOffset(hCPU->gpr[3]))); + std::atomic* semaphore = _rawPtrToAtomic((uint64le*)memory_getPointerFromVirtualOffset(hCPU->gpr[3])); if( actionType == 1 ) { // Signal Semaphore - ++semaphore; + semaphore->fetch_add(1); } else if (actionType == 0) // wait { cemuLog_logDebug(LogType::Force, "DMAESemaphore: Unsupported wait operation"); - --semaphore; + semaphore->fetch_sub(1); } else { diff --git a/src/Common/MemPtr.h b/src/Common/MemPtr.h index 87b5c7b45..7825e4d5c 100644 --- a/src/Common/MemPtr.h +++ b/src/Common/MemPtr.h @@ -77,8 +77,8 @@ class MEMPTR : MEMPTRBase { MEMPTR mp_compare = comparePtr; MEMPTR mp_new = newPtr; - std::atomic_ref thisValueAtomic(m_value); - return thisValueAtomic.compare_exchange_strong(mp_compare.m_value, mp_new.m_value); + auto* thisValueAtomic = reinterpret_cast*>(&m_value); + return thisValueAtomic->compare_exchange_strong(mp_compare.m_value, mp_new.m_value); } explicit constexpr operator bool() const noexcept diff --git a/src/Common/precompiled.h b/src/Common/precompiled.h index ae1f03591..7b0e8c64b 100644 --- a/src/Common/precompiled.h +++ b/src/Common/precompiled.h @@ -496,13 +496,13 @@ bool future_is_ready(std::future& f) } -// helper function to convert raw pointers to std::atomic_ref -// this is only legal as long as alignment restrictions are met +// helper function to cast raw pointers to std::atomic +// this is technically not legal but works on most platforms as long as alignment restrictions are met and the implementation of atomic doesnt come with additional members + template -std::atomic_ref rawPtrToAtomicRef(T* ptr) +std::atomic* _rawPtrToAtomic(T* ptr) { - cemu_assert_debug(reinterpret_cast(ptr) % std::atomic_ref::required_alignment); - return std::atomic_ref(*ptr); + return reinterpret_cast*>(ptr); } #if defined(__GNUC__)