diff options
| author | Matt Peters <[email protected]> | 2021-12-02 21:16:55 -0700 |
|---|---|---|
| committer | Matt Peters <[email protected]> | 2021-12-02 21:16:55 -0700 |
| commit | c9d52890cd98aaf2ec46a726d323169ca724a1dd (patch) | |
| tree | ad9c6c45540336c7298b857273a30b58cc6b645a /zencore/iobuffer.cpp | |
| parent | Merge pull request #31 from EpicGames/non-elevated-asio (diff) | |
| download | zen-c9d52890cd98aaf2ec46a726d323169ca724a1dd.tar.xz zen-c9d52890cd98aaf2ec46a726d323169ca724a1dd.zip | |
Make IoBufferCore::Materialize threadsafe
Diffstat (limited to 'zencore/iobuffer.cpp')
| -rw-r--r-- | zencore/iobuffer.cpp | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/zencore/iobuffer.cpp b/zencore/iobuffer.cpp index 7077942bf..9a7c6b30e 100644 --- a/zencore/iobuffer.cpp +++ b/zencore/iobuffer.cpp @@ -39,7 +39,7 @@ IoBufferCore::AllocateBuffer(size_t InSize, size_t Alignment) #if ZEN_PLATFORM_WINDOWS if (((InSize & 0xffFF) == 0) && (Alignment == 0x10000)) { - m_Flags |= kLowLevelAlloc; + m_Flags.fetch_or(kLowLevelAlloc, std::memory_order_relaxed); m_DataPtr = VirtualAlloc(nullptr, InSize, MEM_COMMIT, PAGE_READWRITE); return; @@ -48,7 +48,7 @@ IoBufferCore::AllocateBuffer(size_t InSize, size_t Alignment) #if ZEN_USE_MIMALLOC void* Ptr = mi_aligned_alloc(Alignment, RoundUp(InSize, Alignment)); - m_Flags |= kIoBufferAlloc; + m_Flags.fetch_or(kIoBufferAlloc, std::memory_order_relaxed); #else void* Ptr = Memory::Alloc(InSize, Alignment); #endif @@ -66,8 +66,9 @@ IoBufferCore::FreeBuffer() return; } + uint32_t LocalFlags = m_Flags.load(std::memory_order_relaxed); #if ZEN_PLATFORM_WINDOWS - if (m_Flags & kLowLevelAlloc) + if (LocalFlags & kLowLevelAlloc) { VirtualFree(const_cast<void*>(m_DataPtr), 0, MEM_DECOMMIT); @@ -76,7 +77,7 @@ IoBufferCore::FreeBuffer() #endif // ZEN_PLATFORM_WINDOWS #if ZEN_USE_MIMALLOC - if (m_Flags & kIoBufferAlloc) + if (LocalFlags & kIoBufferAlloc) { return mi_free(const_cast<void*>(m_DataPtr)); } @@ -170,11 +171,11 @@ IoBufferExtendedCore::IoBufferExtendedCore(void* FileHandle, uint64_t Offset, ui , m_FileHandle(FileHandle) , m_FileOffset(Offset) { - m_Flags |= kIsOwnedByThis | kIsExtended; + m_Flags.fetch_or(kIsOwnedByThis | kIsExtended, std::memory_order_relaxed); if (TransferHandleOwnership) { - m_Flags |= kOwnsFile; + m_Flags.fetch_or(kOwnsFile, std::memory_order_relaxed); } } @@ -183,7 +184,7 @@ IoBufferExtendedCore::IoBufferExtendedCore(const IoBufferExtendedCore* Outer, ui , m_FileHandle(Outer->m_FileHandle) , m_FileOffset(Outer->m_FileOffset + Offset) { - m_Flags |= kIsOwnedByThis | kIsExtended; + m_Flags.fetch_or(kIsOwnedByThis | kIsExtended, std::memory_order_relaxed); } IoBufferExtendedCore::~IoBufferExtendedCore() @@ -198,14 +199,15 @@ IoBufferExtendedCore::~IoBufferExtendedCore() #endif } + uint32_t LocalFlags = m_Flags.load(std::memory_order_relaxed); #if ZEN_PLATFORM_WINDOWS - if (m_Flags & kOwnsMmap) + if (LocalFlags & kOwnsMmap) { CloseHandle(m_MmapHandle); } #endif - if (m_Flags & kOwnsFile) + if (LocalFlags & kOwnsFile) { #if ZEN_PLATFORM_WINDOWS BOOL Success = CloseHandle(m_FileHandle); @@ -233,43 +235,45 @@ IoBufferExtendedCore::Materialize() const // The synchronization scheme here is very primitive, if we end up with // a lot of contention we can make it more fine-grained - if (m_MmapHandle) + if (m_Flags.load(std::memory_order_acquire) & kIsMaterialized) return; RwLock::ExclusiveLockScope _(g_MappingLock); // Someone could have gotten here first - if (m_MmapHandle) + if (m_Flags.load(std::memory_order_acquire) & kIsMaterialized) return; + uint32_t NewFlags = kIsMaterialized; + const uint64_t MapOffset = m_FileOffset & ~0xffffull; const uint64_t MappedOffsetDisplacement = m_FileOffset - MapOffset; const uint64_t MapSize = m_DataBytes + MappedOffsetDisplacement; #if ZEN_PLATFORM_WINDOWS - m_MmapHandle = CreateFileMapping(m_FileHandle, - /* lpFileMappingAttributes */ nullptr, - /* flProtect */ PAGE_READONLY, - /* dwMaximumSizeLow */ 0, - /* dwMaximumSizeHigh */ 0, - /* lpName */ nullptr); - - if (m_MmapHandle == nullptr) + void* NewMmapHandle = CreateFileMapping(m_FileHandle, + /* lpFileMappingAttributes */ nullptr, + /* flProtect */ PAGE_READONLY, + /* dwMaximumSizeLow */ 0, + /* dwMaximumSizeHigh */ 0, + /* lpName */ nullptr); + + if (NewMmapHandle == nullptr) { throw std::system_error(std::error_code(::GetLastError(), std::system_category()), "CreateFileMapping failed on file '{}'"_format(zen::PathFromHandle(m_FileHandle))); } - m_Flags |= kOwnsMmap; + NewFlags |= kOwnsMmap; - void* MappedBase = MapViewOfFile(m_MmapHandle, + void* MappedBase = MapViewOfFile(NewMmapHandle, /* dwDesiredAccess */ FILE_MAP_READ, /* FileOffsetHigh */ uint32_t(MapOffset >> 32), /* FileOffsetLow */ uint32_t(MapOffset & 0xffFFffFFu), /* dwNumberOfBytesToMap */ MapSize); #else - m_MmapHandle = (void*)uintptr_t(~MapSize); // ~ so it's never null (assuming MapSize >= 0) - m_Flags |= kOwnsMmap; + NewMmapHandle = (void*)uintptr_t(~MapSize); // ~ so it's never null (assuming MapSize >= 0) + NewFlags |= kOwnsMmap; void* MappedBase = mmap( /* addr */ nullptr, @@ -289,8 +293,9 @@ IoBufferExtendedCore::Materialize() const m_MappedPointer = MappedBase; m_DataPtr = reinterpret_cast<uint8_t*>(MappedBase) + MappedOffsetDisplacement; + m_MmapHandle = NewMmapHandle; - m_Flags |= kIsMaterialized; + m_Flags.fetch_or(NewFlags, std::memory_order_release); } bool |