pub fn clone_task(
        &self,
        flags: u64,
        user_parent_tid: UserRef<pid_t>,
        user_child_tid: UserRef<pid_t>,
    ) -> Result<CurrentTask, Errno> {
        // TODO: Implement more flags.
        const IMPLEMENTED_FLAGS: u64 = (CLONE_VM
            | CLONE_FS
            | CLONE_FILES
            | CLONE_SIGHAND
            | CLONE_THREAD
            | CLONE_SYSVSEM
            | CLONE_SETTLS
            | CLONE_PARENT_SETTID
            | CLONE_CHILD_CLEARTID
            | CLONE_CHILD_SETTID
            | CSIGNAL) as u64;

        // CLONE_SETTLS is implemented by sys_clone.

        let clone_thread = flags & (CLONE_THREAD as u64) != 0;
        let clone_vm = flags & (CLONE_VM as u64) != 0;
        let clone_sighand = flags & (CLONE_SIGHAND as u64) != 0;

        if clone_sighand && !clone_vm {
            return error!(EINVAL);
        }
        if clone_thread && !clone_sighand {
            return error!(EINVAL);
        }

        if clone_thread != clone_vm {
            not_implemented!("CLONE_VM without CLONE_THRAED is not implemented");
            return error!(ENOSYS);
        }

        if flags & !IMPLEMENTED_FLAGS != 0 {
            not_implemented!("clone does not implement flags: 0x{:x}", flags & !IMPLEMENTED_FLAGS);
            return error!(ENOSYS);
        }

        let raw_child_exist_signal = flags & (CSIGNAL as u64);
        let child_exit_signal = if raw_child_exist_signal == 0 {
            None
        } else {
            Some(Signal::try_from(UncheckedSignal::new(raw_child_exist_signal))?)
        };

        let fs = if flags & (CLONE_FS as u64) != 0 { self.fs.clone() } else { self.fs.fork() };
        let files =
            if flags & (CLONE_FILES as u64) != 0 { self.files.clone() } else { self.files.fork() };
        let signal_actions = if flags & (CLONE_SIGHAND as u64) != 0 {
            self.signal_actions.clone()
        } else {
            self.signal_actions.fork()
        };

        let kernel = &self.thread_group.kernel;
        let mut pids = kernel.pids.write();
        let pid = pids.allocate_pid();
        let comm = self.command.read();
        let (thread, thread_group, mm) = if clone_thread {
            create_zircon_thread(self)?
        } else {
            create_zircon_process(kernel, pid, &comm)?
        };

        let child = Self::new(
            pid,
            comm.clone(),
            self.argv.read().clone(),
            thread_group,
            self.id,
            thread,
            files,
            mm,
            fs,
            signal_actions,
            self.creds.read().clone(),
            self.abstract_socket_namespace.clone(),
            self.shell_job_control.clone(),
            child_exit_signal,
        );
        pids.add_task(&child.task);

        if clone_thread {
            self.thread_group.add(&child);
        } else {
            pids.add_thread_group(&child.thread_group);
            child.signals.write().alt_stack = self.signals.read().alt_stack;
            self.mm.snapshot_to(&child.mm)?;
        }

        if flags & (CLONE_PARENT_SETTID as u64) != 0 {
            self.mm.write_object(user_parent_tid, &child.id)?;
        }

        if flags & (CLONE_CHILD_CLEARTID as u64) != 0 {
            *child.clear_child_tid.lock() = user_child_tid;
        }

        if flags & (CLONE_CHILD_SETTID as u64) != 0 {
            child.mm.write_object(user_child_tid, &child.id)?;
        }

        self.children.write().insert(child.id);

        Ok(child)
    }
/// Clone this task.
///
/// Creates a new task object that shares some state with this task
/// according to the given flags.
///
/// Used by the clone() syscall to create both processes and threads.
Clone this task.
Creates a new task object that shares some state with this task
according to the given flags.

