aboutsummaryrefslogtreecommitdiff
path: root/zencore/iobuffer.cpp
diff options
context:
space:
mode:
authorMatt Peters <[email protected]>2021-12-02 21:16:55 -0700
committerMatt Peters <[email protected]>2021-12-02 21:16:55 -0700
commitc9d52890cd98aaf2ec46a726d323169ca724a1dd (patch)
treead9c6c45540336c7298b857273a30b58cc6b645a /zencore/iobuffer.cpp
parentMerge pull request #31 from EpicGames/non-elevated-asio (diff)
downloadzen-c9d52890cd98aaf2ec46a726d323169ca724a1dd.tar.xz
zen-c9d52890cd98aaf2ec46a726d323169ca724a1dd.zip
Make IoBufferCore::Materialize threadsafe
Diffstat (limited to 'zencore/iobuffer.cpp')
-rw-r--r--zencore/iobuffer.cpp53
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