@@ -170,7 +170,6 @@ use crate::ptr::addr_of_mut;
170170use crate :: str;
171171use crate :: sync:: Arc ;
172172use crate :: sys:: thread as imp;
173- use crate :: sys_common:: mutex;
174173use crate :: sys_common:: thread;
175174use crate :: sys_common:: thread_info;
176175use crate :: sys_common:: thread_parker:: Parker ;
@@ -1033,24 +1032,48 @@ pub struct ThreadId(NonZeroU64);
10331032impl ThreadId {
10341033 // Generate a new unique thread ID.
10351034 fn new ( ) -> ThreadId {
1036- // It is UB to attempt to acquire this mutex reentrantly!
1037- static GUARD : mutex:: StaticMutex = mutex:: StaticMutex :: new ( ) ;
1038- static mut COUNTER : u64 = 1 ;
1039-
1040- unsafe {
1041- let guard = GUARD . lock ( ) ;
1042-
1043- // If we somehow use up all our bits, panic so that we're not
1044- // covering up subtle bugs of IDs being reused.
1045- if COUNTER == u64:: MAX {
1046- drop ( guard) ; // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire.
1047- panic ! ( "failed to generate unique thread ID: bitspace exhausted" ) ;
1048- }
1049-
1050- let id = COUNTER ;
1051- COUNTER += 1 ;
1035+ #[ cold]
1036+ fn exhausted ( ) -> ! {
1037+ panic ! ( "failed to generate unique thread ID: bitspace exhausted" )
1038+ }
10521039
1053- ThreadId ( NonZeroU64 :: new ( id) . unwrap ( ) )
1040+ cfg_if:: cfg_if! {
1041+ if #[ cfg( target_has_atomic = "64" ) ] {
1042+ use crate :: sync:: atomic:: { AtomicU64 , Ordering :: Relaxed } ;
1043+
1044+ static COUNTER : AtomicU64 = AtomicU64 :: new( 0 ) ;
1045+
1046+ let mut last = COUNTER . load( Relaxed ) ;
1047+ loop {
1048+ let Some ( id) = last. checked_add( 1 ) else {
1049+ exhausted( ) ;
1050+ } ;
1051+
1052+ match COUNTER . compare_exchange_weak( last, id, Relaxed , Relaxed ) {
1053+ Ok ( _) => return ThreadId ( NonZeroU64 :: new( id) . unwrap( ) ) ,
1054+ Err ( id) => last = id,
1055+ }
1056+ }
1057+ } else {
1058+ use crate :: sys_common:: mutex:: StaticMutex ;
1059+
1060+ // It is UB to attempt to acquire this mutex reentrantly!
1061+ static GUARD : StaticMutex = StaticMutex :: new( ) ;
1062+ static mut COUNTER : u64 = 0 ;
1063+
1064+ unsafe {
1065+ let guard = GUARD . lock( ) ;
1066+
1067+ let Some ( id) = COUNTER . checked_add( 1 ) else {
1068+ drop( guard) ; // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire.
1069+ exhausted( ) ;
1070+ } ;
1071+
1072+ COUNTER = id;
1073+ drop( guard) ;
1074+ ThreadId ( NonZeroU64 :: new( id) . unwrap( ) )
1075+ }
1076+ }
10541077 }
10551078 }
10561079
0 commit comments