Skip to content

Commit 67c2ddd

Browse files
committed
std: use a mutex for ThreadId generation if available
1 parent 3ff30e7 commit 67c2ddd

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

library/std/src/thread/current.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ pub(super) mod id {
108108
get().unwrap_or_else(
109109
#[cold]
110110
|| {
111-
let id = ThreadId::new();
111+
let id = ThreadId::desperate_new();
112112
id::set(id);
113113
id
114114
},

library/std/src/thread/id.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,15 @@ use crate::sync::atomic::{Atomic, Ordering};
3131
pub struct ThreadId(NonZero<u64>);
3232

3333
impl ThreadId {
34-
// Generate a new unique thread ID.
35-
pub(crate) fn new() -> ThreadId {
34+
/// Generates a new unique thread ID, and does not rely on the global
35+
/// allocator.
36+
///
37+
/// This should only be used in contexts where a new `ThreadId` is
38+
/// desperately required, but the global allocator might not be available.
39+
pub(super) fn desperate_new() -> ThreadId {
3640
#[cold]
3741
fn exhausted() -> ! {
38-
panic!("failed to generate unique thread ID: bitspace exhausted")
42+
rtabort!("failed to generate unique thread ID: bitspace exhausted")
3943
}
4044

4145
cfg_select! {
@@ -96,6 +100,25 @@ impl ThreadId {
96100
}
97101
}
98102

103+
/// Generates a new unique thread ID.
104+
pub(crate) fn new() -> ThreadId {
105+
cfg_select! {
106+
target_has_atomic = "64" => {
107+
// The generation is implemented lock-free anyway.
108+
ThreadId::desperate_new()
109+
}
110+
_ => {
111+
// Synchronize the id generation – `Mutex` has better
112+
// synchronization behaviour than the spinlock used in
113+
// `desperate_new`, but might need allocation.
114+
use crate::sync::nonpoison::Mutex;
115+
static LOCK: Mutex<()> = Mutex::new(());
116+
let _guard = LOCK.lock();
117+
ThreadId::desperate_new()
118+
}
119+
}
120+
}
121+
99122
#[cfg(any(not(target_thread_local), target_has_atomic = "64"))]
100123
pub(super) fn from_u64(v: u64) -> Option<ThreadId> {
101124
NonZero::new(v).map(ThreadId)

0 commit comments

Comments
 (0)