aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/threading/light_rw_lock/lightrwlock.h
diff options
context:
space:
mode:
authoragri <agri@yandex-team.ru>2022-02-10 16:48:12 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:48:12 +0300
commit2909866fbc652492b7d7cab3023cb19489dc4fd8 (patch)
treeb222e5ac2e2e98872661c51ccceee5da0d291e13 /library/cpp/threading/light_rw_lock/lightrwlock.h
parentd3530b2692e400bd4d29bd4f07cafaee139164e7 (diff)
downloadydb-2909866fbc652492b7d7cab3023cb19489dc4fd8.tar.gz
Restoring authorship annotation for <agri@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'library/cpp/threading/light_rw_lock/lightrwlock.h')
-rw-r--r--library/cpp/threading/light_rw_lock/lightrwlock.h254
1 files changed, 127 insertions, 127 deletions
diff --git a/library/cpp/threading/light_rw_lock/lightrwlock.h b/library/cpp/threading/light_rw_lock/lightrwlock.h
index 4411787169..931a1817bc 100644
--- a/library/cpp/threading/light_rw_lock/lightrwlock.h
+++ b/library/cpp/threading/light_rw_lock/lightrwlock.h
@@ -1,45 +1,45 @@
-#pragma once
+#pragma once
-#include <util/system/rwlock.h>
+#include <util/system/rwlock.h>
#include <util/system/sanitizers.h>
-
-#if defined(_linux_)
-/* TLightRWLock is optimized for read lock and very fast lock/unlock switching.
- Read lock increments counter.
- Write lock sets highest bit of counter (makes counter negative).
-
- Whenever a thread tries to acquire read lock that thread increments
- the counter. If the thread gets negative value of the counter right just
- after the increment that means write lock was acquired in another thread.
- In that case the thread decrements the counter back, wakes one thread on
- UnshareFutex, waits on the TrappedFutex and then tries acquire read lock
- from the beginning.
- If the thread gets positive value of the counter after the increment
- then read lock was successfully acquired and
- the thread can proceed execution.
-
- Whenever a thread tries to acquire write lock that thread set the highest bit
- of the counter. If the thread determine that the bit was set previously then
- write lock was acquired in another thread. In that case the thread waits on
- the TrappedFutex and then tries again from the beginning.
- If the highest bit was successfully set then thread check if any read lock
- exists at the moment. If so the thread waits on UnshareFutex. If there is
- no more read locks then write lock was successfully acquired and the thread
- can proceed execution.
-*/
-
-#include <linux/futex.h>
+
+#if defined(_linux_)
+/* TLightRWLock is optimized for read lock and very fast lock/unlock switching.
+ Read lock increments counter.
+ Write lock sets highest bit of counter (makes counter negative).
+
+ Whenever a thread tries to acquire read lock that thread increments
+ the counter. If the thread gets negative value of the counter right just
+ after the increment that means write lock was acquired in another thread.
+ In that case the thread decrements the counter back, wakes one thread on
+ UnshareFutex, waits on the TrappedFutex and then tries acquire read lock
+ from the beginning.
+ If the thread gets positive value of the counter after the increment
+ then read lock was successfully acquired and
+ the thread can proceed execution.
+
+ Whenever a thread tries to acquire write lock that thread set the highest bit
+ of the counter. If the thread determine that the bit was set previously then
+ write lock was acquired in another thread. In that case the thread waits on
+ the TrappedFutex and then tries again from the beginning.
+ If the highest bit was successfully set then thread check if any read lock
+ exists at the moment. If so the thread waits on UnshareFutex. If there is
+ no more read locks then write lock was successfully acquired and the thread
+ can proceed execution.
+*/
+
+#include <linux/futex.h>
#include <unistd.h>
-#include <sys/syscall.h>
-#include <errno.h>
-
-namespace NS_LightRWLock {
+#include <sys/syscall.h>
+#include <errno.h>
+
+namespace NS_LightRWLock {
static int Y_FORCE_INLINE AtomicFetchAdd(volatile int& item, int value) {
return __atomic_fetch_add(&item, value, __ATOMIC_SEQ_CST);
}
-
-#if defined(_x86_64_) || defined(_i386_)
-
+
+#if defined(_x86_64_) || defined(_i386_)
+
static char Y_FORCE_INLINE AtomicSetBit(volatile int& item, unsigned bit) {
char ret;
__asm__ __volatile__(
@@ -54,7 +54,7 @@ namespace NS_LightRWLock {
return ret;
}
-
+
static char Y_FORCE_INLINE AtomicClearBit(volatile int& item, unsigned bit) {
char ret;
__asm__ __volatile__(
@@ -69,22 +69,22 @@ namespace NS_LightRWLock {
return ret;
}
-
-
-#else
-
+
+
+#else
+
static char Y_FORCE_INLINE AtomicSetBit(volatile int& item, unsigned bit) {
int prev = __atomic_fetch_or(&item, 1 << bit, __ATOMIC_SEQ_CST);
return (prev & (1 << bit)) != 0 ? 1 : 0;
}
-
+
static char Y_FORCE_INLINE
AtomicClearBit(volatile int& item, unsigned bit) {
int prev = __atomic_fetch_and(&item, ~(1 << bit), __ATOMIC_SEQ_CST);
return (prev & (1 << bit)) != 0 ? 1 : 0;
}
#endif
-
+
#if defined(_x86_64_) || defined(_i386_) || defined (__aarch64__) || defined (__powerpc64__)
static bool AtomicLockHighByte(volatile int& item) {
union TA {
@@ -98,23 +98,23 @@ namespace NS_LightRWLock {
__ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
}
-#endif
-
+#endif
+
template <typename TInt>
static void Y_FORCE_INLINE AtomicStore(volatile TInt& var, TInt value) {
__atomic_store_n(&var, value, __ATOMIC_RELEASE);
}
-
+
template <typename TInt>
static void Y_FORCE_INLINE SequenceStore(volatile TInt& var, TInt value) {
__atomic_store_n(&var, value, __ATOMIC_SEQ_CST);
}
-
+
template <typename TInt>
static TInt Y_FORCE_INLINE AtomicLoad(const volatile TInt& var) {
return __atomic_load_n(&var, __ATOMIC_ACQUIRE);
}
-
+
static void Y_FORCE_INLINE FutexWait(volatile int& fvar, int value) {
for (;;) {
int result =
@@ -126,9 +126,9 @@ namespace NS_LightRWLock {
continue;
Y_FAIL("futex error");
}
- }
- }
-
+ }
+ }
+
static void Y_FORCE_INLINE FutexWake(volatile int& fvar, int amount) {
const int result =
syscall(SYS_futex, &fvar, FUTEX_WAKE_PRIVATE, amount, NULL, NULL, 0);
@@ -136,85 +136,85 @@ namespace NS_LightRWLock {
Y_FAIL("futex error");
}
-}
-
-class alignas(64) TLightRWLock {
-public:
- TLightRWLock(ui32 spinCount = 10)
- : Counter_(0)
- , TrappedFutex_(0)
- , UnshareFutex_(0)
- , SpinCount_(spinCount)
+}
+
+class alignas(64) TLightRWLock {
+public:
+ TLightRWLock(ui32 spinCount = 10)
+ : Counter_(0)
+ , TrappedFutex_(0)
+ , UnshareFutex_(0)
+ , SpinCount_(spinCount)
{
}
-
- TLightRWLock(const TLightRWLock&) = delete;
- void operator=(const TLightRWLock&) = delete;
-
- Y_FORCE_INLINE void AcquireWrite() {
- using namespace NS_LightRWLock;
-
- if (AtomicLockHighByte(Counter_)) {
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
- return;
- return WaitForUntrappedShared();
- }
- WaitForExclusiveAndUntrappedShared();
- }
-
- Y_FORCE_INLINE void AcquireRead() {
- using namespace NS_LightRWLock;
-
- if (Y_LIKELY(AtomicFetchAdd(Counter_, 1) >= 0))
- return;
- WaitForUntrappedAndAcquireRead();
- }
-
- Y_FORCE_INLINE void ReleaseWrite() {
- using namespace NS_LightRWLock;
-
- AtomicClearBit(Counter_, 31);
- if (AtomicLoad(TrappedFutex_)) {
- SequenceStore(TrappedFutex_, 0);
- FutexWake(TrappedFutex_, 0x7fffffff);
- }
- }
-
- Y_FORCE_INLINE void ReleaseRead() {
- using namespace NS_LightRWLock;
-
- if (Y_LIKELY(AtomicFetchAdd(Counter_, -1) >= 0))
- return;
- if (!AtomicLoad(UnshareFutex_))
- return;
- if ((AtomicLoad(Counter_) & 0x7fffffff) == 0) {
- SequenceStore(UnshareFutex_, 0);
- FutexWake(UnshareFutex_, 1);
- }
- }
-
-private:
- volatile int Counter_;
- volatile int TrappedFutex_;
- volatile int UnshareFutex_;
- const ui32 SpinCount_;
-
- void WaitForUntrappedShared();
- void WaitForExclusiveAndUntrappedShared();
- void WaitForUntrappedAndAcquireRead();
-};
-
-#else
-
-class TLightRWLock: public TRWMutex {
-public:
+
+ TLightRWLock(const TLightRWLock&) = delete;
+ void operator=(const TLightRWLock&) = delete;
+
+ Y_FORCE_INLINE void AcquireWrite() {
+ using namespace NS_LightRWLock;
+
+ if (AtomicLockHighByte(Counter_)) {
+ if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
+ return;
+ return WaitForUntrappedShared();
+ }
+ WaitForExclusiveAndUntrappedShared();
+ }
+
+ Y_FORCE_INLINE void AcquireRead() {
+ using namespace NS_LightRWLock;
+
+ if (Y_LIKELY(AtomicFetchAdd(Counter_, 1) >= 0))
+ return;
+ WaitForUntrappedAndAcquireRead();
+ }
+
+ Y_FORCE_INLINE void ReleaseWrite() {
+ using namespace NS_LightRWLock;
+
+ AtomicClearBit(Counter_, 31);
+ if (AtomicLoad(TrappedFutex_)) {
+ SequenceStore(TrappedFutex_, 0);
+ FutexWake(TrappedFutex_, 0x7fffffff);
+ }
+ }
+
+ Y_FORCE_INLINE void ReleaseRead() {
+ using namespace NS_LightRWLock;
+
+ if (Y_LIKELY(AtomicFetchAdd(Counter_, -1) >= 0))
+ return;
+ if (!AtomicLoad(UnshareFutex_))
+ return;
+ if ((AtomicLoad(Counter_) & 0x7fffffff) == 0) {
+ SequenceStore(UnshareFutex_, 0);
+ FutexWake(UnshareFutex_, 1);
+ }
+ }
+
+private:
+ volatile int Counter_;
+ volatile int TrappedFutex_;
+ volatile int UnshareFutex_;
+ const ui32 SpinCount_;
+
+ void WaitForUntrappedShared();
+ void WaitForExclusiveAndUntrappedShared();
+ void WaitForUntrappedAndAcquireRead();
+};
+
+#else
+
+class TLightRWLock: public TRWMutex {
+public:
TLightRWLock() {
}
TLightRWLock(ui32) {
}
-};
-
-#endif
-
-using TLightReadGuard = TReadGuardBase<TLightRWLock>;
-using TLightWriteGuard = TWriteGuardBase<TLightRWLock>;
+};
+
+#endif
+
+using TLightReadGuard = TReadGuardBase<TLightRWLock>;
+using TLightWriteGuard = TWriteGuardBase<TLightRWLock>;