diff --git a/kernel/src/process/structs.rs b/kernel/src/process/structs.rs index 4a0f30c..8ef01bc 100644 --- a/kernel/src/process/structs.rs +++ b/kernel/src/process/structs.rs @@ -32,41 +32,23 @@ pub struct Thread { /// Pid type /// For strong type separation -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Pid(Option); +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct Pid(usize); impl Pid { - pub fn uninitialized() -> Self { - Pid(None) - } - - /// Return if it was uninitialized before this call - /// When returning true, it usually means this is the first thread - pub fn set_if_uninitialized(&mut self, tid: Tid) -> bool { - if self.0 == None { - self.0 = Some(tid as usize); - true - } else { - false - } - } - pub fn get(&self) -> usize { - self.0.unwrap() + self.0 } /// Return whether this pid represents the init process pub fn is_init(&self) -> bool { - self.0 == Some(0) + self.0 == 0 } } impl fmt::Display for Pid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.0 { - Some(pid) => write!(f, "{}", pid), - None => write!(f, "None"), - } + write!(f, "{}", self.0) } } @@ -103,21 +85,9 @@ impl rcore_thread::Context for Thread { } fn set_tid(&mut self, tid: Tid) { - // set pid=tid if unspecified let mut proc = self.proc.lock(); - if proc.pid.set_if_uninitialized(tid) { - // first thread in the process - // link to its ppid - if let Some(parent) = &proc.parent { - let mut parent = parent.lock(); - parent.children.push(Arc::downgrade(&self.proc)); - } - } // add it to threads proc.threads.push(tid); - PROCESSES - .write() - .insert(proc.pid.get(), Arc::downgrade(&self.proc)); } } @@ -140,18 +110,19 @@ impl Thread { kstack, clear_child_tid: 0, // TODO: kernel thread should not have a process - proc: Arc::new(Mutex::new(Process { + proc: Process { vm, files: BTreeMap::default(), cwd: String::from("/"), futexes: BTreeMap::default(), - pid: Pid::uninitialized(), + pid: Pid(0), parent: None, children: Vec::new(), threads: Vec::new(), child_exit: Arc::new(Condvar::new()), child_exit_code: BTreeMap::new(), - })), + } + .add_to_table(), }) } @@ -290,18 +261,19 @@ impl Thread { }, kstack, clear_child_tid: 0, - proc: Arc::new(Mutex::new(Process { + proc: Process { vm, files, cwd: String::from("/"), futexes: BTreeMap::default(), - pid: Pid::uninitialized(), + pid: Pid(0), parent: None, children: Vec::new(), threads: Vec::new(), child_exit: Arc::new(Condvar::new()), child_exit_code: BTreeMap::new(), - })), + } + .add_to_table(), }) } @@ -330,18 +302,19 @@ impl Thread { context: unsafe { Context::new_fork(tf, kstack.top(), vm.token()) }, kstack, clear_child_tid: 0, - proc: Arc::new(Mutex::new(Process { + proc: Process { vm, files, cwd, futexes: BTreeMap::default(), - pid: Pid::uninitialized(), + pid: Pid(0), parent, children: Vec::new(), threads: Vec::new(), child_exit: Arc::new(Condvar::new()), child_exit_code: BTreeMap::new(), - })), + } + .add_to_table(), }) } @@ -365,9 +338,39 @@ impl Thread { } impl Process { - pub fn get_free_fd(&self) -> usize { + /// Assign a pid and put itself to global process table. + fn add_to_table(mut self) -> Arc> { + let mut process_table = PROCESSES.write(); + + // assign pid + let pid = (0..) + .find(|i| match process_table.get(i) { + Some(p) if p.upgrade().is_some() => false, + _ => true, + }) + .unwrap(); + self.pid = Pid(pid); + + // put to process table + let self_ref = Arc::new(Mutex::new(self)); + process_table.insert(pid, Arc::downgrade(&self_ref)); + + // link to parent + if let Some(parent) = &self_ref.lock().parent { + parent.lock().children.push(Arc::downgrade(&self_ref)); + } + + self_ref + } + fn get_free_fd(&self) -> usize { (0..).find(|i| !self.files.contains_key(i)).unwrap() } + /// Add a file to the process, return its fd. + pub fn add_file(&mut self, file_like: FileLike) -> usize { + let fd = self.get_free_fd(); + self.files.insert(fd, file_like); + fd + } pub fn get_futex(&mut self, uaddr: usize) -> Arc { if !self.futexes.contains_key(&uaddr) { self.futexes.insert(uaddr, Arc::new(Condvar::new())); diff --git a/kernel/src/syscall/fs.rs b/kernel/src/syscall/fs.rs index 757f4e0..e80cd39 100644 --- a/kernel/src/syscall/fs.rs +++ b/kernel/src/syscall/fs.rs @@ -277,10 +277,8 @@ pub fn sys_openat(dir_fd: usize, path: *const u8, flags: usize, mode: usize) -> proc.lookup_inode_at(dir_fd, &path, true)? }; - let fd = proc.get_free_fd(); - let file = FileHandle::new(inode, flags.to_options()); - proc.files.insert(fd, FileLike::File(file)); + let fd = proc.add_file(FileLike::File(file)); Ok(fd) } @@ -636,9 +634,7 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult { proc.vm.check_write_array(fds, 2)?; let (read, write) = Pipe::create_pair(); - let read_fd = proc.get_free_fd(); - proc.files.insert( - read_fd, + let read_fd = proc.add_file( FileLike::File(FileHandle::new( Arc::new(read), OpenOptions { @@ -649,9 +645,7 @@ pub fn sys_pipe(fds: *mut u32) -> SysResult { )), ); - let write_fd = proc.get_free_fd(); - proc.files.insert( - write_fd, + let write_fd = proc.add_file( FileLike::File(FileHandle::new( Arc::new(write), OpenOptions { diff --git a/kernel/src/syscall/net.rs b/kernel/src/syscall/net.rs index 1372340..34ebb14 100644 --- a/kernel/src/syscall/net.rs +++ b/kernel/src/syscall/net.rs @@ -39,8 +39,7 @@ pub fn sys_socket(domain: usize, socket_type: usize, protocol: usize) -> SysResu }, _ => return Err(SysError::EAFNOSUPPORT), }; - let fd = proc.get_free_fd(); - proc.files.insert(fd, FileLike::Socket(socket)); + let fd = proc.add_file(FileLike::Socket(socket)); Ok(fd) } @@ -237,8 +236,7 @@ pub fn sys_accept(fd: usize, addr: *mut SockAddr, addr_len: *mut u32) -> SysResu let socket = proc.get_socket(fd)?; let (new_socket, remote_endpoint) = socket.accept()?; - let new_fd = proc.get_free_fd(); - proc.files.insert(new_fd, FileLike::Socket(new_socket)); + let new_fd = proc.add_file(FileLike::Socket(new_socket)); if !addr.is_null() { let sockaddr_in = SockAddr::from(remote_endpoint); diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index f0fc954..046391b 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -6,7 +6,8 @@ use crate::fs::INodeExt; /// Fork the current process. Return the child's PID. pub fn sys_fork(tf: &TrapFrame) -> SysResult { let new_thread = current_thread().fork(tf); - let pid = processor().manager().add(new_thread); + let pid = new_thread.proc.lock().pid.get(); + processor().manager().add(new_thread); info!("fork: {} -> {}", thread::current().id(), pid); Ok(pid) }