From 19d8a0fc2bb1aba5f4fd97b1a10fd8d156d12b98 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 17 May 2020 23:20:21 -0700 Subject: [PATCH] os: use ported libnx mutex impl --- ...ernal_critical_section_impl.os.horizon.cpp | 148 +++--------------- 1 file changed, 24 insertions(+), 124 deletions(-) diff --git a/libraries/libstratosphere/source/os/impl/os_internal_critical_section_impl.os.horizon.cpp b/libraries/libstratosphere/source/os/impl/os_internal_critical_section_impl.os.horizon.cpp index effa13f5f..48a21f96d 100644 --- a/libraries/libstratosphere/source/os/impl/os_internal_critical_section_impl.os.horizon.cpp +++ b/libraries/libstratosphere/source/os/impl/os_internal_critical_section_impl.os.horizon.cpp @@ -19,142 +19,42 @@ namespace ams::os::impl { - namespace { + #if defined(ATMOSPHERE_ARCH_ARM64) - ALWAYS_INLINE void DataMemoryBarrierForCriticalSection() { - #if defined(ATMOSPHERE_ARCH_ARM64) - /* ... */ - #else - #error "Unknown architecture for os::impl::InternalCriticalSectionImpl DataMemoryBarrier" - #endif + void InternalCriticalSectionImpl::Enter() { + AMS_ASSERT(svc::GetThreadLocalRegion()->disable_count == 0); + + /* Use the libnx impl. */ + static_assert(std::is_samethread_handle), ::Mutex>::value); + return ::mutexLock(std::addressof(this->thread_handle)); } - ALWAYS_INLINE u32 LoadExclusive(u32 *ptr) { - u32 value; + bool InternalCriticalSectionImpl::TryEnter() { + AMS_ASSERT(svc::GetThreadLocalRegion()->disable_count == 0); - #if defined(ATMOSPHERE_ARCH_ARM64) - __asm__ __volatile__("ldaxr %w[value], [%[ptr]]" : [value]"=&r"(value) : [ptr]"r"(ptr) : "memory"); - #else - #error "Unknown architecture for os::impl::InternalCriticalSectionImpl LoadExclusive" - #endif - - return value; + /* Use the libnx impl. */ + static_assert(std::is_samethread_handle), ::Mutex>::value); + return ::mutexTryLock(std::addressof(this->thread_handle)); } - ALWAYS_INLINE int StoreExclusive(u32 *ptr, u32 value) { - int result; + void InternalCriticalSectionImpl::Leave() { + AMS_ASSERT(svc::GetThreadLocalRegion()->disable_count == 0); - #if defined(ATMOSPHERE_ARCH_ARM64) - __asm__ __volatile__("stlxr %w[result], %w[value], [%[ptr]]" : [result]"=&r"(result) : [value]"r"(value), [ptr]"r"(ptr) : "memory"); - #else - #error "Unknown architecture for os::impl::InternalCriticalSectionImpl StoreExclusive" - #endif - - - return result; + /* Use the libnx impl. */ + static_assert(std::is_samethread_handle), ::Mutex>::value); + return ::mutexUnlock(std::addressof(this->thread_handle)); } - ALWAYS_INLINE void ClearExclusive() { - #if defined(ATMOSPHERE_ARCH_ARM64) - __asm__ __volatile__("clrex" ::: "memory"); - #else - #error "Unknown architecture for os::impl::InternalCriticalSectionImpl ClearExclusive" - #endif + bool InternalCriticalSectionImpl::IsLockedByCurrentThread() const { + /* Use the libnx impl. */ + static_assert(std::is_samethread_handle), ::Mutex>::value); + return ::mutexIsLockedByCurrentThread(std::addressof(this->thread_handle)); } - } + #else - void InternalCriticalSectionImpl::Enter() { - AMS_ASSERT(svc::GetThreadLocalRegion()->disable_count == 0); + #error "Architecture not yet supported for os::InternalCriticalSectionImpl" - const auto cur_handle = GetCurrentThreadHandle(); - AMS_ASSERT((this->thread_handle & ~ams::svc::HandleWaitMask) != cur_handle); - - u32 value = LoadExclusive(std::addressof(this->thread_handle)); - while (true) { - if (AMS_LIKELY(value == svc::InvalidHandle)) { - if (AMS_UNLIKELY(StoreExclusive(std::addressof(this->thread_handle), cur_handle) != 0)) { - value = LoadExclusive(std::addressof(this->thread_handle)); - continue; - } - break; - } - - if (AMS_LIKELY((value & ams::svc::HandleWaitMask) == 0)) { - if (AMS_UNLIKELY(StoreExclusive(std::addressof(this->thread_handle), value | ams::svc::HandleWaitMask) != 0)) { - value = LoadExclusive(std::addressof(this->thread_handle)); - continue; - } - } - - R_ABORT_UNLESS(ams::svc::ArbitrateLock(value & ~ams::svc::HandleWaitMask, reinterpret_cast(std::addressof(this->thread_handle)), cur_handle)); - - value = LoadExclusive(std::addressof(this->thread_handle)); - if (AMS_LIKELY((value & ~ams::svc::HandleWaitMask) == cur_handle)) { - ClearExclusive(); - break; - } - } - - DataMemoryBarrierForCriticalSection(); - } - - bool InternalCriticalSectionImpl::TryEnter() { - AMS_ASSERT(svc::GetThreadLocalRegion()->disable_count == 0); - - const auto cur_handle = GetCurrentThreadHandle(); - - while (true) { - u32 value = LoadExclusive(std::addressof(this->thread_handle)); - if (AMS_UNLIKELY(value != svc::InvalidHandle)) { - break; - } - - DataMemoryBarrierForCriticalSection(); - - if (AMS_LIKELY(StoreExclusive(std::addressof(this->thread_handle), cur_handle) == 0)) { - return true; - } - } - - ClearExclusive(); - DataMemoryBarrierForCriticalSection(); - - return false; - } - - void InternalCriticalSectionImpl::Leave() { - AMS_ASSERT(svc::GetThreadLocalRegion()->disable_count == 0); - - const auto cur_handle = GetCurrentThreadHandle(); - u32 value = LoadExclusive(std::addressof(this->thread_handle)); - - while (true) { - if (AMS_UNLIKELY(value != cur_handle)) { - ClearExclusive(); - break; - } - - DataMemoryBarrierForCriticalSection(); - - if (AMS_LIKELY(StoreExclusive(std::addressof(this->thread_handle), 0) == 0)) { - break; - } - - value = LoadExclusive(std::addressof(this->thread_handle)); - } - - DataMemoryBarrierForCriticalSection(); - - AMS_ASSERT((value | ams::svc::HandleWaitMask) == (cur_handle | ams::svc::HandleWaitMask)); - if (value & ams::svc::HandleWaitMask) { - R_ABORT_UNLESS(ams::svc::ArbitrateUnlock(reinterpret_cast(std::addressof(this->thread_handle)))); - } - } - - bool InternalCriticalSectionImpl::IsLockedByCurrentThread() const { - const auto cur_handle = GetCurrentThreadHandle(); - return (this->thread_handle & ~ams::svc::HandleWaitMask) == cur_handle; - } + #endif }