123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- #include "lightrwlock.h"
- #include <util/system/spinlock.h>
- #if defined(_linux_) && !defined(_tsan_enabled_)
- using namespace NS_LightRWLock;
- void TLightRWLock::WaitForUntrappedShared() {
- for (;;) {
- for (ui32 i = 0; i < SpinCount_; ++i) {
- SpinLockPause();
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
- return;
- }
- SequenceStore(UnshareFutex_, 1);
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
- AtomicStore(UnshareFutex_, 0);
- return;
- }
- FutexWait(UnshareFutex_, 1);
- }
- }
- void TLightRWLock::WaitForExclusiveAndUntrappedShared() {
- for (;;) {
- for (ui32 i = 0; i < SpinCount_; ++i) {
- SpinLockPause();
- if (AtomicLoad(Counter_) >= 0)
- goto try_to_get_lock;
- if (AtomicLoad(TrappedFutex_) == 1)
- goto skip_store_trapped;
- }
- SequenceStore(TrappedFutex_, 1);
- skip_store_trapped:
- if (AtomicLoad(Counter_) < 0) {
- FutexWait(TrappedFutex_, 1);
- }
- try_to_get_lock:
- if (!AtomicSetBit(Counter_, 31))
- break;
- }
- for (;;) {
- for (ui32 i = 0; i < SpinCount_; ++i) {
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0)
- return;
- SpinLockPause();
- }
- SequenceStore(UnshareFutex_, 1);
- if ((AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
- AtomicStore(UnshareFutex_, 0);
- return;
- }
- FutexWait(UnshareFutex_, 1);
- }
- }
- void TLightRWLock::WaitForUntrappedAndAcquireRead() {
- if (AtomicFetchAdd(Counter_, -1) < 0)
- goto skip_lock_try;
- for (;;) {
- again:
- if (Y_UNLIKELY(AtomicFetchAdd(Counter_, 1) >= 0)) {
- return;
- } else {
- if (AtomicFetchAdd(Counter_, -1) >= 0)
- goto again;
- }
- skip_lock_try:
- if (AtomicLoad(UnshareFutex_) && (AtomicLoad(Counter_) & 0x7FFFFFFF) == 0) {
- SequenceStore(UnshareFutex_, 0);
- FutexWake(UnshareFutex_, 1);
- }
- for (;;) {
- for (ui32 i = 0; i < SpinCount_; ++i) {
- SpinLockPause();
- if (AtomicLoad(Counter_) >= 0)
- goto again;
- if (AtomicLoad(TrappedFutex_) == 1)
- goto skip_store_trapped;
- }
- SequenceStore(TrappedFutex_, 1);
- skip_store_trapped:
- if (AtomicLoad(Counter_) < 0) {
- FutexWait(TrappedFutex_, 1);
- if (AtomicLoad(Counter_) < 0)
- goto again;
- } else if (AtomicLoad(TrappedFutex_)) {
- SequenceStore(TrappedFutex_, 0);
- FutexWake(TrappedFutex_, 0x7fffffff);
- }
- break;
- }
- }
- }
- #endif // _linux_
|