]> git.lizzy.rs Git - rust.git/blobdiff - library/std/src/sys/itron/thread.rs
Rollup merge of #105615 - WaffleLapkin:remove_opt_scope_span_mention, r=compiler...
[rust.git] / library / std / src / sys / itron / thread.rs
index d28f57f33be20566de33bd7a79389a85067105a6..c2b3668087225cdc884a28d3a15660974c16b98d 100644 (file)
     ffi::CStr,
     hint, io,
     mem::ManuallyDrop,
+    ptr::NonNull,
     sync::atomic::{AtomicUsize, Ordering},
     sys::thread_local_dtor::run_dtors,
     time::Duration,
 };
 
 pub struct Thread {
-    inner: ManuallyDrop<Box<ThreadInner>>,
+    p_inner: NonNull<ThreadInner>,
 
     /// The ID of the underlying task.
     task: abi::ID,
 }
 
+// Safety: There's nothing in `Thread` that ties it to the original creator. It
+//         can be dropped by any threads.
+unsafe impl Send for Thread {}
+// Safety: `Thread` provides no methods that take `&self`.
+unsafe impl Sync for Thread {}
+
 /// State data shared between a parent thread and child thread. It's dropped on
 /// a transition to one of the final states.
 struct ThreadInner {
@@ -90,8 +97,9 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         });
 
         unsafe extern "C" fn trampoline(exinf: isize) {
+            let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize);
             // Safety: `ThreadInner` is alive at this point
-            let inner = unsafe { &*(exinf as *const ThreadInner) };
+            let inner = unsafe { &*p_inner };
 
             // Safety: Since `trampoline` is called only once for each
             //         `ThreadInner` and only `trampoline` touches `start`,
@@ -119,13 +127,13 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
                     // No one will ever join, so we'll ask the collector task to
                     // delete the task.
 
-                    // In this case, `inner`'s ownership has been moved to us,
-                    // And we are responsible for dropping it. The acquire
+                    // In this case, `*p_inner`'s ownership has been moved to
+                    // us, and we are responsible for dropping it. The acquire
                     // ordering is not necessary because the parent thread made
                     // no memory access needing synchronization since the call
                     // to `acre_tsk`.
                     // Safety: See above.
-                    let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) };
+                    let _ = unsafe { Box::from_raw(p_inner) };
 
                     // Safety: There are no pinned references to the stack
                     unsafe { terminate_and_delete_current_task() };
@@ -162,13 +170,14 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
             }
         }
 
-        let inner_ptr = (&*inner) as *const ThreadInner;
+        // Safety: `Box::into_raw` returns a non-null pointer
+        let p_inner = unsafe { NonNull::new_unchecked(Box::into_raw(inner)) };
 
         let new_task = ItronError::err_if_negative(unsafe {
             abi::acre_tsk(&abi::T_CTSK {
                 // Activate this task immediately
                 tskatr: abi::TA_ACT,
-                exinf: inner_ptr as abi::EXINF,
+                exinf: p_inner.as_ptr().expose_addr() as abi::EXINF,
                 // The entry point
                 task: Some(trampoline),
                 // Inherit the calling task's base priority
@@ -180,7 +189,7 @@ pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
         })
         .map_err(|e| e.as_io_error())?;
 
-        Ok(Self { inner: ManuallyDrop::new(inner), task: new_task })
+        Ok(Self { p_inner, task: new_task })
     }
 
     pub fn yield_now() {
@@ -197,8 +206,9 @@ pub fn sleep(dur: Duration) {
         }
     }
 
-    pub fn join(mut self) {
-        let inner = &*self.inner;
+    pub fn join(self) {
+        // Safety: `ThreadInner` is alive at this point
+        let inner = unsafe { self.p_inner.as_ref() };
         // Get the current task ID. Panicking here would cause a resource leak,
         // so just abort on failure.
         let current_task = task::current_task_id_aborting();
@@ -243,8 +253,8 @@ pub fn join(mut self) {
         unsafe { terminate_and_delete_task(self.task) };
 
         // In either case, we are responsible for dropping `inner`.
-        // Safety: The contents of `self.inner` will not be accessed hereafter
-        let _inner = unsafe { ManuallyDrop::take(&mut self.inner) };
+        // Safety: The contents of `*p_inner` will not be accessed hereafter
+        let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
 
         // Skip the destructor (because it would attempt to detach the thread)
         crate::mem::forget(self);
@@ -253,13 +263,16 @@ pub fn join(mut self) {
 
 impl Drop for Thread {
     fn drop(&mut self) {
+        // Safety: `ThreadInner` is alive at this point
+        let inner = unsafe { self.p_inner.as_ref() };
+
         // Detach the thread.
-        match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
+        match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
             LIFECYCLE_INIT => {
                 // [INIT → DETACHED]
                 // When the time comes, the child will figure out that no
                 // one will ever join it.
-                // The ownership of `self.inner` is moved to the child thread.
+                // The ownership of `*p_inner` is moved to the child thread.
                 // However, the release ordering is not necessary because we
                 // made no memory access needing synchronization since the call
                 // to `acre_tsk`.
@@ -278,10 +291,9 @@ fn drop(&mut self) {
                 //         delete by entering the `FINISHED` state.
                 unsafe { terminate_and_delete_task(self.task) };
 
-                // Wwe are responsible for dropping `inner`.
-                // Safety: The contents of `self.inner` will not be accessed
-                //         hereafter
-                unsafe { ManuallyDrop::drop(&mut self.inner) };
+                // Wwe are responsible for dropping `*p_inner`.
+                // Safety: The contents of `*p_inner` will not be accessed hereafter
+                let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
             }
             _ => unsafe { hint::unreachable_unchecked() },
         }