Skip to content

Commit df2ef1d

Browse files
committed
Migrate standard library away from compare_and_swap
1 parent 7bd770c commit df2ef1d

File tree

15 files changed

+79
-36
lines changed

15 files changed

+79
-36
lines changed

library/core/tests/atomic.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ use core::sync::atomic::*;
44
#[test]
55
fn bool_() {
66
let a = AtomicBool::new(false);
7-
assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
8-
assert_eq!(a.compare_and_swap(false, true, SeqCst), true);
7+
assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false));
8+
assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Err(true));
99

1010
a.store(false, SeqCst);
11-
assert_eq!(a.compare_and_swap(false, true, SeqCst), false);
11+
assert_eq!(a.compare_exchange(false, true, SeqCst, SeqCst), Ok(false));
1212
}
1313

1414
#[test]

library/std/src/sync/mpsc/blocking.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ pub fn tokens() -> (WaitToken, SignalToken) {
3636

3737
impl SignalToken {
3838
pub fn signal(&self) -> bool {
39-
let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
39+
let wake = self
40+
.inner
41+
.woken
42+
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
43+
.is_ok();
4044
if wake {
4145
self.inner.thread.unpark();
4246
}

library/std/src/sync/mpsc/oneshot.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ impl<T> Packet<T> {
129129
let ptr = unsafe { signal_token.cast_to_usize() };
130130

131131
// race with senders to enter the blocking state
132-
if self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) == EMPTY {
132+
if self.state.compare_exchange(EMPTY, ptr, Ordering::SeqCst, Ordering::SeqCst).is_ok() {
133133
if let Some(deadline) = deadline {
134134
let timed_out = !wait_token.wait_max_until(deadline);
135135
// Try to reset the state
@@ -161,7 +161,12 @@ impl<T> Packet<T> {
161161
// the state changes under our feet we'd rather just see that state
162162
// change.
163163
DATA => {
164-
self.state.compare_and_swap(DATA, EMPTY, Ordering::SeqCst);
164+
let _ = self.state.compare_exchange(
165+
DATA,
166+
EMPTY,
167+
Ordering::SeqCst,
168+
Ordering::SeqCst,
169+
);
165170
match (&mut *self.data.get()).take() {
166171
Some(data) => Ok(data),
167172
None => unreachable!(),
@@ -264,7 +269,10 @@ impl<T> Packet<T> {
264269

265270
// If we've got a blocked thread, then use an atomic to gain ownership
266271
// of it (may fail)
267-
ptr => self.state.compare_and_swap(ptr, EMPTY, Ordering::SeqCst),
272+
ptr => self
273+
.state
274+
.compare_exchange(ptr, EMPTY, Ordering::SeqCst, Ordering::SeqCst)
275+
.unwrap_or_else(|x| x),
268276
};
269277

270278
// Now that we've got ownership of our state, figure out what to do

library/std/src/sync/mpsc/shared.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,15 @@ impl<T> Packet<T> {
385385
self.port_dropped.store(true, Ordering::SeqCst);
386386
let mut steals = unsafe { *self.steals.get() };
387387
while {
388-
let cnt = self.cnt.compare_and_swap(steals, DISCONNECTED, Ordering::SeqCst);
389-
cnt != DISCONNECTED && cnt != steals
388+
match self.cnt.compare_exchange(
389+
steals,
390+
DISCONNECTED,
391+
Ordering::SeqCst,
392+
Ordering::SeqCst,
393+
) {
394+
Ok(_) => false,
395+
Err(old) => old != DISCONNECTED,
396+
}
390397
} {
391398
// See the discussion in 'try_recv' for why we yield
392399
// control of this thread.

library/std/src/sync/mpsc/stream.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -322,12 +322,15 @@ impl<T> Packet<T> {
322322
// (because there is a bounded number of senders).
323323
let mut steals = unsafe { *self.queue.consumer_addition().steals.get() };
324324
while {
325-
let cnt = self.queue.producer_addition().cnt.compare_and_swap(
325+
match self.queue.producer_addition().cnt.compare_exchange(
326326
steals,
327327
DISCONNECTED,
328328
Ordering::SeqCst,
329-
);
330-
cnt != DISCONNECTED && cnt != steals
329+
Ordering::SeqCst,
330+
) {
331+
Ok(_) => false,
332+
Err(old) => old != DISCONNECTED,
333+
}
331334
} {
332335
while self.queue.pop().is_some() {
333336
steals += 1;

library/std/src/sync/once.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
// must do so with Release ordering to make the result available.
6666
// - `wait` inserts `Waiter` nodes as a pointer in `state_and_queue`, and
6767
// needs to make the nodes available with Release ordering. The load in
68-
// its `compare_and_swap` can be Relaxed because it only has to compare
68+
// its `compare_exchange` can be Relaxed because it only has to compare
6969
// the atomic, not to read other data.
7070
// - `WaiterQueue::Drop` must see the `Waiter` nodes, so it must load
7171
// `state_and_queue` with Acquire ordering.
@@ -395,12 +395,13 @@ impl Once {
395395
}
396396
POISONED | INCOMPLETE => {
397397
// Try to register this thread as the one RUNNING.
398-
let old = self.state_and_queue.compare_and_swap(
398+
let exchange_result = self.state_and_queue.compare_exchange(
399399
state_and_queue,
400400
RUNNING,
401401
Ordering::Acquire,
402+
Ordering::Acquire,
402403
);
403-
if old != state_and_queue {
404+
if let Err(old) = exchange_result {
404405
state_and_queue = old;
405406
continue;
406407
}
@@ -452,8 +453,13 @@ fn wait(state_and_queue: &AtomicUsize, mut current_state: usize) {
452453

453454
// Try to slide in the node at the head of the linked list, making sure
454455
// that another thread didn't just replace the head of the linked list.
455-
let old = state_and_queue.compare_and_swap(current_state, me | RUNNING, Ordering::Release);
456-
if old != current_state {
456+
let exchange_result = state_and_queue.compare_exchange(
457+
current_state,
458+
me | RUNNING,
459+
Ordering::Release,
460+
Ordering::Relaxed,
461+
);
462+
if let Err(old) = exchange_result {
457463
current_state = old;
458464
continue;
459465
}

library/std/src/sys/sgx/abi/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,20 @@ unsafe extern "C" fn tcs_init(secondary: bool) {
3636
}
3737

3838
// Try to atomically swap UNINIT with BUSY. The returned state can be:
39-
match RELOC_STATE.compare_and_swap(UNINIT, BUSY, Ordering::Acquire) {
39+
match RELOC_STATE.compare_exchange(UNINIT, BUSY, Ordering::Acquire, Ordering::Acquire) {
4040
// This thread just obtained the lock and other threads will observe BUSY
41-
UNINIT => {
41+
Ok(_) => {
4242
reloc::relocate_elf_rela();
4343
RELOC_STATE.store(DONE, Ordering::Release);
4444
}
4545
// We need to wait until the initialization is done.
46-
BUSY => {
46+
Err(BUSY) => {
4747
while RELOC_STATE.load(Ordering::Acquire) == BUSY {
4848
core::hint::spin_loop();
4949
}
5050
}
5151
// Initialization is done.
52-
DONE => {}
52+
Err(DONE) => {}
5353
_ => unreachable!(),
5454
}
5555
}

library/std/src/sys/sgx/waitqueue/spin_mutex.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl<T> SpinMutex<T> {
4242

4343
#[inline(always)]
4444
pub fn try_lock(&self) -> Option<SpinMutexGuard<'_, T>> {
45-
if !self.lock.compare_and_swap(false, true, Ordering::Acquire) {
45+
if self.lock.compare_exchange(false, true, Ordering::Acquire, Ordering::Acquire).is_ok() {
4646
Some(SpinMutexGuard { mutex: self })
4747
} else {
4848
None

library/std/src/sys/windows/mutex.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ impl Mutex {
123123
let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
124124
inner.remutex.init();
125125
let inner = Box::into_raw(inner);
126-
match self.lock.compare_and_swap(0, inner as usize, Ordering::SeqCst) {
127-
0 => inner,
128-
n => {
126+
match self.lock.compare_exchange(0, inner as usize, Ordering::SeqCst, Ordering::SeqCst) {
127+
Ok(_) => inner,
128+
Err(n) => {
129129
Box::from_raw(inner).remutex.destroy();
130130
n as *const _
131131
}

library/std/src/sys_common/condvar/check.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ impl SameMutexCheck {
2323
}
2424
pub fn verify(&self, mutex: &MovableMutex) {
2525
let addr = mutex.raw() as *const mutex_imp::Mutex as usize;
26-
match self.addr.compare_and_swap(0, addr, Ordering::SeqCst) {
27-
0 => {} // Stored the address
28-
n if n == addr => {} // Lost a race to store the same address
26+
match self.addr.compare_exchange(0, addr, Ordering::SeqCst, Ordering::SeqCst) {
27+
Ok(_) => {} // Stored the address
28+
Err(n) if n == addr => {} // Lost a race to store the same address
2929
_ => panic!("attempted to use a condition variable with two mutexes"),
3030
}
3131
}

library/std/src/sys_common/thread_local_key.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl StaticKey {
168168
return key;
169169
}
170170

171-
// POSIX allows the key created here to be 0, but the compare_and_swap
171+
// POSIX allows the key created here to be 0, but the compare_exchange
172172
// below relies on using 0 as a sentinel value to check who won the
173173
// race to set the shared TLS key. As far as I know, there is no
174174
// guaranteed value that cannot be returned as a posix_key_create key,
@@ -186,11 +186,11 @@ impl StaticKey {
186186
key2
187187
};
188188
rtassert!(key != 0);
189-
match self.key.compare_and_swap(0, key as usize, Ordering::SeqCst) {
189+
match self.key.compare_exchange(0, key as usize, Ordering::SeqCst, Ordering::SeqCst) {
190190
// The CAS succeeded, so we've created the actual key
191-
0 => key as usize,
191+
Ok(_) => key as usize,
192192
// If someone beat us to the punch, use their key instead
193-
n => {
193+
Err(n) => {
194194
imp::destroy(key);
195195
n
196196
}

library/std/src/sys_common/thread_parker/futex.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ impl Parker {
4949
// Wait for something to happen, assuming it's still set to PARKED.
5050
futex_wait(&self.state, PARKED, None);
5151
// Change NOTIFIED=>EMPTY and return in that case.
52-
if self.state.compare_and_swap(NOTIFIED, EMPTY, Acquire) == NOTIFIED {
52+
if self.state.compare_exchange_weak(NOTIFIED, EMPTY, Acquire, Acquire).is_ok() {
5353
return;
5454
} else {
5555
// Spurious wake up. We loop to try again.

src/test/ui/array-slice-vec/box-of-array-of-drop-1.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ impl Drop for D {
1717
fn drop(&mut self) {
1818
println!("Dropping {}", self.0);
1919
let old = LOG.load(Ordering::SeqCst);
20-
LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst);
20+
let _ = LOG.compare_exchange(
21+
old,
22+
old << 4 | self.0 as usize,
23+
Ordering::SeqCst,
24+
Ordering::SeqCst
25+
);
2126
}
2227
}
2328

src/test/ui/array-slice-vec/box-of-array-of-drop-2.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ impl Drop for D {
1717
fn drop(&mut self) {
1818
println!("Dropping {}", self.0);
1919
let old = LOG.load(Ordering::SeqCst);
20-
LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst);
20+
let _ = LOG.compare_exchange(
21+
old,
22+
old << 4 | self.0 as usize,
23+
Ordering::SeqCst,
24+
Ordering::SeqCst
25+
);
2126
}
2227
}
2328

src/test/ui/array-slice-vec/nested-vec-3.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ impl Drop for D {
1818
fn drop(&mut self) {
1919
println!("Dropping {}", self.0);
2020
let old = LOG.load(Ordering::SeqCst);
21-
LOG.compare_and_swap(old, old << 4 | self.0 as usize, Ordering::SeqCst);
21+
let _ = LOG.compare_exchange(
22+
old,
23+
old << 4 | self.0 as usize,
24+
Ordering::SeqCst,
25+
Ordering::SeqCst,
26+
);
2227
}
2328
}
2429

0 commit comments

Comments
 (0)