mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-08 17:54:22 +01:00
Merge 'LimboRwLock write and read lock fixes' from Pere Diaz Bou
* `write` was returning `true` even though it shouldn't because it
should return `false` in case it was already acquired.
* `read` theoritically can increase `nread` after another thread calls
`unlock` between first lock load and increase of `nread`. So it looks
something like this:
1. THREAD 1: read()
2. THREAD 2: get lock = `SHARED_LOCK`
3. THREAD 1: unlock -> lock is now `NO_LOCK`
4. THREAD 2: increase nread, return true.
This is obviously wrong because `nreads` will be ` > 0 ` but `lock`
is `NO_LOCK`
Closes #1676
This commit is contained in:
@@ -106,8 +106,30 @@ impl LimboRwLock {
|
||||
ok
|
||||
}
|
||||
SHARED_LOCK => {
|
||||
// There is this race condition where we could've unlocked after loading lock ==
|
||||
// SHARED_LOCK.
|
||||
self.nreads.fetch_add(1, Ordering::SeqCst);
|
||||
true
|
||||
let lock_after_load = self.lock.load(Ordering::SeqCst);
|
||||
if lock_after_load != lock {
|
||||
// try to lock it again
|
||||
let res = self.lock.compare_exchange(
|
||||
lock_after_load,
|
||||
SHARED_LOCK,
|
||||
Ordering::SeqCst,
|
||||
Ordering::SeqCst,
|
||||
);
|
||||
let ok = res.is_ok();
|
||||
if ok {
|
||||
// we were able to acquire it back
|
||||
true
|
||||
} else {
|
||||
// we couldn't acquire it back, reduce number again
|
||||
self.nreads.fetch_sub(1, Ordering::SeqCst);
|
||||
false
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
WRITE_LOCK => false,
|
||||
_ => unreachable!(),
|
||||
@@ -133,7 +155,7 @@ impl LimboRwLock {
|
||||
// no op
|
||||
false
|
||||
}
|
||||
WRITE_LOCK => true,
|
||||
WRITE_LOCK => false,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
tracing::trace!("write_lock({})", ok);
|
||||
|
||||
Reference in New Issue
Block a user