diff --git a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp index 694e05e65..78f3460f4 100644 --- a/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp +++ b/src/Cafe/HW/Espresso/Interpreter/PPCInterpreterLoadStore.hpp @@ -60,18 +60,19 @@ 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) - std::atomic* wordPtr; + uint32be* wordPtr; if constexpr(ppcItpCtrl::allowSupervisorMode) { - wordPtr = _rawPtrToAtomic((uint32be*)(memory_base + ppcItpCtrl::ppcMem_translateVirtualDataToPhysicalAddr(hCPU, ea))); + wordPtr = reinterpret_cast(memory_base + ppcItpCtrl::ppcMem_translateVirtualDataToPhysicalAddr(hCPU, ea)); DSI_EXIT(); } else { - wordPtr = _rawPtrToAtomic((uint32be*)memory_getPointerFromVirtualOffset(ea)); + wordPtr = reinterpret_cast(memory_getPointerFromVirtualOffset(ea)); } + auto word = rawPtrToAtomicRef(wordPtr); uint32be newValue = hCPU->gpr[rS]; - if (!wordPtr->compare_exchange_strong(reservedValue, newValue)) + if (!word.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 167911b6a..0a80acfdf 100644 --- a/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp +++ b/src/Cafe/HW/Latte/Core/LatteCommandProcessor.cpp @@ -583,13 +583,12 @@ LatteCMDPtr LatteCP_itMemSemaphore(LatteCMDPtr cmd, uint32 nWords) uint32 semaphoreControl = LatteReadCMD(); uint8 SEM_SIGNAL = (semaphoreControl >> 29) & 7; - std::atomic* semaphoreData = _rawPtrToAtomic((uint64le*)memory_getPointerFromPhysicalOffset(semaphorePhysicalAddress)); - static_assert(sizeof(std::atomic) == sizeof(uint64le)); + auto semaphoreData = rawPtrToAtomicRef(reinterpret_cast(memory_getPointerFromPhysicalOffset(semaphorePhysicalAddress))); if (SEM_SIGNAL == 6) { // signal - semaphoreData->fetch_add(1); + semaphoreData.fetch_add(1); } else if(SEM_SIGNAL == 7) { @@ -597,7 +596,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++; @@ -605,7 +604,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 accce5523..bf24b4028 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_Atomic.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_Atomic.cpp @@ -6,40 +6,44 @@ namespace coreinit { /* 32bit atomic operations */ - uint32 OSSwapAtomic(std::atomic* mem, uint32 newValue) + uint32 OSSwapAtomic(uint32be* mem, uint32 newValue) { + const auto ref = rawPtrToAtomicRef(mem); uint32be _newValue = newValue; - uint32be previousValue = mem->exchange(_newValue); + uint32be previousValue = ref.exchange(_newValue); return previousValue; } - bool OSCompareAndSwapAtomic(std::atomic* mem, uint32 compareValue, uint32 swapValue) + bool OSCompareAndSwapAtomic(uint32be* mem, uint32 compareValue, uint32 swapValue) { // seen in GTA3 homebrew port + const auto ref = rawPtrToAtomicRef(mem); uint32be _compareValue = compareValue; uint32be _swapValue = swapValue; - return mem->compare_exchange_strong(_compareValue, _swapValue); + return ref.compare_exchange_strong(_compareValue, _swapValue); } - bool OSCompareAndSwapAtomicEx(std::atomic* mem, uint32 compareValue, uint32 swapValue, uint32be* previousValue) + bool OSCompareAndSwapAtomicEx(uint32be* 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 = mem->compare_exchange_strong(_compareValue, _swapValue); + bool r = ref.compare_exchange_strong(_compareValue, _swapValue); *previousValue = _compareValue; return r; } - uint32 OSAddAtomic(std::atomic* mem, uint32 adder) + uint32 OSAddAtomic(uint32be* mem, uint32 adder) { // used by SDL Wii U port + const auto ref = rawPtrToAtomicRef(mem); uint32be knownValue; while (true) { - knownValue = mem->load(); + knownValue = ref.load(); uint32be newValue = knownValue + adder; - if (mem->compare_exchange_strong(knownValue, newValue)) + if (ref.compare_exchange_strong(knownValue, newValue)) break; } return knownValue; @@ -47,74 +51,80 @@ namespace coreinit /* 64bit atomic operations */ - uint64 OSSwapAtomic64(std::atomic* mem, uint64 newValue) + uint64 OSSwapAtomic64(uint64be* mem, uint64 newValue) { + const auto ref = rawPtrToAtomicRef(mem); uint64be _newValue = newValue; - uint64be previousValue = mem->exchange(_newValue); + uint64be previousValue = ref.exchange(_newValue); return previousValue; } - uint64 OSSetAtomic64(std::atomic* mem, uint64 newValue) + uint64 OSSetAtomic64(uint64be* mem, uint64 newValue) { return OSSwapAtomic64(mem, newValue); } - uint64 OSGetAtomic64(std::atomic* mem) + uint64 OSGetAtomic64(uint64be* mem) { - return mem->load(); + return rawPtrToAtomicRef(mem).load(); } - uint64 OSAddAtomic64(std::atomic* mem, uint64 adder) + uint64 OSAddAtomic64(uint64be* mem, uint64 adder) { + const auto ref = rawPtrToAtomicRef(mem); uint64be knownValue; while (true) { - knownValue = mem->load(); + knownValue = ref.load(); uint64be newValue = knownValue + adder; - if (mem->compare_exchange_strong(knownValue, newValue)) + if (ref.compare_exchange_strong(knownValue, newValue)) break; } return knownValue; } - uint64 OSAndAtomic64(std::atomic* mem, uint64 val) + uint64 OSAndAtomic64(uint64be* mem, uint64 val) { + const auto ref = rawPtrToAtomicRef(mem); uint64be knownValue; while (true) { - knownValue = mem->load(); + knownValue = ref.load(); uint64be newValue = knownValue & val; - if (mem->compare_exchange_strong(knownValue, newValue)) + if (ref.compare_exchange_strong(knownValue, newValue)) break; } return knownValue; } - uint64 OSOrAtomic64(std::atomic* mem, uint64 val) + uint64 OSOrAtomic64(uint64be* mem, uint64 val) { + const auto ref = rawPtrToAtomicRef(mem); uint64be knownValue; while (true) { - knownValue = mem->load(); + knownValue = ref.load(); uint64be newValue = knownValue | val; - if (mem->compare_exchange_strong(knownValue, newValue)) + if (ref.compare_exchange_strong(knownValue, newValue)) break; } return knownValue; } - bool OSCompareAndSwapAtomic64(std::atomic* mem, uint64 compareValue, uint64 swapValue) + bool OSCompareAndSwapAtomic64(uint64be* mem, uint64 compareValue, uint64 swapValue) { + const auto ref = rawPtrToAtomicRef(mem); uint64be _compareValue = compareValue; uint64be _swapValue = swapValue; - return mem->compare_exchange_strong(_compareValue, _swapValue); + return ref.compare_exchange_strong(_compareValue, _swapValue); } - bool OSCompareAndSwapAtomicEx64(std::atomic* mem, uint64 compareValue, uint64 swapValue, uint64be* previousValue) + bool OSCompareAndSwapAtomicEx64(uint64be* mem, uint64 compareValue, uint64 swapValue, uint64be* previousValue) { + const auto ref = rawPtrToAtomicRef(mem); uint64be _compareValue = compareValue; uint64be _swapValue = swapValue; - bool r = mem->compare_exchange_strong(_compareValue, _swapValue); + bool r = ref.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 317c20cee..635afe599 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(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); + 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); - 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); + 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); 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 6b3e8d0d4..1a8b5e1d4 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]; - std::atomic* semaphore = _rawPtrToAtomic((uint64le*)memory_getPointerFromVirtualOffset(hCPU->gpr[3])); + auto semaphore = rawPtrToAtomicRef(reinterpret_cast(memory_getPointerFromVirtualOffset(hCPU->gpr[3]))); if( actionType == 1 ) { // Signal Semaphore - semaphore->fetch_add(1); + ++semaphore; } else if (actionType == 0) // wait { cemuLog_logDebug(LogType::Force, "DMAESemaphore: Unsupported wait operation"); - semaphore->fetch_sub(1); + --semaphore; } else { diff --git a/src/Common/MemPtr.h b/src/Common/MemPtr.h index 7825e4d5c..87b5c7b45 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; - auto* thisValueAtomic = reinterpret_cast*>(&m_value); - return thisValueAtomic->compare_exchange_strong(mp_compare.m_value, mp_new.m_value); + std::atomic_ref thisValueAtomic(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 617075193..06bd26ab1 100644 --- a/src/Common/precompiled.h +++ b/src/Common/precompiled.h @@ -509,13 +509,13 @@ struct scope_exit ~scope_exit() { if (f_) f_(); } }; -// 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 - +// helper function to convert raw pointers to std::atomic_ref +// this is only legal as long as alignment restrictions are met template -std::atomic* _rawPtrToAtomic(T* ptr) +std::atomic_ref rawPtrToAtomicRef(T* ptr) { - return reinterpret_cast*>(ptr); + cemu_assert_debug(reinterpret_cast(ptr) % std::atomic_ref::required_alignment); + return std::atomic_ref(*ptr); } #if defined(__GNUC__)