Kaynağa Gözat

change(clone): parse clone args at entry point and save them into Option's

greatbridf 7 ay önce
ebeveyn
işleme
da6298e357
4 değiştirilmiş dosya ile 92 ekleme ve 86 silme
  1. 38 2
      src/kernel/syscall/procops.rs
  2. 43 19
      src/kernel/task/clone.rs
  3. 10 63
      src/kernel/task/thread.rs
  4. 1 2
      src/lib.rs

+ 38 - 2
src/kernel/syscall/procops.rs

@@ -11,7 +11,7 @@ use crate::kernel::task::{
     SignalAction, SignalMask, WaitObject, WaitType,
 };
 use crate::kernel::task::{parse_futexop, CloneArgs};
-use crate::kernel::user::dataflow::UserString;
+use crate::kernel::user::dataflow::{CheckedUserPointer, UserString};
 use crate::kernel::user::{UserPointer, UserPointerMut};
 use crate::kernel::vfs::{self, dentry::Dentry};
 use crate::path::Path;
@@ -20,6 +20,7 @@ use crate::{kernel::user::dataflow::UserBuffer, prelude::*};
 use alloc::borrow::ToOwned;
 use alloc::ffi::CString;
 use bitflags::bitflags;
+use eonix_hal::processor::UserTLS;
 use eonix_hal::traits::trap::RawTrapContext;
 use eonix_mm::address::Addr as _;
 use eonix_runtime::task::Task;
@@ -302,9 +303,43 @@ fn gettid() -> KResult<u32> {
     Ok(thread.tid)
 }
 
