@@ -114,45 +114,59 @@ struct Metadata {
114114 thread : ThreadData ,
115115}
116116
117- /// Fields which accessed by user code via known offsets from the platform
118- /// thread-pointer register.
117+ /// Fields which accessed by user code via well-known offsets from the platform
118+ /// thread-pointer register. Specifically, the thread-pointer register points
119+ /// to the `thread_pointee` field.
119120#[ repr( C ) ]
120121#[ cfg_attr( target_arch = "arm" , repr( align( 8 ) ) ) ]
121122struct Abi {
123+ /// The address the thread pointer points to.
124+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
125+ thread_pointee : [ u8 ; 0 ] ,
126+
122127 /// The ABI-exposed `canary` field.
123128 #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" , target_arch = "riscv64" ) ) ]
124129 canary : usize ,
125130
131+ /// The address the thread pointer points to.
132+ #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" , ) ) ]
133+ thread_pointee : [ u8 ; 0 ] ,
134+
126135 /// The ABI-exposed `dtv` field (though we don't yet implement dynamic
127136 /// linking).
128137 #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" , target_arch = "riscv64" ) ) ]
129138 dtv : * const c_void ,
130139
140+ /// The address the thread pointer points to.
141+ #[ cfg( target_arch = "riscv64" ) ]
142+ thread_pointee : [ u8 ; 0 ] ,
143+
144+ /// Padding to put the TLS data which follows at its well-known offset.
145+ #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" ) ) ]
146+ _pad : [ usize ; 1 ] ,
147+
148+ /// Padding to put the TLS data which follows at its well-known offset.
149+ #[ cfg( target_arch = "riscv64" ) ]
150+ _pad : [ usize ; 0 ] ,
151+
131152 /// x86 and x86-64 put a copy of the thread-pointer register at the memory
132153 /// location pointed to by the thread-pointer register, because reading the
133154 /// thread-pointer register directly is slow.
134155 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
135- this : * mut Abi ,
156+ this : * mut c_void ,
136157
137158 /// The ABI-exposed `dtv` field (though we don't yet implement dynamic
138159 /// linking).
139160 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
140161 dtv : * const c_void ,
141162
163+ /// Padding to put the `canary` field at its well-known offset.
142164 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
143165 _pad : [ usize ; 3 ] ,
144166
145167 /// The ABI-exposed `canary` field.
146168 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
147169 canary : usize ,
148-
149- /// Padding to put the TLS data which follows at its known offset.
150- #[ cfg( any( target_arch = "aarch64" , target_arch = "arm" ) ) ]
151- _pad : [ usize ; 1 ] ,
152-
153- /// Padding to put the TLS data which follows at its known offset.
154- #[ cfg( target_arch = "riscv64" ) ]
155- _pad : [ usize ; 0 ] ,
156170}
157171
158172/// Information obtained from the `DT_TLS` segment of the executable.
@@ -270,7 +284,9 @@ pub use rustix::thread::Pid as ThreadId;
270284///
271285/// This function is similar to `create_thread` except that the OS thread is
272286/// already created, and already has a stack (which we need to locate), and is
273- /// already running.
287+ /// already running. We still need to create the thread [`Metadata`], copy in
288+ /// the TLS initializers, and point the thread pointer to it so that it follows
289+ /// the thread ABI that all the other threads follow.
274290///
275291/// # Safety
276292///
@@ -346,7 +362,7 @@ pub(super) unsafe fn initialize_main_thread(mem: *mut c_void) {
346362
347363 let tls_data = new. add ( tls_data_bottom) ;
348364 let metadata: * mut Metadata = new. add ( header) . cast ( ) ;
349- let newtls: * mut Abi = & mut ( * metadata) . abi ;
365+ let newtls: * mut c_void = ( * metadata) . abi . thread_pointee . as_mut_ptr ( ) . cast ( ) ;
350366
351367 let thread_id_ptr = ( * metadata) . thread . thread_id . as_ptr ( ) ;
352368 let tid = rustix:: runtime:: set_tid_address ( thread_id_ptr. cast ( ) ) ;
@@ -364,6 +380,7 @@ pub(super) unsafe fn initialize_main_thread(mem: *mut c_void) {
364380 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
365381 this : newtls,
366382 _pad : Default :: default ( ) ,
383+ thread_pointee : [ ] ,
367384 } ,
368385 thread : ThreadData :: new (
369386 Some ( tid) ,
@@ -390,7 +407,7 @@ pub(super) unsafe fn initialize_main_thread(mem: *mut c_void) {
390407 . fill ( 0 ) ;
391408
392409 // Point the platform thread-pointer register at the new thread metadata.
393- set_thread_pointer ( newtls. cast :: < u8 > ( ) . cast ( ) ) ;
410+ set_thread_pointer ( newtls) ;
394411}
395412
396413/// Creates a new thread.
@@ -486,7 +503,7 @@ pub unsafe fn create_thread(
486503
487504 let tls_data = map. add ( tls_data_bottom) ;
488505 let metadata: * mut Metadata = map. add ( header) . cast ( ) ;
489- let newtls: * mut Abi = & mut ( * metadata) . abi ;
506+ let newtls: * mut c_void = ( * metadata) . abi . thread_pointee . as_mut_ptr ( ) . cast ( ) ;
490507
491508 // Copy the current thread's canary to the new thread.
492509 let canary = ( * current_metadata ( ) ) . abi . canary ;
@@ -499,6 +516,7 @@ pub unsafe fn create_thread(
499516 #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
500517 this : newtls,
501518 _pad : Default :: default ( ) ,
519+ thread_pointee : [ ] ,
502520 } ,
503521 thread : ThreadData :: new (
504522 None , // the real tid will be written by `clone`.
@@ -560,7 +578,7 @@ pub unsafe fn create_thread(
560578 stack. cast ( ) ,
561579 thread_id_ptr,
562580 thread_id_ptr,
563- newtls. cast :: < u8 > ( ) . cast ( ) ,
581+ newtls,
564582 core:: mem:: transmute ( fn_) ,
565583 args. len ( ) ,
566584 ) ;
@@ -909,7 +927,7 @@ pub fn at_thread_exit(func: Box<dyn FnOnce()>) {
909927fn current_metadata ( ) -> * mut Metadata {
910928 thread_pointer ( )
911929 . cast :: < u8 > ( )
912- . wrapping_sub ( offset_of ! ( Metadata , abi) )
930+ . wrapping_sub ( offset_of ! ( Metadata , abi) + offset_of ! ( Abi , thread_pointee ) )
913931 . cast ( )
914932}
915933
@@ -976,8 +994,8 @@ pub fn current_thread_tls_addr(offset: usize) -> *mut c_void {
976994 {
977995 thread_pointer ( )
978996 . cast :: < u8 > ( )
997+ . wrapping_add ( size_of :: < Abi > ( ) - offset_of ! ( Abi , thread_pointee) )
979998 . wrapping_add ( TLS_OFFSET )
980- . wrapping_add ( size_of :: < Abi > ( ) )
981999 . wrapping_add ( offset)
9821000 . cast ( )
9831001 }
@@ -990,8 +1008,8 @@ pub fn current_thread_tls_addr(offset: usize) -> *mut c_void {
9901008 unsafe {
9911009 thread_pointer ( )
9921010 . cast :: < u8 > ( )
993- . wrapping_add ( TLS_OFFSET )
9941011 . wrapping_sub ( STARTUP_TLS_INFO . mem_size )
1012+ . wrapping_add ( TLS_OFFSET )
9951013 . wrapping_add ( offset)
9961014 . cast ( )
9971015 }
0 commit comments