mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-26 10:53:25 +00:00
Add syscall clone3
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
a5707b4ddc
commit
07fbbcfd8c
@ -59,6 +59,7 @@ bitflags! {
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct CloneArgs {
|
||||
new_sp: u64,
|
||||
stack_size: usize,
|
||||
parent_tidptr: Vaddr,
|
||||
child_tidptr: Vaddr,
|
||||
tls: u64,
|
||||
@ -66,9 +67,12 @@ pub struct CloneArgs {
|
||||
}
|
||||
|
||||
impl CloneArgs {
|
||||
pub const fn default() -> Self {
|
||||
/// Clone Args for syscall fork.
|
||||
/// TODO: set the correct values
|
||||
pub const fn for_fork() -> Self {
|
||||
CloneArgs {
|
||||
new_sp: 0,
|
||||
stack_size: 0,
|
||||
parent_tidptr: 0,
|
||||
child_tidptr: 0,
|
||||
tls: 0,
|
||||
@ -78,6 +82,7 @@ impl CloneArgs {
|
||||
|
||||
pub const fn new(
|
||||
new_sp: u64,
|
||||
stack_size: usize,
|
||||
parent_tidptr: Vaddr,
|
||||
child_tidptr: Vaddr,
|
||||
tls: u64,
|
||||
@ -85,6 +90,7 @@ impl CloneArgs {
|
||||
) -> Self {
|
||||
CloneArgs {
|
||||
new_sp,
|
||||
stack_size,
|
||||
parent_tidptr,
|
||||
child_tidptr,
|
||||
tls,
|
||||
@ -121,43 +127,28 @@ impl CloneFlags {
|
||||
}
|
||||
}
|
||||
|
||||
/// Clone a child thread. Without schedule it to run.
|
||||
pub fn clone_child(parent_context: UserContext, clone_args: CloneArgs) -> Result<Tid> {
|
||||
/// Clone a child thread or child process.
|
||||
///
|
||||
/// FIXME: currently, the child process or thread will be scheduled to run at once,
|
||||
/// but this may not be the expected bahavior.
|
||||
pub fn clone_child(parent_context: &UserContext, clone_args: CloneArgs) -> Result<Tid> {
|
||||
clone_args.clone_flags.check_unsupported_flags()?;
|
||||
if clone_args.clone_flags.contains(CloneFlags::CLONE_THREAD) {
|
||||
let child_thread = clone_child_thread(parent_context, clone_args)?;
|
||||
let child_tid = child_thread.tid();
|
||||
debug!(
|
||||
"*********schedule child thread, current tid = {}, child pid = {}**********",
|
||||
current_thread!().tid(),
|
||||
child_tid
|
||||
);
|
||||
child_thread.run();
|
||||
debug!(
|
||||
"*********return to parent thread, current tid = {}, child pid = {}*********",
|
||||
current_thread!().tid(),
|
||||
child_tid
|
||||
);
|
||||
|
||||
let child_tid = child_thread.tid();
|
||||
Ok(child_tid)
|
||||
} else {
|
||||
let child_process = clone_child_process(parent_context, clone_args)?;
|
||||
let child_pid = child_process.pid();
|
||||
debug!(
|
||||
"*********schedule child process, current pid = {}, child pid = {}**********",
|
||||
current!().pid(),
|
||||
child_pid
|
||||
);
|
||||
child_process.run();
|
||||
debug!(
|
||||
"*********return to parent process, current pid = {}, child pid = {}*********",
|
||||
current!().pid(),
|
||||
child_pid
|
||||
);
|
||||
|
||||
let child_pid = child_process.pid();
|
||||
Ok(child_pid)
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_child_thread(parent_context: UserContext, clone_args: CloneArgs) -> Result<Arc<Thread>> {
|
||||
fn clone_child_thread(parent_context: &UserContext, clone_args: CloneArgs) -> Result<Arc<Thread>> {
|
||||
let clone_flags = clone_args.clone_flags;
|
||||
let current = current!();
|
||||
debug_assert!(clone_flags.contains(CloneFlags::CLONE_VM));
|
||||
@ -170,6 +161,7 @@ fn clone_child_thread(parent_context: UserContext, clone_args: CloneArgs) -> Res
|
||||
let child_cpu_context = clone_cpu_context(
|
||||
parent_context,
|
||||
clone_args.new_sp,
|
||||
clone_args.stack_size,
|
||||
clone_args.tls,
|
||||
clone_flags,
|
||||
);
|
||||
@ -215,7 +207,10 @@ fn clone_child_thread(parent_context: UserContext, clone_args: CloneArgs) -> Res
|
||||
Ok(child_thread)
|
||||
}
|
||||
|
||||
fn clone_child_process(parent_context: UserContext, clone_args: CloneArgs) -> Result<Arc<Process>> {
|
||||
fn clone_child_process(
|
||||
parent_context: &UserContext,
|
||||
clone_args: CloneArgs,
|
||||
) -> Result<Arc<Process>> {
|
||||
let current = current!();
|
||||
let parent = Arc::downgrade(¤t);
|
||||
let clone_flags = clone_args.clone_flags;
|
||||
@ -231,6 +226,7 @@ fn clone_child_process(parent_context: UserContext, clone_args: CloneArgs) -> Re
|
||||
let child_cpu_context = clone_cpu_context(
|
||||
parent_context,
|
||||
clone_args.new_sp,
|
||||
clone_args.stack_size,
|
||||
clone_args.tls,
|
||||
clone_flags,
|
||||
);
|
||||
@ -368,12 +364,13 @@ fn clone_vm(parent_process_vm: &ProcessVm, clone_flags: CloneFlags) -> Result<Pr
|
||||
}
|
||||
|
||||
fn clone_cpu_context(
|
||||
parent_context: UserContext,
|
||||
parent_context: &UserContext,
|
||||
new_sp: u64,
|
||||
stack_size: usize,
|
||||
tls: u64,
|
||||
clone_flags: CloneFlags,
|
||||
) -> UserContext {
|
||||
let mut child_context = parent_context;
|
||||
let mut child_context = *parent_context;
|
||||
// The return value of child thread is zero
|
||||
child_context.set_syscall_ret(0);
|
||||
|
||||
@ -382,7 +379,14 @@ fn clone_cpu_context(
|
||||
debug_assert!(new_sp != 0);
|
||||
}
|
||||
if new_sp != 0 {
|
||||
child_context.set_stack_pointer(new_sp as usize);
|
||||
// If stack size is not 0, the `new_sp` points to the BOTTOMMOST byte of stack.
|
||||
if stack_size != 0 {
|
||||
child_context.set_stack_pointer(new_sp as usize + stack_size);
|
||||
}
|
||||
// If stack size is 0, the new_sp points to the TOPMOST byte of stack.
|
||||
else {
|
||||
child_context.set_stack_pointer(new_sp as usize);
|
||||
}
|
||||
}
|
||||
if clone_flags.contains(CloneFlags::CLONE_SETTLS) {
|
||||
child_context.set_tls_pointer(tls as usize);
|
||||
|
@ -12,7 +12,7 @@ use crate::syscall::{
|
||||
chown::{sys_chown, sys_fchown, sys_fchownat, sys_lchown},
|
||||
chroot::sys_chroot,
|
||||
clock_gettime::sys_clock_gettime,
|
||||
clone::sys_clone,
|
||||
clone::{sys_clone, sys_clone3},
|
||||
close::sys_close,
|
||||
connect::sys_connect,
|
||||
dup::{sys_dup, sys_dup2},
|
||||
@ -248,4 +248,5 @@ impl_syscall_nums_and_dispatch_fn! {
|
||||
SYS_PRLIMIT64 = 302 => sys_prlimit64(args[..4]);
|
||||
SYS_GETRANDOM = 318 => sys_getrandom(args[..3]);
|
||||
SYS_EXECVEAT = 322 => sys_execveat(args[..5], &mut context);
|
||||
SYS_CLONE3 = 435 => sys_clone3(args[..2], &context);
|
||||
}
|
||||
|
@ -5,7 +5,8 @@ use aster_frame::cpu::UserContext;
|
||||
use super::SyscallReturn;
|
||||
use crate::{
|
||||
prelude::*,
|
||||
process::{clone_child, CloneArgs, CloneFlags},
|
||||
process::{clone_child, signal::constants::SIGCHLD, CloneArgs, CloneFlags},
|
||||
util::read_val_from_user,
|
||||
};
|
||||
|
||||
// The order of arguments for clone differs in different architecture.
|
||||
@ -20,7 +21,94 @@ pub fn sys_clone(
|
||||
) -> Result<SyscallReturn> {
|
||||
let clone_flags = CloneFlags::from(clone_flags);
|
||||
debug!("flags = {:?}, child_stack_ptr = 0x{:x}, parent_tid_ptr = 0x{:x}, child tid ptr = 0x{:x}, tls = 0x{:x}", clone_flags, new_sp, parent_tidptr, child_tidptr, tls);
|
||||
let clone_args = CloneArgs::new(new_sp, parent_tidptr, child_tidptr, tls, clone_flags);
|
||||
let child_pid = clone_child(*parent_context, clone_args).unwrap();
|
||||
let clone_args = CloneArgs::new(new_sp, 0, parent_tidptr, child_tidptr, tls, clone_flags);
|
||||
let child_pid = clone_child(parent_context, clone_args).unwrap();
|
||||
Ok(SyscallReturn::Return(child_pid as _))
|
||||
}
|
||||
|
||||
pub fn sys_clone3(
|
||||
clong_args_addr: Vaddr,
|
||||
size: usize,
|
||||
parent_context: &UserContext,
|
||||
) -> Result<SyscallReturn> {
|
||||
trace!(
|
||||
"clone args addr = 0x{:x}, size = 0x{:x}",
|
||||
clong_args_addr,
|
||||
size
|
||||
);
|
||||
if size != core::mem::size_of::<Clone3Args>() {
|
||||
return_errno_with_message!(Errno::EINVAL, "invalid size");
|
||||
}
|
||||
|
||||
let clone_args = {
|
||||
let args: Clone3Args = read_val_from_user(clong_args_addr)?;
|
||||
trace!("clone3 args = {:x?}", args);
|
||||
CloneArgs::from(args)
|
||||
};
|
||||
debug!("clone args = {:x?}", clone_args);
|
||||
|
||||
let child_pid = clone_child(parent_context, clone_args)?;
|
||||
trace!("child pid = {}", child_pid);
|
||||
Ok(SyscallReturn::Return(child_pid as _))
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
struct Clone3Args {
|
||||
/// Flags bit mask
|
||||
flags: u64,
|
||||
/// Where to store PID file descriptor
|
||||
pidfd: u64,
|
||||
/// Where to store child TID in child's memory
|
||||
child_tid: u64,
|
||||
/// Where to store child TID in parent's memory
|
||||
parent_tid: u64,
|
||||
/// Signal to deliver to parent on child termination
|
||||
exit_signal: u64,
|
||||
/// Pointer to lowest byte of stack
|
||||
stack: u64,
|
||||
/// Size of stack
|
||||
stack_size: u64,
|
||||
/// Location of new TLS
|
||||
tls: u64,
|
||||
/// Pointer to a pid_t array
|
||||
set_tid: u64,
|
||||
/// Number of elements in set_tid
|
||||
set_tid_size: u64,
|
||||
/// File descriptor for target cgroup of child
|
||||
cgroup: u64,
|
||||
}
|
||||
|
||||
impl From<Clone3Args> for CloneArgs {
|
||||
fn from(value: Clone3Args) -> Self {
|
||||
const FLAGS_MASK: u64 = 0xff;
|
||||
let clone_flags =
|
||||
CloneFlags::from(value.exit_signal & FLAGS_MASK | value.flags & !FLAGS_MASK);
|
||||
|
||||
// TODO: deal with pidfd, exit_signal, set_tid, set_tid_size, cgroup
|
||||
if value.exit_signal != 0 || value.exit_signal as u8 != SIGCHLD.as_u8() {
|
||||
warn!("exit signal is not supported");
|
||||
}
|
||||
|
||||
if value.pidfd != 0 {
|
||||
warn!("pidfd is not supported");
|
||||
}
|
||||
|
||||
if value.set_tid != 0 || value.set_tid_size != 0 {
|
||||
warn!("set_tid is not supported");
|
||||
}
|
||||
|
||||
if value.cgroup != 0 {
|
||||
warn!("cgroup is not supported");
|
||||
}
|
||||
|
||||
CloneArgs::new(
|
||||
value.stack,
|
||||
value.stack_size as _,
|
||||
value.parent_tid as _,
|
||||
value.child_tid as _,
|
||||
value.tls,
|
||||
clone_flags,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,7 @@ use crate::{
|
||||
|
||||
pub fn sys_fork(parent_context: &UserContext) -> Result<SyscallReturn> {
|
||||
let current = current!();
|
||||
// FIXME: set correct args for fork
|
||||
let clone_args = CloneArgs::default();
|
||||
let child_pid = clone_child(*parent_context, clone_args).unwrap();
|
||||
let clone_args = CloneArgs::for_fork();
|
||||
let child_pid = clone_child(parent_context, clone_args).unwrap();
|
||||
Ok(SyscallReturn::Return(child_pid as _))
|
||||
}
|
||||
|
Reference in New Issue
Block a user