+pub fn parse_user_tls(arch_tls: usize) -> KResult<UserTLS> {
+    #[cfg(target_arch = "x86_64")]
+    {
+        let desc = arch_tls as *mut posix_types::x86_64::UserDescriptor;
+        let desc_pointer = UserPointerMut::new(desc)?;
+        let mut desc = desc_pointer.read()?;
+
+        // Clear the TLS area if it is not present.
+        if desc.flags.is_read_exec_only() && !desc.flags.is_present() {
+            if desc.limit != 0 && desc.base != 0 {
+                let len = if desc.flags.is_limit_in_pages() {
+                    (desc.limit as usize) << 12
+                } else {
+                    desc.limit as usize
+                };
+
+                CheckedUserPointer::new(desc.base as _, len)?.zero()?;
+            }
+        }
+
+        let (new_tls, entry) =
+            UserTLS::new32(desc.base, desc.limit, desc.flags.is_limit_in_pages());
+        desc.entry = entry;
+        desc_pointer.write(desc)?;
+
+        Ok(new_tls)
+    }
+
+    #[cfg(not(target_arch = "x86_64"))]
+    {
+        todo!()
+    }
+}
+
 #[eonix_macros::define_syscall(0xf3)]
 fn set_thread_area(arch_tls: usize) -> KResult<()> {
-    thread.set_user_tls(arch_tls)?;
+    thread.set_user_tls(parse_user_tls(arch_tls)?)?;
 
     // SAFETY: Preemption is disabled on calling `load_thread_area32()`.
     unsafe {
@@ -318,6 +353,7 @@ fn set_thread_area(arch_tls: usize) -> KResult<()> {
 
 #[eonix_macros::define_syscall(0x102)]
 fn set_tid_address(tidptr: usize) -> KResult<u32> {
+    thread.clear_child_tid(Some(tidptr));
     Ok(thread.tid)
 }
 

+ 43 - 19
src/kernel/task/clone.rs

@@ -1,14 +1,16 @@
 use crate::{
     kernel::{
+        syscall::procops::parse_user_tls,
         task::{
             alloc_pid, new_thread_runnable, KernelStack, ProcessBuilder, ProcessList, Thread,
             ThreadBuilder,
         },
-        user::UserPointerMut,
+        user::{dataflow::CheckedUserPointer, UserPointerMut},
     },
     KResult,
 };
 use bitflags::bitflags;
+use eonix_hal::processor::UserTLS;
 use eonix_runtime::{scheduler::Scheduler, task::Task};
 use eonix_sync::AsProof;
 
@@ -47,11 +49,12 @@ bitflags! {
 #[derive(Debug)]
 pub struct CloneArgs {
     pub flags: CloneFlags,
-    pub sp: Option<usize>,           // Stack pointer for the new thread.
-    pub exit_signal: Option<Signal>, // Signal to send to the parent on exit.
-    pub child_tid_ptr: usize,        // Pointer to child TID in user space.
-    pub parent_tid_ptr: usize,       // Pointer to parent TID in user space.
-    pub tls: usize,                  // Pointer to TLS information.
+    pub sp: Option<usize>,             // Stack pointer for the new thread.
+    pub exit_signal: Option<Signal>,   // Signal to send to the parent on exit.
+    pub set_tid_ptr: Option<usize>,    // Pointer to set child TID in user space.
+    pub clear_tid_ptr: Option<usize>,  // Pointer to clear child TID in user space.
+    pub parent_tid_ptr: Option<usize>, // Pointer to parent TID in user space.
+    pub tls: Option<UserTLS>,          // Pointer to TLS information.
 }
 
 impl CloneArgs {
@@ -72,12 +75,34 @@ impl CloneArgs {
             None
         };
 
+        let mut set_tid_ptr = None;
+        if clone_flags.contains(CloneFlags::CLONE_CHILD_SETTID) {
+            set_tid_ptr = Some(child_tid_ptr);
+        }
+
+        let mut clear_tid_ptr = None;
+        if clone_flags.contains(CloneFlags::CLONE_CHILD_CLEARTID) {
+            clear_tid_ptr = Some(child_tid_ptr);
+        }
+
+        let parent_tid_ptr = clone_flags
+            .contains(CloneFlags::CLONE_PARENT_SETTID)
+            .then_some(parent_tid_ptr);
+
+        #[cfg(target_arch = "x86_64")]
+        let tls = if clone_flags.contains(CloneFlags::CLONE_SETTLS) {
+            Some(parse_user_tls(tls)?)
+        } else {
+            None
+        };
+
         assert!(sp != 0);
 
         let clone_args = CloneArgs {
             flags: clone_flags,
             sp: Some(sp),
-            child_tid_ptr,
+            set_tid_ptr,
+            clear_tid_ptr,
             parent_tid_ptr,
             exit_signal,
             tls,
@@ -90,10 +115,11 @@ impl CloneArgs {
         CloneArgs {
             flags: CloneFlags::empty(),
             sp: None,
-            child_tid_ptr: 0,
-            parent_tid_ptr: 0,
+            set_tid_ptr: None,
+            clear_tid_ptr: None,
+            parent_tid_ptr: None,
             exit_signal: Some(Signal::SIGCHLD),
-            tls: 0,
+            tls: None,
         }
     }
 
@@ -101,10 +127,11 @@ impl CloneArgs {
         CloneArgs {
             flags: CloneFlags::CLONE_VFORK | CloneFlags::CLONE_VM,
             sp: None,
-            child_tid_ptr: 0,
-            parent_tid_ptr: 0,
+            set_tid_ptr: None,
+            clear_tid_ptr: None,
+            parent_tid_ptr: None,
             exit_signal: Some(Signal::SIGCHLD),
-            tls: 0,
+            tls: None,
         }
     }
 }
@@ -121,6 +148,7 @@ pub fn do_clone(thread: &Thread, clone_args: CloneArgs) -> KResult<u32> {
         let new_thread = thread_builder
             .process(current_process)
             .tid(new_pid)
+            .tls(clone_args.tls)
             .build(&mut procs);
         new_thread
     } else {
@@ -137,12 +165,8 @@ pub fn do_clone(thread: &Thread, clone_args: CloneArgs) -> KResult<u32> {
         new_thread
     };
 
-    if clone_args.flags.contains(CloneFlags::CLONE_PARENT_SETTID) {
-        UserPointerMut::new(clone_args.parent_tid_ptr as *mut u32)?.write(new_pid)?
-    }
-
-    if clone_args.flags.contains(CloneFlags::CLONE_SETTLS) {
-        new_thread.set_user_tls(clone_args.tls)?;
+    if let Some(parent_tid_ptr) = clone_args.parent_tid_ptr {
+        UserPointerMut::new(parent_tid_ptr as *mut u32)?.write(new_pid)?
     }
 
     Scheduler::get().spawn::<KernelStack, _>(new_thread_runnable(new_thread));

+ 10 - 63
src/kernel/task/thread.rs

@@ -1,6 +1,6 @@
 use super::{
     signal::{RaiseResult, Signal, SignalList},
-    Process, ProcessList,
+    Process, ProcessList, WaitType,
 };
 use crate::{
     kernel::{
@@ -8,7 +8,7 @@ use crate::{
         syscall::{syscall_handlers, SyscallHandler},
         task::{clone::CloneArgs, CloneFlags},
         timer::timer_interrupt,
-        user::{dataflow::CheckedUserPointer, UserPointerMut},
+        user::UserPointerMut,
         vfs::{filearray::FileArray, FsContext},
     },
     prelude::*,
@@ -37,7 +37,6 @@ use eonix_mm::address::{Addr as _, VAddr};
 use eonix_runtime::run::{Contexted, Run, RunState};
 use eonix_sync::AsProofMut as _;
 use pointers::BorrowedArc;
-use posix_types::x86_64::UserDescriptor;
 
 #[eonix_percpu::define_percpu]
 static CURRENT_THREAD: Option<NonNull<Thread>> = None;
@@ -54,7 +53,7 @@ pub struct ThreadBuilder {
     files: Option<Arc<FileArray>>,
     fs_context: Option<Arc<FsContext>>,
     signal_list: Option<SignalList>,
-    tls: Option<usize>,
+    tls: Option<UserTLS>,
     set_child_tid: Option<usize>,
     clear_child_tid: Option<usize>,
 
@@ -141,7 +140,7 @@ impl ThreadBuilder {
         self
     }
 
-    pub fn tls(mut self, tls: Option<usize>) -> Self {
+    pub fn tls(mut self, tls: Option<UserTLS>) -> Self {
         self.tls = tls;
         self
     }
@@ -188,12 +187,6 @@ impl ThreadBuilder {
             trap_ctx.set_stack_pointer(sp);
         }
 
-        let tls = if clone_args.flags.contains(CloneFlags::CLONE_SETTLS) {
-            Some(clone_args.tls)
-        } else {
-            None
-        };
-
         let fs_context = if clone_args.flags.contains(CloneFlags::CLONE_FS) {
             FsContext::new_shared(&thread.fs_context)
         } else {
@@ -212,26 +205,14 @@ impl ThreadBuilder {
             SignalList::new_cloned(&thread.signal_list)
         };
 
-        let set_child_tid = if clone_args.flags.contains(CloneFlags::CLONE_CHILD_SETTID) {
-            Some(clone_args.child_tid_ptr)
-        } else {
-            None
-        };
-
-        let clear_child_tid = if clone_args.flags.contains(CloneFlags::CLONE_CHILD_CLEARTID) {
-            Some(clone_args.child_tid_ptr)
-        } else {
-            None
-        };
-
         Ok(self
             .files(files)
             .fs_context(fs_context)
             .signal_list(signal_list)
             .name(inner.name.clone())
-            .tls(tls)
-            .set_child_tid(set_child_tid)
-            .clear_child_tid(clear_child_tid)
+            .tls(clone_args.tls.clone())
+            .set_child_tid(clone_args.set_tid_ptr)
+            .clear_child_tid(clone_args.clear_tid_ptr)
             .trap_ctx(trap_ctx)
             .fpu_state(thread.fpu_state.borrow().clone()))
     }
@@ -261,7 +242,7 @@ impl ThreadBuilder {
             dead: AtomicBool::new(false),
             inner: Spin::new(ThreadInner {
                 name,
-                tls: None,
+                tls: self.tls,
                 set_child_tid: self.set_child_tid,
                 clear_child_tid: self.clear_child_tid,
             }),
@@ -296,38 +277,8 @@ impl Thread {
         }
     }
 
-    pub fn set_user_tls(&self, arch_tls: usize) -> KResult<()> {
-        #[cfg(target_arch = "x86_64")]
-        {
-            let desc = arch_tls as *mut UserDescriptor;
-
-            let desc_pointer = UserPointerMut::new(desc)?;
-            let mut desc = desc_pointer.read()?;
-
-            // Clear the TLS area if it is not present.
-            if desc.flags.is_read_exec_only() && !desc.flags.is_present() {
-                if desc.limit == 0 || desc.base == 0 {
-                    return Ok(());
-                }
-
-                let len = if desc.flags.is_limit_in_pages() {
-                    (desc.limit as usize) << 12
-                } else {
-                    desc.limit as usize
-                };
-
-                CheckedUserPointer::new(desc.base as _, len)?.zero()?;
-                return Ok(());
-            }
-
-            let (tls, entry) =
-                UserTLS::new32(desc.base, desc.limit, desc.flags.is_limit_in_pages());
-            desc.entry = entry;
-
-            self.inner.lock().tls = Some(tls);
-            desc_pointer.write(desc)?;
-        }
-
+    pub fn set_user_tls(&self, tls: UserTLS) -> KResult<()> {
+        self.inner.lock().tls = Some(tls);
         Ok(())
     }
 
@@ -339,10 +290,6 @@ impl Thread {
         self.inner.lock().name.clone()
     }
 
-    pub fn set_child_tid(&self, set_child_tid: Option<usize>) {
-        self.inner.lock().set_child_tid = set_child_tid;
-    }
-
     pub fn clear_child_tid(&self, clear_child_tid: Option<usize>) {
         self.inner.lock().clear_child_tid = clear_child_tid;
     }

+ 1 - 2
src/lib.rs

@@ -20,6 +20,7 @@ mod prelude;
 mod rcu;
 mod sync;
 
+use crate::kernel::task::alloc_pid;
 use alloc::{ffi::CString, sync::Arc};
 use core::{
     hint::spin_loop,
@@ -45,8 +46,6 @@ use kernel_init::setup_memory;
 use path::Path;
 use prelude::*;
 
-use crate::kernel::task::alloc_pid;
-
 #[panic_handler]
 fn panic(info: &core::panic::PanicInfo) -> ! {
     if let Some(location) = info.location() {