minimal impl sys_clone

master
WangRunji 6 years ago
parent c3563192b5
commit d51c52902d

@ -105,7 +105,7 @@ struct ContextData {
impl ContextData {
fn new(cr3: usize) -> Self {
ContextData { rip: forkret as usize, cr3, ..ContextData::default() }
ContextData { rip: trap_ret as usize, cr3, ..ContextData::default() }
}
}
@ -114,7 +114,6 @@ impl ContextData {
#[repr(C)]
struct InitStack {
context: ContextData,
trapret: usize,
tf: TrapFrame,
}
@ -130,11 +129,6 @@ extern {
fn trap_ret();
}
/// The entry point of new thread
extern fn forkret() {
// Will return to `trapret`
}
#[derive(Debug)]
pub struct Context(usize);
@ -189,23 +183,23 @@ impl Context {
pub unsafe fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, kstack_top: usize, cr3: usize) -> Self {
InitStack {
context: ContextData::new(cr3),
trapret: trap_ret as usize,
tf: TrapFrame::new_kernel_thread(entry, arg, kstack_top),
}.push_at(kstack_top)
}
pub unsafe fn new_user_thread(entry_addr: usize, ustack_top: usize, kstack_top: usize, is32: bool, cr3: usize) -> Self {
InitStack {
context: ContextData::new(cr3),
trapret: trap_ret as usize,
tf: TrapFrame::new_user_thread(entry_addr, ustack_top, is32),
}.push_at(kstack_top)
}
pub unsafe fn new_fork(tf: &TrapFrame, kstack_top: usize, cr3: usize) -> Self {
pub unsafe fn new_fork(tf: &TrapFrame, ustack_top: Option<usize>, kstack_top: usize, cr3: usize) -> Self {
InitStack {
context: ContextData::new(cr3),
trapret: trap_ret as usize,
tf: {
let mut tf = tf.clone();
if let Some(sp) = ustack_top {
tf.rsp = sp;
}
tf.rax = 0;
// skip syscall inst;
tf.rip = tf.rip + 2;

@ -214,7 +214,7 @@ impl Thread {
Box::new(Thread {
context: unsafe { Context::new_fork(tf, kstack.top(), memory_set.token()) },
context: unsafe { Context::new_fork(tf, None, kstack.top(), memory_set.token()) },
kstack,
proc: Arc::new(Mutex::new(Process {
memory_set,
@ -223,6 +223,17 @@ impl Thread {
})),
})
}
/// Create a new thread in the same process.
pub fn clone(&self, tf: &TrapFrame, stack_top: usize) -> Box<Thread> {
let kstack = KernelStack::new();
let token = self.proc.lock().memory_set.token();
Box::new(Thread {
context: unsafe { Context::new_fork(tf, Some(stack_top), kstack.top(), token) },
kstack,
proc: self.proc.clone(),
})
}
}
impl Process {

@ -30,7 +30,7 @@ pub extern fn shell(_arg: usize) -> ! {
if cmd == "" {
continue;
}
let name = cmd.split(' ').next().unwrap();
let name = cmd.trim().split(' ').next().unwrap();
if let Ok(file) = ROOT_INODE.lookup(name) {
let data = file.read_as_vec().unwrap();
let pid = processor().manager().add(Thread::new_user(data.as_slice(), cmd.split(' ')), thread::current().id());

@ -45,18 +45,19 @@ pub fn sys_mprotect(addr: usize, len: usize, prot: usize) -> SysResult {
let mut proc = process();
let attr = prot.to_attr();
// FIXME: properly set the attribute of the area
// now some mut ptr check is fault
let memory_area = proc.memory_set.iter().find(|area| area.contains(addr));
if memory_area.is_some() {
proc.memory_set.edit(|pt| {
for page in Page::range_of(addr, addr + len) {
let entry = pt.get_entry(page.start_address()).expect("failed to get entry");
attr.apply(entry);
}
});
Ok(0)
} else {
Err(SysError::ENOMEM)
if memory_area.is_none() {
return Err(SysError::ENOMEM);
}
proc.memory_set.edit(|pt| {
for page in Page::range_of(addr, addr + len) {
let entry = pt.get_entry(page.start_address()).expect("failed to get entry");
attr.apply(entry);
}
});
Ok(0)
}
pub fn sys_munmap(addr: usize, len: usize) -> SysResult {

@ -76,7 +76,7 @@ pub fn syscall(id: usize, args: [usize; 6], tf: &mut TrapFrame) -> isize {
052 => sys_getpeername(args[0], args[1] as *mut SockaddrIn, args[2] as *mut u32),
054 => sys_setsockopt(args[0], args[1], args[2], args[3] as *const u8, args[4]),
055 => sys_getsockopt(args[0], args[1], args[2], args[3] as *mut u8, args[4] as *mut u32),
// 056 => sys_clone(),
056 => sys_clone(args[0], args[1], args[2] as *mut usize, args[3] as *mut usize, tf),
057 => sys_fork(tf),
// use fork for vfork
058 => sys_fork(tf),

@ -4,12 +4,41 @@ use super::*;
/// Fork the current process. Return the child's PID.
pub fn sys_fork(tf: &TrapFrame) -> SysResult {
let context = current_thread().fork(tf);
let pid = processor().manager().add(context, thread::current().id());
let new_thread = current_thread().fork(tf);
let pid = processor().manager().add(new_thread, thread::current().id());
info!("fork: {} -> {}", thread::current().id(), pid);
Ok(pid)
}
/// Create a new thread in the current process.
/// The new thread's stack pointer will be set to `newsp`.
/// The child tid will be stored at both `parent_tid` and `child_tid`.
/// This is partially implemented for musl only.
pub fn sys_clone(flags: usize, newsp: usize, parent_tid: *mut usize, child_tid: *mut usize, tf: &TrapFrame) -> SysResult {
info!("clone: flags: {:#x}, newsp: {:#x}, parent_tid: {:?}, child_tid: {:?}",
flags, newsp, parent_tid, child_tid);
if flags != 0x7d0f00 {
warn!("sys_clone only support musl pthread_create");
return Err(SysError::ENOSYS);
}
{
// FIXME: see sys_mprotect
// let proc = process();
// proc.memory_set.check_mut_ptr(parent_tid)?;
// proc.memory_set.check_mut_ptr(child_tid)?;
}
// FIXME: tf.rip => tf.ip() for all arch
let new_thread = current_thread().clone(tf, newsp);
// FIXME: parent pid
let tid = processor().manager().add(new_thread, thread::current().id());
info!("clone: {} -> {}", thread::current().id(), tid);
unsafe {
parent_tid.write(tid);
child_tid.write(tid);
}
Ok(tid)
}
/// Wait the process exit.
/// Return the PID. Store exit code to `code` if it's not null.
pub fn sys_wait4(pid: isize, wstatus: *mut i32) -> SysResult {

Loading…
Cancel
Save