From 372649f3d600013b170238aaf4f1294a49c18d9c Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Thu, 3 Jan 2019 21:20:55 +0800 Subject: [PATCH] Add getpid and getppid --- src/libos/include/syscall.h | 3 +- src/libos/src/fs/file_table.rs | 9 +---- src/libos/src/lib.rs | 3 +- src/libos/src/process/mod.rs | 50 +++++++++++++++++++++++--- src/libos/src/process/process.rs | 40 ++++++++++----------- src/libos/src/process/process_table.rs | 2 ++ src/libos/src/process/spawn/mod.rs | 12 ++++++- src/libos/src/process/task.rs | 26 +++++++++----- src/libos/src/syscall/mod.rs | 13 +++++-- src/libos/src/syscall/syscall_entry.c | 4 +++ src/libos/src/vm/mod.rs | 4 +-- src/libos/src/vm/process_vm.rs | 2 +- src/libos/src/vm/vm_range.rs | 10 ++++++ test/Makefile | 2 +- test/getpid/Makefile | 4 +++ test/getpid/main.c | 9 +++++ 16 files changed, 141 insertions(+), 52 deletions(-) create mode 100644 test/getpid/Makefile create mode 100644 test/getpid/main.c diff --git a/src/libos/include/syscall.h b/src/libos/include/syscall.h index 01f1eb81..59d74050 100644 --- a/src/libos/include/syscall.h +++ b/src/libos/include/syscall.h @@ -22,8 +22,9 @@ extern int occlum_spawn(int* child_pid, const char* path, const char** argv, const char** envp); extern int occlum_wait4(int child_pid, int* status, int options/*, struct rusage* rusage*/); -extern unsigned int occlum_getpid(void); extern void occlum_exit(int status); +extern unsigned int occlum_getpid(void); +extern unsigned int occlum_getppid(void); extern void *occlum_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); extern int occlum_munmap(void *addr, size_t length); diff --git a/src/libos/src/fs/file_table.rs b/src/libos/src/fs/file_table.rs index e517db39..b855390e 100644 --- a/src/libos/src/fs/file_table.rs +++ b/src/libos/src/fs/file_table.rs @@ -7,7 +7,7 @@ pub type FileDesc = u32; // Invariant 1: fd < max_fd, where fd is any fd in the table // Invariant 2: max_fd = table.size() // Invariant 3: num_fds <= table.size() -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Default)] #[repr(C)] pub struct FileTable { table: Vec>, @@ -72,10 +72,3 @@ impl FileTable { del_file } } - -impl Default for FileTable { - fn default() -> FileTable { - FileTable::new() - } -} - diff --git a/src/libos/src/lib.rs b/src/libos/src/lib.rs index d4aa8785..1eb64503 100644 --- a/src/libos/src/lib.rs +++ b/src/libos/src/lib.rs @@ -78,7 +78,8 @@ fn do_boot(path_str: &str) -> Result<(), Error> { let argv = std::vec::Vec::new(); let envp = std::vec::Vec::new(); - process::do_spawn(&path_str, &argv, &envp)?; + let parent = &process::IDLE_PROCESS; + process::do_spawn(&path_str, &argv, &envp, parent)?; Ok(()) } diff --git a/src/libos/src/process/mod.rs b/src/libos/src/process/mod.rs index 798cb0bc..42c0f1a5 100644 --- a/src/libos/src/process/mod.rs +++ b/src/libos/src/process/mod.rs @@ -1,20 +1,57 @@ -pub use self::process::{Process, ProcessRef, Status, pid_t}; +pub use self::process::{Status, IDLE_PROCESS}; pub use self::task::{get_current, run_task}; pub mod table { pub use super::process_table::{get}; } pub use self::spawn::{do_spawn}; + +#[allow(non_camel_case_types)] +pub type pid_t = u32; + +#[derive(Debug)] +pub struct Process { + task: Task, + status: Status, + pid: pid_t, + tgid: pid_t, + exit_status: i32, + exec_path: String, + parent: Option, + children: Vec, + vm: ProcessVM, + file_table: FileTable, +} + +pub type ProcessRef = Arc>; + + pub fn do_getpid() -> pid_t { let current_ref = get_current(); - let current_process = current_ref.lock().unwrap(); - current_process.get_pid() + let current = current_ref.lock().unwrap(); + current.get_pid() +} + +pub fn do_getppid() -> pid_t { + let current_ref = get_current(); + let current = current_ref.lock().unwrap(); + let parent_ref = current.get_parent(); + let parent = parent_ref.lock().unwrap(); + parent.get_pid() } pub fn do_exit(exit_status: i32) { let current_ref = get_current(); - let mut current_process = current_ref.lock().unwrap(); - current_process.exit(exit_status); + let mut current = current_ref.lock().unwrap(); + + current.exit_status = exit_status; + current.status = Status::ZOMBIE; + + for child_ref in ¤t.children { + let mut child = child_ref.lock().unwrap(); + child.parent = Some(IDLE_PROCESS.clone()); + } + current.children.clear(); } pub fn do_wait4(child_pid: u32) -> Result { @@ -43,3 +80,6 @@ mod process_table; mod spawn; use prelude::*; +use vm::{ProcessVM, VMRangeTrait}; +use fs::{FileTable, File, FileRef}; +use self::task::{Task}; diff --git a/src/libos/src/process/process.rs b/src/libos/src/process/process.rs index 1ed30bb2..077c96b3 100644 --- a/src/libos/src/process/process.rs +++ b/src/libos/src/process/process.rs @@ -3,23 +3,24 @@ use super::task::{Task}; use vm::{ProcessVM, VMRangeTrait}; use fs::{FileTable, File, FileRef}; -#[allow(non_camel_case_types)] -pub type pid_t = u32; - -#[derive(Debug)] -pub struct Process { - task: Task, - status: Status, - pid: pid_t, - tgid: pid_t, - exit_status: i32, - exec_path: String, - vm: ProcessVM, - file_table: FileTable, +lazy_static! { + // Dummy object to make all processes having a parent + pub static ref IDLE_PROCESS: ProcessRef = { + Arc::new(SgxMutex::new(Process { + task: Default::default(), + status: Default::default(), + pid: 0, + tgid: 0, + exit_status: 0, + exec_path: "".to_owned(), + parent: None, + children: Vec::new(), + vm: Default::default(), + file_table: Default::default(), + })) + }; } -pub type ProcessRef = Arc>; - impl Process { pub fn new(exec_path: &str, task: Task, vm: ProcessVM, file_table: FileTable) -> Result<(pid_t, ProcessRef), Error> @@ -32,6 +33,8 @@ impl Process { tgid: new_pid, exec_path: exec_path.to_owned(), exit_status: 0, + parent: None, + children: Vec::new(), vm: vm, file_table: file_table, })); @@ -49,11 +52,8 @@ impl Process { pub fn get_vm_mut(&mut self) -> &mut ProcessVM { &mut self.vm } pub fn get_files(&self) -> &FileTable { &self.file_table } pub fn get_files_mut(&mut self) -> &mut FileTable { &mut self.file_table } - - pub fn exit(&mut self, exit_status: i32) { - self.exit_status = exit_status; - self.status = Status::ZOMBIE; - } + pub fn get_parent(&self) -> &ProcessRef { self.parent.as_ref().unwrap() } + pub fn get_children(&self) -> &[ProcessRef] { &self.children } } impl Drop for Process { diff --git a/src/libos/src/process/process_table.rs b/src/libos/src/process/process_table.rs index 51fc851d..ac4b9752 100644 --- a/src/libos/src/process/process_table.rs +++ b/src/libos/src/process/process_table.rs @@ -27,6 +27,8 @@ pub fn alloc_pid() -> u32 { } pub fn free_pid(pid: u32) { + // PID 0 is reserved for idle thread, thus no need to free + if pid == 0 { return; } // TODO: } diff --git a/src/libos/src/process/spawn/mod.rs b/src/libos/src/process/spawn/mod.rs index 5dfe0c1b..e0e9ec94 100644 --- a/src/libos/src/process/spawn/mod.rs +++ b/src/libos/src/process/spawn/mod.rs @@ -14,7 +14,8 @@ mod init_vm; mod elf_helper; mod segment; -pub fn do_spawn>(elf_path: &P, argv: &[CString], envp: &[CString]) +pub fn do_spawn>(elf_path: &P, argv: &[CString], envp: &[CString], + parent_ref: &ProcessRef) -> Result { let mut elf_buf = { @@ -58,6 +59,7 @@ pub fn do_spawn>(elf_path: &P, argv: &[CString], envp: &[CString] let exec_path = elf_path.as_ref().to_str().unwrap(); Process::new(exec_path, task, vm, files)? }; + parent_adopts_new_child(&parent_ref, &new_process_ref); process_table::put(new_pid, new_process_ref.clone()); task::enqueue_task(new_process_ref); Ok(new_pid) @@ -102,3 +104,11 @@ fn init_stack(stack_top: usize, argv: &[CString], envp: &[CString]) init_stack::do_init(stack_top, 4096, argv, envp, &auxtbl) } + +fn parent_adopts_new_child(parent_ref: &ProcessRef, child_ref: &ProcessRef) +{ + let mut parent = parent_ref.lock().unwrap(); + let mut child = child_ref.lock().unwrap(); + parent.children.push(child_ref.clone()); + child.parent = Some(parent_ref.clone()); +} diff --git a/src/libos/src/process/task.rs b/src/libos/src/process/task.rs index 1d3576ad..ace4b1fc 100644 --- a/src/libos/src/process/task.rs +++ b/src/libos/src/process/task.rs @@ -66,18 +66,26 @@ pub fn run_task() -> Result { Ok(exit_status) } - thread_local! { - static _CURRENT_PROCESS_PTR: Cell<*const SgxMutex> = - Cell::new(0 as *const SgxMutex); + static _CURRENT_PROCESS_PTR: Cell<*const SgxMutex> = { + Cell::new(0 as *const SgxMutex) + }; } -pub fn get_current() -> &'static SgxMutex { - let mut process_ptr = 0 as *const SgxMutex; - _CURRENT_PROCESS_PTR.with(|cp| { - process_ptr = cp.get(); - }); - unsafe { mem::transmute(process_ptr) } +pub fn get_current() -> ProcessRef { + let current_ptr = { + let mut current_ptr = 0 as *const SgxMutex; + _CURRENT_PROCESS_PTR.with(|cell| { + current_ptr = cell.get(); + }); + current_ptr + }; + + let current_ref = unsafe { Arc::from_raw(current_ptr) }; + let current_ref_clone = current_ref.clone(); + Arc::into_raw(current_ref); + + current_ref_clone } fn set_current(process: &ProcessRef) { diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 399f1ac6..22d4800a 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -30,7 +30,7 @@ fn check_mut_array_from_user(user_buf: *mut T, count: usize) -> Result<(), Er Ok(()) } -fn clone_string_from_user_safely(user_ptr: *const c_char) +fn clone_cstring_from_user_safely(user_ptr: *const c_char) -> Result { check_ptr_from_user(user_ptr)?; @@ -329,6 +329,12 @@ pub extern "C" fn occlum_getpid() -> c_uint process::do_getpid() } +#[no_mangle] +pub extern "C" fn occlum_getppid() -> c_uint +{ + process::do_getppid() +} + #[no_mangle] pub extern "C" fn occlum_exit(status: i32) { @@ -348,11 +354,12 @@ fn do_spawn(child_pid_ptr: *mut c_uint, -> Result<(), Error> { check_mut_ptr_from_user(child_pid_ptr)?; - let path = clone_string_from_user_safely(path)?; + let path = clone_cstring_from_user_safely(path)?; let argv = clone_cstrings_from_user_safely(argv)?; let envp = clone_cstrings_from_user_safely(envp)?; + let parent = process::get_current(); - let child_pid = process::do_spawn(&path, &argv, &envp)?; + let child_pid = process::do_spawn(&path, &argv, &envp, &parent)?; unsafe { *child_pid_ptr = child_pid }; Ok(()) diff --git a/src/libos/src/syscall/syscall_entry.c b/src/libos/src/syscall/syscall_entry.c index 5dc4b0b7..b172e2e4 100644 --- a/src/libos/src/syscall/syscall_entry.c +++ b/src/libos/src/syscall/syscall_entry.c @@ -80,6 +80,10 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long ret = occlum_getpid(); break; } + case SYS_getppid: { + ret = occlum_getppid(); + break; + } case SYS_mmap: { DECL_SYSCALL_ARG(void*, addr, arg0); DECL_SYSCALL_ARG(size_t, length, arg1); diff --git a/src/libos/src/vm/mod.rs b/src/libos/src/vm/mod.rs index 1dcce3a8..9d2e33e4 100644 --- a/src/libos/src/vm/mod.rs +++ b/src/libos/src/vm/mod.rs @@ -59,12 +59,12 @@ pub struct VMSpace { guard_type: VMGuardAreaType, } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct VMDomain { range: VMRange, } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct VMArea { range: VMRange, flags: VMAreaFlags, diff --git a/src/libos/src/vm/process_vm.rs b/src/libos/src/vm/process_vm.rs index 3ebd3dda..1de4a523 100644 --- a/src/libos/src/vm/process_vm.rs +++ b/src/libos/src/vm/process_vm.rs @@ -22,7 +22,7 @@ extern { pub fn vm_get_prealloced_data_space(addr: &mut usize, size: &mut usize); } -#[derive(Debug)] +#[derive(Debug, Default)] pub struct ProcessVM { //code_domain: VMDomain, data_domain: VMDomain, diff --git a/src/libos/src/vm/vm_range.rs b/src/libos/src/vm/vm_range.rs index b2cbdd42..e2ee815a 100644 --- a/src/libos/src/vm/vm_range.rs +++ b/src/libos/src/vm/vm_range.rs @@ -383,6 +383,16 @@ impl Drop for VMRange { unsafe impl Send for VMRange {} unsafe impl Sync for VMRange {} +impl Default for VMRange { + fn default() -> VMRange { + VMRange { + inner: VMRangeInner::new(0, 0, VMGrowthType::Fixed), + parent_range: 0 as *const VMRange, + sub_ranges: None, + } + } +} + #[derive(Clone, Copy)] pub struct VMRangeInner { diff --git a/test/Makefile b/test/Makefile index 31a45a08..9c33b5cc 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,7 +1,7 @@ CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) PROJECT_DIR := $(realpath $(CUR_DIR)/../) -TEST_SUITES := empty hello_world malloc +TEST_SUITES := empty hello_world malloc getpid BUILD_TEST_SUITES := $(TEST_SUITES:%=%) RUN_TEST_SUITES := $(TEST_SUITES:%=run-%) CLEAN_TEST_SUITES := $(TEST_SUITES:%=clean-%) diff --git a/test/getpid/Makefile b/test/getpid/Makefile new file mode 100644 index 00000000..b71a4d49 --- /dev/null +++ b/test/getpid/Makefile @@ -0,0 +1,4 @@ +include ../test_common.mk + +EXTRA_C_FLAGS := +EXTRA_LINK_FLAGS := diff --git a/test/getpid/main.c b/test/getpid/main.c new file mode 100644 index 00000000..668b6d97 --- /dev/null +++ b/test/getpid/main.c @@ -0,0 +1,9 @@ +#include +#include +#include + +int main(void) { + printf("pid = %d\n", getpid()); + printf("ppid = %d\n", getppid()); + return 0; +}