@@ -11,18 +11,25 @@ use crate::{
11
11
ffi:: CStr ,
12
12
hint, io,
13
13
mem:: ManuallyDrop ,
14
+ ptr:: NonNull ,
14
15
sync:: atomic:: { AtomicUsize , Ordering } ,
15
16
sys:: thread_local_dtor:: run_dtors,
16
17
time:: Duration ,
17
18
} ;
18
19
19
20
pub struct Thread {
20
- inner : ManuallyDrop < Box < ThreadInner > > ,
21
+ p_inner : NonNull < ThreadInner > ,
21
22
22
23
/// The ID of the underlying task.
23
24
task : abi:: ID ,
24
25
}
25
26
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
+
26
33
/// State data shared between a parent thread and child thread. It's dropped on
27
34
/// a transition to one of the final states.
28
35
struct ThreadInner {
@@ -90,8 +97,9 @@ impl Thread {
90
97
} ) ;
91
98
92
99
unsafe extern "C" fn trampoline ( exinf : isize ) {
100
+ let p_inner: * mut ThreadInner = crate :: ptr:: from_exposed_addr_mut ( exinf as usize ) ;
93
101
// Safety: `ThreadInner` is alive at this point
94
- let inner = unsafe { & * ( exinf as * const ThreadInner ) } ;
102
+ let inner = unsafe { & * p_inner } ;
95
103
96
104
// Safety: Since `trampoline` is called only once for each
97
105
// `ThreadInner` and only `trampoline` touches `start`,
@@ -119,13 +127,13 @@ impl Thread {
119
127
// No one will ever join, so we'll ask the collector task to
120
128
// delete the task.
121
129
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
124
132
// ordering is not necessary because the parent thread made
125
133
// no memory access needing synchronization since the call
126
134
// to `acre_tsk`.
127
135
// Safety: See above.
128
- let _ = unsafe { Box :: from_raw ( inner as * const _ as * mut ThreadInner ) } ;
136
+ let _ = unsafe { Box :: from_raw ( p_inner ) } ;
129
137
130
138
// Safety: There are no pinned references to the stack
131
139
unsafe { terminate_and_delete_current_task ( ) } ;
@@ -162,13 +170,14 @@ impl Thread {
162
170
}
163
171
}
164
172
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) ) } ;
166
175
167
176
let new_task = ItronError :: err_if_negative ( unsafe {
168
177
abi:: acre_tsk ( & abi:: T_CTSK {
169
178
// Activate this task immediately
170
179
tskatr : abi:: TA_ACT ,
171
- exinf : inner_ptr as abi:: EXINF ,
180
+ exinf : p_inner . as_ptr ( ) . expose_addr ( ) as abi:: EXINF ,
172
181
// The entry point
173
182
task : Some ( trampoline) ,
174
183
// Inherit the calling task's base priority
@@ -180,7 +189,7 @@ impl Thread {
180
189
} )
181
190
. map_err ( |e| e. as_io_error ( ) ) ?;
182
191
183
- Ok ( Self { inner : ManuallyDrop :: new ( inner ) , task : new_task } )
192
+ Ok ( Self { p_inner , task : new_task } )
184
193
}
185
194
186
195
pub fn yield_now ( ) {
@@ -197,8 +206,9 @@ impl Thread {
197
206
}
198
207
}
199
208
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 ( ) } ;
202
212
// Get the current task ID. Panicking here would cause a resource leak,
203
213
// so just abort on failure.
204
214
let current_task = task:: current_task_id_aborting ( ) ;
@@ -243,8 +253,8 @@ impl Thread {
243
253
unsafe { terminate_and_delete_task ( self . task ) } ;
244
254
245
255
// 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 ( ) ) } ;
248
258
249
259
// Skip the destructor (because it would attempt to detach the thread)
250
260
crate :: mem:: forget ( self ) ;
@@ -253,13 +263,16 @@ impl Thread {
253
263
254
264
impl Drop for Thread {
255
265
fn drop ( & mut self ) {
266
+ // Safety: `ThreadInner` is alive at this point
267
+ let inner = unsafe { self . p_inner . as_ref ( ) } ;
268
+
256
269
// 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 ) {
258
271
LIFECYCLE_INIT => {
259
272
// [INIT → DETACHED]
260
273
// When the time comes, the child will figure out that no
261
274
// 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.
263
276
// However, the release ordering is not necessary because we
264
277
// made no memory access needing synchronization since the call
265
278
// to `acre_tsk`.
@@ -278,10 +291,9 @@ impl Drop for Thread {
278
291
// delete by entering the `FINISHED` state.
279
292
unsafe { terminate_and_delete_task ( self . task ) } ;
280
293
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 ( ) ) } ;
285
297
}
286
298
_ => unsafe { hint:: unreachable_unchecked ( ) } ,
287
299
}
0 commit comments