@@ -11,18 +11,25 @@ use crate::{
1111 ffi:: CStr ,
1212 hint, io,
1313 mem:: ManuallyDrop ,
14+ ptr:: NonNull ,
1415 sync:: atomic:: { AtomicUsize , Ordering } ,
1516 sys:: thread_local_dtor:: run_dtors,
1617 time:: Duration ,
1718} ;
1819
1920pub struct Thread {
20- inner : ManuallyDrop < Box < ThreadInner > > ,
21+ p_inner : NonNull < ThreadInner > ,
2122
2223 /// The ID of the underlying task.
2324 task : abi:: ID ,
2425}
2526
27+ // Safety: There's nothing in `Thread` that ties it to the original creator. It
28+ // can be dropped by any threads.
29+ unsafe impl Send for Thread { }
30+ // Safety: `Thread` provides no methods that take `&self`.
31+ unsafe impl Sync for Thread { }
32+
2633/// State data shared between a parent thread and child thread. It's dropped on
2734/// a transition to one of the final states.
2835struct ThreadInner {
@@ -90,8 +97,9 @@ impl Thread {
9097 } ) ;
9198
9299 unsafe extern "C" fn trampoline ( exinf : isize ) {
100+ let p_inner: * mut ThreadInner = crate :: ptr:: from_exposed_addr_mut ( exinf as usize ) ;
93101 // Safety: `ThreadInner` is alive at this point
94- let inner: & ThreadInner = unsafe { & * crate :: ptr :: from_exposed_addr ( exinf as usize ) } ;
102+ let inner = unsafe { & * p_inner } ;
95103
96104 // Safety: Since `trampoline` is called only once for each
97105 // `ThreadInner` and only `trampoline` touches `start`,
@@ -119,13 +127,13 @@ impl Thread {
119127 // No one will ever join, so we'll ask the collector task to
120128 // delete the task.
121129
122- // In this case, `inner `'s ownership has been moved to us,
123- // And we are responsible for dropping it. The acquire
130+ // In this case, `*p_inner `'s ownership has been moved to
131+ // us, and we are responsible for dropping it. The acquire
124132 // ordering is not necessary because the parent thread made
125133 // no memory access needing synchronization since the call
126134 // to `acre_tsk`.
127135 // Safety: See above.
128- let _ = unsafe { Box :: from_raw ( inner as * const _ as * mut ThreadInner ) } ;
136+ let _ = unsafe { Box :: from_raw ( p_inner ) } ;
129137
130138 // Safety: There are no pinned references to the stack
131139 unsafe { terminate_and_delete_current_task ( ) } ;
@@ -162,13 +170,14 @@ impl Thread {
162170 }
163171 }
164172
165- let inner_ptr = ( & * inner) as * const ThreadInner ;
173+ // Safety: `Box::into_raw` returns a non-null pointer
174+ let p_inner = unsafe { NonNull :: new_unchecked ( Box :: into_raw ( inner) ) } ;
166175
167176 let new_task = ItronError :: err_if_negative ( unsafe {
168177 abi:: acre_tsk ( & abi:: T_CTSK {
169178 // Activate this task immediately
170179 tskatr : abi:: TA_ACT ,
171- exinf : inner_ptr . expose_addr ( ) as abi:: EXINF ,
180+ exinf : p_inner . as_ptr ( ) . expose_addr ( ) as abi:: EXINF ,
172181 // The entry point
173182 task : Some ( trampoline) ,
174183 // Inherit the calling task's base priority
@@ -180,7 +189,7 @@ impl Thread {
180189 } )
181190 . map_err ( |e| e. as_io_error ( ) ) ?;
182191
183- Ok ( Self { inner : ManuallyDrop :: new ( inner ) , task : new_task } )
192+ Ok ( Self { p_inner , task : new_task } )
184193 }
185194
186195 pub fn yield_now ( ) {
@@ -197,8 +206,9 @@ impl Thread {
197206 }
198207 }
199208
200- pub fn join ( mut self ) {
201- let inner = & * self . inner ;
209+ pub fn join ( self ) {
210+ // Safety: `ThreadInner` is alive at this point
211+ let inner = unsafe { self . p_inner . as_ref ( ) } ;
202212 // Get the current task ID. Panicking here would cause a resource leak,
203213 // so just abort on failure.
204214 let current_task = task:: current_task_id_aborting ( ) ;
@@ -243,8 +253,8 @@ impl Thread {
243253 unsafe { terminate_and_delete_task ( self . task ) } ;
244254
245255 // In either case, we are responsible for dropping `inner`.
246- // Safety: The contents of `self.inner ` will not be accessed hereafter
247- let _inner = unsafe { ManuallyDrop :: take ( & mut self . inner ) } ;
256+ // Safety: The contents of `*p_inner ` will not be accessed hereafter
257+ let _inner = unsafe { Box :: from_raw ( self . p_inner . as_ptr ( ) ) } ;
248258
249259 // Skip the destructor (because it would attempt to detach the thread)
250260 crate :: mem:: forget ( self ) ;
@@ -253,13 +263,16 @@ impl Thread {
253263
254264impl Drop for Thread {
255265 fn drop ( & mut self ) {
266+ // Safety: `ThreadInner` is alive at this point
267+ let inner = unsafe { self . p_inner . as_ref ( ) } ;
268+
256269 // Detach the thread.
257- match self . inner . lifecycle . swap ( LIFECYCLE_DETACHED_OR_JOINED , Ordering :: Acquire ) {
270+ match inner. lifecycle . swap ( LIFECYCLE_DETACHED_OR_JOINED , Ordering :: Acquire ) {
258271 LIFECYCLE_INIT => {
259272 // [INIT → DETACHED]
260273 // When the time comes, the child will figure out that no
261274 // one will ever join it.
262- // The ownership of `self.inner ` is moved to the child thread.
275+ // The ownership of `*p_inner ` is moved to the child thread.
263276 // However, the release ordering is not necessary because we
264277 // made no memory access needing synchronization since the call
265278 // to `acre_tsk`.
@@ -278,10 +291,9 @@ impl Drop for Thread {
278291 // delete by entering the `FINISHED` state.
279292 unsafe { terminate_and_delete_task ( self . task ) } ;
280293
281- // Wwe are responsible for dropping `inner`.
282- // Safety: The contents of `self.inner` will not be accessed
283- // hereafter
284- unsafe { ManuallyDrop :: drop ( & mut self . inner ) } ;
294+ // Wwe are responsible for dropping `*p_inner`.
295+ // Safety: The contents of `*p_inner` will not be accessed hereafter
296+ let _ = unsafe { Box :: from_raw ( self . p_inner . as_ptr ( ) ) } ;
285297 }
286298 _ => unsafe { hint:: unreachable_unchecked ( ) } ,
287299 }
0 commit comments