Used by the clone() syscall to create both processes and threads.
Clone this task . Creates a new task object that shares some state with this task according to the given flags . Used by the clone () syscall to create both processes and threads .
pub fn clone_task(
        &self,
        flags: u64,
        user_parent_tid: UserRef<pid_t>,
        user_child_tid: UserRef<pid_t>,
    ) -> Result<CurrentTask, Errno> {
        // TODO: Implement more flags.
        const IMPLEMENTED_FLAGS: u64 = (CLONE_VM
            | CLONE_FS
            | CLONE_FILES
            | CLONE_SIGHAND
            | CLONE_THREAD
            | CLONE_SYSVSEM
            | CLONE_SETTLS
            | CLONE_PARENT_SETTID
            | CLONE_CHILD_CLEARTID
            | CLONE_CHILD_SETTID
            | CSIGNAL) as u64;
        // CLONE_SETTLS is implemented by sys_clone.
        let clone_thread = flags & (CLONE_THREAD as u64) != 0;
        let clone_vm = flags & (CLONE_VM as u64) != 0;
        let clone_sighand = flags & (CLONE_SIGHAND as u64) != 0;
        if clone_sighand && !clone_vm {
            return error!(EINVAL);
        }
        if clone_thread && !clone_sighand {
            return error!(EINVAL);
        }
        if clone_thread != clone_vm {
            not_implemented!("CLONE_VM without CLONE_THRAED is not implemented");
            return error!(ENOSYS);
        }
        if flags & !IMPLEMENTED_FLAGS != 0 {
            not_implemented!("clone does not implement flags: 0x{:x}", flags & !IMPLEMENTED_FLAGS);
            return error!(ENOSYS);
        }
        let raw_child_exist_signal = flags & (CSIGNAL as u64);
        let child_exit_signal = if raw_child_exist_signal == 0 {
            None
        } else {
            Some(Signal::try_from(UncheckedSignal::new(raw_child_exist_signal))?)
        };
        let fs = if flags & (CLONE_FS as u64) != 0 { self.fs.clone() } else { self.fs.fork() };
        let files =
            if flags & (CLONE_FILES as u64) != 0 { self.files.clone() } else { self.files.fork() };
        let signal_actions = if flags & (CLONE_SIGHAND as u64) != 0 {
            self.signal_actions.clone()
        } else {
            self.signal_actions.fork()
        };
        let kernel = &self.thread_group.kernel;
        let mut pids = kernel.pids.write();
        let pid = pids.allocate_pid();
        let comm = self.command.read();
        let (thread, thread_group, mm) = if clone_thread {
            create_zircon_thread(self)?
        } else {
            create_zircon_process(kernel, pid, &comm)?
        };
        let child = Self::new(
            pid,
            comm.clone(),
            self.argv.read().clone(),
            thread_group,
            self.id,
            thread,
            files,
            mm,
            fs,
            signal_actions,
            self.creds.read().clone(),
            self.abstract_socket_namespace.clone(),
            self.shell_job_control.clone(),
            child_exit_signal,
        );
        pids.add_task(&child.task);
        if clone_thread {
            self.thread_group.add(&child);
        } else {
            pids.add_thread_group(&child.thread_group);
            child.signals.write().alt_stack = self.signals.read().alt_stack;
            self.mm.snapshot_to(&child.mm)?;
        }
        if flags & (CLONE_PARENT_SETTID as u64) != 0 {
            self.mm.write_object(user_parent_tid, &child.id)?;
        }
        if flags & (CLONE_CHILD_CLEARTID as u64) != 0 {
            *child.clear_child_tid.lock() = user_child_tid;
        }
        if flags & (CLONE_CHILD_SETTID as u64) != 0 {
            child.mm.write_object(user_child_tid, &child.id)?;
        }
        self.children.write().insert(child.id);
        Ok(child)
    }
pub fn clone_task ( & self , flags : u64 , user_parent_tid : UserRef < pid_t > , user_child_tid : UserRef < pid_t > , ) -> Result < CurrentTask , Errno > { // TODO: Implement more flags. const IMPLEMENTED_FLAGS : u64 = ( CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CSIGNAL ) as u64 ; // CLONE_SETTLS is implemented by sys_clone. let clone_thread = flags & ( CLONE_THREAD as u64 ) != 0 ; let clone_vm = flags & ( CLONE_VM as u64 ) != 0 ; let clone_sighand = flags & ( CLONE_SIGHAND as u64 ) != 0 ; if clone_sighand && ! clone_vm { return error ! ( EINVAL ) ; } if clone_thread && ! clone_sighand { return error ! ( EINVAL ) ; } if clone_thread != clone_vm { not_implemented ! ( " " ) ; return error ! ( ENOSYS ) ; } if flags & ! IMPLEMENTED_FLAGS != 0 { not_implemented ! ( " " flags IMPLEMENTED_FLAGS ) ; return error ! ( ENOSYS ) ; } let raw_child_exist_signal = flags & ( CSIGNAL as u64 ) ; let child_exit_signal = if raw_child_exist_signal == 0 { None } else { Some ( Signal :: try_from ( UncheckedSignal :: new ( raw_child_exist_signal ) ) ? ) } ; let fs = if flags & ( CLONE_FS as u64 ) != 0 { self . fs . clone ( ) } else { self . fs . fork ( ) } ; let files = if flags & ( CLONE_FILES as u64 ) != 0 { self . files . clone ( ) } else { self . files . fork ( ) } ; let signal_actions = if flags & ( CLONE_SIGHAND as u64 ) != 0 { self . signal_actions . clone ( ) } else { self . signal_actions . fork ( ) } ; let kernel = & self . thread_group . kernel ; let mut pids = kernel . pids . write ( ) ; let pid = pids . allocate_pid ( ) ; let comm = self . command . read ( ) ; let ( thread , thread_group , mm ) = if clone_thread { create_zircon_thread ( self ) ? } else { create_zircon_process ( kernel , pid , & comm ) ? } ; let child = Self :: new ( pid , comm . clone ( ) , self . argv . read ( ) . clone ( ) , thread_group , self . id , thread , files , mm , fs , signal_actions , self . creds . read ( ) . clone ( ) , self . abstract_socket_namespace . clone ( ) , self . shell_job_control . clone ( ) , child_exit_signal , ) ; pids . add_task ( & child . task ) ; if clone_thread { self . thread_group . add ( & child ) ; } else { pids . add_thread_group ( & child . thread_group ) ; child . signals . write ( ) . alt_stack = self . signals . read ( ) . alt_stack ; self . mm . snapshot_to ( & child . mm ) ? ; } if flags & ( CLONE_PARENT_SETTID as u64 ) != 0 { self . mm . write_object ( user_parent_tid , & child . id ) ? ; } if flags & ( CLONE_CHILD_CLEARTID as u64 ) != 0 { * child . clear_child_tid . lock ( ) = user_child_tid ; } if flags & ( CLONE_CHILD_SETTID as u64 ) != 0 { child . mm . write_object ( user_child_tid , & child . id ) ? ; } self . children . write ( ) . insert ( child . id ) ; Ok ( child ) }
Clone this task.
Clone this task .
&self
flags
u64
user_parent_tid
UserRef<pid_t>
user_child_tid
UserRef<pid_t>
&self
flags
u64
user_parent_tid
UserRef<pid_t>
user_child_tid
UserRef<pid_t>