Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5703d4d

Browse files
committed
Use spinlock for ThreadId if 64-bit atomic unavailable
1 parent ceb1945 commit 5703d4d

File tree

1 file changed

+36
-12
lines changed

1 file changed

+36
-12
lines changed

‎library/std/src/thread/mod.rs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,21 +1232,45 @@ impl ThreadId {
12321232
}
12331233
}
12341234
_ => {
1235-
use crate::sync::{Mutex, PoisonError};
1236-
1237-
static COUNTER: Mutex<u64> = Mutex::new(0);
1235+
use crate::cell::SyncUnsafeCell;
1236+
use crate::hint::spin_loop;
1237+
use crate::sync::atomic::{Atomic, AtomicBool};
1238+
use crate::thread::yield_now;
1239+
1240+
// If we don't have a 64-bit atomic we use a small spinlock. We don't use Mutex
1241+
// here as we might be trying to get the current thread id in the global allocator,
1242+
// and on some platforms Mutex requires allocation.
1243+
static COUNTER_LOCKED: Atomic<bool> = AtomicBool::new(false);
1244+
static COUNTER: SyncUnsafeCell<u64> = SyncUnsafeCell::new(0);
1245+
1246+
// Acquire lock.
1247+
let mut spin = 0;
1248+
while COUNTER_LOCKED.compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed).is_err() {
1249+
if spin <= 3 {
1250+
for _ in 0..(1 << spin) {
1251+
spin_loop();
1252+
}
1253+
} else {
1254+
yield_now();
1255+
}
1256+
spin += 1;
1257+
}
12381258

1239-
let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner);
1240-
let Some(id) = counter.checked_add(1) else {
1241-
// in case the panic handler ends up calling `ThreadId::new()`,
1242-
// avoid reentrant lock acquire.
1243-
drop(counter);
1244-
exhausted();
1259+
let id;
1260+
// SAFETY: we have an exclusive lock on the counter.
1261+
unsafe {
1262+
id = (*COUNTER.get()).saturating_add(1);
1263+
(*COUNTER.get()) = id;
12451264
};
12461265

1247-
*counter = id;
1248-
drop(counter);
1249-
ThreadId(NonZero::new(id).unwrap())
1266+
// Release the lock.
1267+
COUNTER_LOCKED.store(false, Ordering::Release);
1268+
1269+
if id == u64::MAX {
1270+
exhausted()
1271+
} else {
1272+
ThreadId(NonZero::new(id).unwrap())
1273+
}
12501274
}
12511275
}
12521276
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /