[+] 32bit SOO sizes for sync primitives under x86_32/MSVC
[*] Optimize the write-biased reentrant read-write lock down to 88 bytes on MSVC x64
This commit is contained in:
parent
451b9025c0
commit
2d6dca4e21
@ -14,41 +14,75 @@
|
||||
|
||||
namespace Aurora::Threading::Primitives
|
||||
{
|
||||
static const auto kDefaultPrimitiveSize = 128;
|
||||
static const auto kDefaultPrimitiveSize64 = 128;
|
||||
|
||||
static const auto kPrimitiveSizeNTMutex = 16;
|
||||
static const auto kPrimitiveSizeNTSemaphore = 64;
|
||||
static const auto kPrimitiveSizeNTCS = 32;
|
||||
static const auto kPrimitiveSizeNTEvent = 64;
|
||||
static const auto kPrimitiveSizeNTRWLock = 104;
|
||||
static const auto kPrimitiveSizeNTCond = 32;
|
||||
static const auto kPrimitiveSizeNTCondMutex = 16;
|
||||
static const auto kPrimitiveSize64NTMutex = 16;
|
||||
static const auto kPrimitiveSize64NTSemaphore = 64;
|
||||
static const auto kPrimitiveSize64NTCS = 32;
|
||||
static const auto kPrimitiveSize64NTEvent = 64;
|
||||
static const auto kPrimitiveSize64NTRWLock = 88;
|
||||
static const auto kPrimitiveSize64NTCond = 32;
|
||||
static const auto kPrimitiveSize64NTCondMutex = 16;
|
||||
|
||||
static const auto kPrimitiveSize32NTMutex = 8;
|
||||
static const auto kPrimitiveSize32NTSemaphore = 36;
|
||||
static const auto kPrimitiveSize32NTCS = 20;
|
||||
static const auto kPrimitiveSize32NTEvent = 36;
|
||||
static const auto kPrimitiveSize32NTRWLock = 56;
|
||||
static const auto kPrimitiveSize32NTCond = 20;
|
||||
static const auto kPrimitiveSize32NTCondMutex = 8;
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
|
||||
static const auto kPrimitiveSizeMutex = kPrimitiveSizeNTMutex;
|
||||
static const auto kPrimitiveSizeSemaphore = kPrimitiveSizeNTSemaphore;
|
||||
static const auto kPrimitiveSizeCS = kPrimitiveSizeNTCS;
|
||||
static const auto kPrimitiveSizeEvent = kPrimitiveSizeNTEvent;
|
||||
static const auto kPrimitiveSizeRWLock = kPrimitiveSizeNTRWLock;
|
||||
static const auto kPrimitiveSizeCond = kPrimitiveSizeNTCond;
|
||||
static const auto kPrimitiveSizeCondMutex = kPrimitiveSizeNTCondMutex;
|
||||
|
||||
// fuck you, its time to overtake the STL in even Windows 11 micro-benchmarks
|
||||
#define AURT_ENABLE_HYPER_MUTEX
|
||||
static const auto kPrimitiveSize64Mutex = kPrimitiveSize64NTMutex;
|
||||
static const auto kPrimitiveSize64Semaphore = kPrimitiveSize64NTSemaphore;
|
||||
static const auto kPrimitiveSize64CS = kPrimitiveSize64NTCS;
|
||||
static const auto kPrimitiveSize64Event = kPrimitiveSize64NTEvent;
|
||||
static const auto kPrimitiveSize64RWLock = kPrimitiveSize64NTRWLock;
|
||||
static const auto kPrimitiveSize64Cond = kPrimitiveSize64NTCond;
|
||||
static const auto kPrimitiveSize64CondMutex = kPrimitiveSize64NTCondMutex;
|
||||
|
||||
//#elif defined(AURORA_IS_LINUX_DERIVED)
|
||||
//
|
||||
static const auto kPrimitiveSize32Mutex = kPrimitiveSize32NTMutex;
|
||||
static const auto kPrimitiveSize32Semaphore = kPrimitiveSize32NTSemaphore;
|
||||
static const auto kPrimitiveSize32CS = kPrimitiveSize32NTCS;
|
||||
static const auto kPrimitiveSize32Event = kPrimitiveSize32NTEvent;
|
||||
static const auto kPrimitiveSize32RWLock = kPrimitiveSize32NTRWLock;
|
||||
static const auto kPrimitiveSize32Cond = kPrimitiveSize32NTCond;
|
||||
static const auto kPrimitiveSize32CondMutex = kPrimitiveSize32NTCondMutex;
|
||||
|
||||
#define AURT_ENABLE_HYPER_MUTEX
|
||||
|
||||
#else
|
||||
|
||||
static const auto kPrimitiveSizeMutex = kDefaultPrimitiveSize;
|
||||
static const auto kPrimitiveSizeSemaphore = kDefaultPrimitiveSize;
|
||||
static const auto kPrimitiveSizeCS = kDefaultPrimitiveSize;
|
||||
static const auto kPrimitiveSizeEvent = kDefaultPrimitiveSize;
|
||||
static const auto kPrimitiveSizeRWLock = kDefaultPrimitiveSize;
|
||||
static const auto kPrimitiveSizeCond = kDefaultPrimitiveSize;
|
||||
static const auto kPrimitiveSizeCondMutex = kDefaultPrimitiveSize;
|
||||
static const auto kPrimitiveSize64Mutex = kDefaultPrimitiveSize64;
|
||||
static const auto kPrimitiveSize64Semaphore = kDefaultPrimitiveSize64;
|
||||
static const auto kPrimitiveSize64CS = kDefaultPrimitiveSize64;
|
||||
static const auto kPrimitiveSize64Event = kDefaultPrimitiveSize64;
|
||||
static const auto kPrimitiveSize64RWLock = kDefaultPrimitiveSize64;
|
||||
static const auto kPrimitiveSize64Cond = kDefaultPrimitiveSize64;
|
||||
static const auto kPrimitiveSize64CondMutex = kDefaultPrimitiveSize64;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_64BIT)
|
||||
|
||||
static const auto kPrimitiveSizeMutex = kPrimitiveSize64Mutex;
|
||||
static const auto kPrimitiveSizeSemaphore = kPrimitiveSize64Semaphore;
|
||||
static const auto kPrimitiveSizeCS = kPrimitiveSize64CS;
|
||||
static const auto kPrimitiveSizeEvent = kPrimitiveSize64Event;
|
||||
static const auto kPrimitiveSizeRWLock = kPrimitiveSize64RWLock;
|
||||
static const auto kPrimitiveSizeCond = kPrimitiveSize64Cond;
|
||||
static const auto kPrimitiveSizeCondMutex = kPrimitiveSize64CondMutex;
|
||||
|
||||
#else
|
||||
|
||||
static const auto kPrimitiveSizeMutex = kPrimitiveSize32Mutex;
|
||||
static const auto kPrimitiveSizeSemaphore = kPrimitiveSize32Semaphore;
|
||||
static const auto kPrimitiveSizeCS = kPrimitiveSize32CS;
|
||||
static const auto kPrimitiveSizeEvent = kPrimitiveSize32Event;
|
||||
static const auto kPrimitiveSizeRWLock = kPrimitiveSize32RWLock;
|
||||
static const auto kPrimitiveSizeCond = kPrimitiveSize32Cond;
|
||||
static const auto kPrimitiveSizeCondMutex = kPrimitiveSize32CondMutex;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -6,21 +6,29 @@
|
||||
Author: Reece
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
//#define RWLOCK_VIEW_HAS_PARENT
|
||||
#include "AuRWLock.hpp"
|
||||
#include "SMTYield.hpp"
|
||||
|
||||
namespace Aurora::Threading::Primitives
|
||||
{
|
||||
#if defined(RWLOCK_VIEW_HAS_PARENT)
|
||||
#define ViewParent (&this->parent_)
|
||||
#else
|
||||
#define ViewParent ((T *)(((char *)this) - (bIsReadView ? RWLockImpl<true>::kOffsetOfRead : RWLockImpl<true>::kOffsetOfWrite)))
|
||||
#endif
|
||||
|
||||
template<bool bIsReadView, typename T>
|
||||
void RWLockAccessView<bIsReadView, T>::Unlock()
|
||||
{
|
||||
|
||||
if constexpr (bIsReadView)
|
||||
{
|
||||
this->parent_.UnlockRead();
|
||||
ViewParent->UnlockRead();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->parent_.UnlockWrite();
|
||||
ViewParent->UnlockWrite();
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,11 +37,11 @@ namespace Aurora::Threading::Primitives
|
||||
{
|
||||
if constexpr (bIsReadView)
|
||||
{
|
||||
return this->parent_.LockReadNS(AuMSToNS<AuUInt64>(timeout));
|
||||
return ViewParent->LockReadNS(AuMSToNS<AuUInt64>(timeout));
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->parent_.LockWriteNS(AuMSToNS<AuUInt64>(timeout));
|
||||
return ViewParent->LockWriteNS(AuMSToNS<AuUInt64>(timeout));
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,11 +50,11 @@ namespace Aurora::Threading::Primitives
|
||||
{
|
||||
if constexpr (bIsReadView)
|
||||
{
|
||||
return this->parent_.LockReadNS(timeout);
|
||||
return ViewParent->LockReadNS(timeout);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->parent_.LockWriteNS(timeout);
|
||||
return ViewParent->LockWriteNS(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,18 +63,20 @@ namespace Aurora::Threading::Primitives
|
||||
{
|
||||
if constexpr (bIsReadView)
|
||||
{
|
||||
return this->parent_.TryLockRead();
|
||||
return ViewParent->TryLockRead();
|
||||
}
|
||||
else
|
||||
{
|
||||
return this->parent_.TryLockWrite();
|
||||
return ViewParent->TryLockWrite();
|
||||
}
|
||||
}
|
||||
|
||||
template<bool bIsWriteRecursionAllowed>
|
||||
RWLockImpl<bIsWriteRecursionAllowed>::RWLockImpl() :
|
||||
read_(*this),
|
||||
RWLockImpl<bIsWriteRecursionAllowed>::RWLockImpl()
|
||||
#if defined(RWLOCK_VIEW_HAS_PARENT)
|
||||
: read_(*this),
|
||||
write_(*this)
|
||||
#endif
|
||||
#if 0
|
||||
, condition_(AuUnsafeRaiiToShared(&this->mutex_)),
|
||||
conditionWriter_(AuUnsafeRaiiToShared(&this->mutex_))
|
||||
@ -80,13 +90,6 @@ namespace Aurora::Threading::Primitives
|
||||
{
|
||||
}
|
||||
|
||||
template<bool bIsWriteRecursionAllowed>
|
||||
bool RWLockImpl<bIsWriteRecursionAllowed>::Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<bool bIsWriteRecursionAllowed>
|
||||
ConditionVariableImpl &RWLockImpl<bIsWriteRecursionAllowed>::GetCondition()
|
||||
{
|
||||
@ -220,9 +223,9 @@ namespace Aurora::Threading::Primitives
|
||||
|
||||
#if defined(AURWLOCK_NO_SIZE_OPTIMIZED_CONDVAR)
|
||||
if (!this->GetConditionWriter().WaitForSignalNS(uSecondTimeout))
|
||||
#else
|
||||
#else
|
||||
if (!this->GetConditionWriter().WaitForSignalNsEx(AuUnsafeRaiiToShared(&this->mutex_), uSecondTimeout))
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
this->writersPending_--;
|
||||
return false;
|
||||
@ -407,12 +410,6 @@ namespace Aurora::Threading::Primitives
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!pRwLock->Init())
|
||||
{
|
||||
delete pRwLock;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pRwLock;
|
||||
}
|
||||
|
||||
@ -429,12 +426,6 @@ namespace Aurora::Threading::Primitives
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!pRwLock->Init())
|
||||
{
|
||||
delete pRwLock;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pRwLock;
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,13 @@ namespace Aurora::Threading::Primitives
|
||||
template<bool bIsReadView, typename T>
|
||||
struct RWLockAccessView : IWaitable
|
||||
{
|
||||
RWLockAccessView(T &impl) : parent_(impl)
|
||||
#if defined(RWLOCK_VIEW_HAS_PARENT)
|
||||
RWLockAccessView(T &impl) :
|
||||
parent_(impl)
|
||||
{
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
bool LockMS(AuUInt64 timeout) override;
|
||||
bool LockNS(AuUInt64 timeout) override;
|
||||
@ -47,7 +50,9 @@ namespace Aurora::Threading::Primitives
|
||||
void Unlock() override;
|
||||
|
||||
private:
|
||||
#if defined(RWLOCK_VIEW_HAS_PARENT)
|
||||
T &parent_;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<bool bIsWriteRecursionAllowed>
|
||||
@ -70,16 +75,11 @@ namespace Aurora::Threading::Primitives
|
||||
IWaitable *AsReadable() override;
|
||||
IWaitable *AsWritable() override;
|
||||
|
||||
bool Init();
|
||||
|
||||
auline ConditionVariableImpl &GetCondition();
|
||||
auline ConditionVariableImpl &GetConditionWriter();
|
||||
|
||||
private:
|
||||
|
||||
//bool reentrantWriteLock_ {true};
|
||||
ThreadCookie_t reentrantWriteLockHandle_ {};
|
||||
|
||||
RWLockAccessView<true, RWLockImpl> read_;
|
||||
RWLockAccessView<false, RWLockImpl> write_;
|
||||
|
||||
@ -91,9 +91,15 @@ namespace Aurora::Threading::Primitives
|
||||
char conditionVariable_[kSizeOfDummyCondVar] {};
|
||||
char conditionVariableWriter_[kSizeOfDummyCondVar] {};
|
||||
#endif
|
||||
ThreadCookie_t reentrantWriteLockHandle_ {};
|
||||
volatile AuInt32 state_ {};
|
||||
AuInt32 writersPending_ : 31 {};
|
||||
AuInt32 bElevaterPending_ : 1 {};
|
||||
//bool bElevaterPending_{};
|
||||
//bool reentrantWriteLock_ {true};
|
||||
|
||||
public:
|
||||
cstatic const AuUInt8 kOffsetOfRead = AuOffsetOf(&RWLockImpl::read_);
|
||||
cstatic const AuUInt8 kOffsetOfWrite = AuOffsetOf(&RWLockImpl::write_);
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user