Skip to content

Commit 2ceca7d

Browse files
author
Stjepan Glavina
committed
Fix a deadlock issue
1 parent ea562ce commit 2ceca7d

File tree

1 file changed

+21
-13
lines changed

1 file changed

+21
-13
lines changed

src/lib.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,11 +130,11 @@ impl<T> Lock<T> {
130130
// Lock acquired!
131131
0 => return LockGuard(self.clone()),
132132

133-
// Unlocked and somebody is starved - notify the first waiter in line.
134-
s if s % 2 == 0 => self.0.lock_ops.notify_one(),
133+
// Lock is held and nobody is starved.
134+
1 => {}
135135

136-
// The lock is currently acquired.
137-
_ => {}
136+
// Somebody is starved.
137+
_ => break,
138138
}
139139

140140
// Wait for a notification.
@@ -145,11 +145,16 @@ impl<T> Lock<T> {
145145
// Lock acquired!
146146
0 => return LockGuard(self.clone()),
147147

148-
// Unlocked and somebody is starved - notify the first waiter in line.
149-
s if s % 2 == 0 => self.0.lock_ops.notify_one(),
148+
// Lock is held and nobody is starved.
149+
1 => {}
150150

151-
// The lock is currently acquired.
152-
_ => {}
151+
// Somebody is starved.
152+
_ => {
153+
// Notify the first listener in line because we probably received a
154+
// notification that was meant for a starved thread.
155+
self.0.lock_ops.notify_one();
156+
break;
157+
}
153158
}
154159

155160
// If waiting for too long, fall back to a fairer locking strategy that will prevent
@@ -177,13 +182,16 @@ impl<T> Lock<T> {
177182
// Try locking if nobody else is being starved.
178183
match self.0.state.compare_and_swap(2, 2 | 1, Ordering::Acquire) {
179184
// Lock acquired!
180-
0 => return LockGuard(self.clone()),
185+
2 => return LockGuard(self.clone()),
181186

182-
// Unlocked and somebody is starved - notify the first waiter in line.
183-
s if s % 2 == 0 => self.0.lock_ops.notify_one(),
187+
// Lock is held by someone.
188+
s if s % 2 == 1 => {}
184189

185-
// The lock is currently acquired.
186-
_ => {}
190+
// Lock is available.
191+
_ => {
192+
// Be fair: notify the first listener and then go wait in line.
193+
self.0.lock_ops.notify_one();
194+
}
187195
}
188196

189197
// Wait for a notification.

0 commit comments

Comments
 (0)