Move the ziron libos entry point to zCore directory

This commit is contained in:
Yuekai Jia 2021-10-25 20:10:32 +08:00
parent 806c9d104b
commit 169088dc31
19 changed files with 221 additions and 198 deletions

View File

@ -47,7 +47,6 @@ jobs:
with:
crate: cargo-binutils
version: latest
use-tool-cache: true
- name: Build linux LibOS
run: cargo build --features "linux libos"
- name: Build zircon LibOS
@ -257,7 +256,6 @@ jobs:
with:
crate: cargo-binutils
version: latest
use-tool-cache: true
- name: Install cargo tools and qemu-system-riscv64
run: |
sudo apt update

View File

@ -44,9 +44,17 @@ pub struct U128(pub [u64; 2]);
impl fmt::Debug for U128 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:#016x}{:016x}", self.0[1], self.0[0])
write!(f, "{:#016x}_{:016x}", self.0[1], self.0[0])
}
}
#[cfg(feature = "libos")]
pub use trapframe::syscall_fn_entry as syscall_entry;
cfg_if! {
if #[cfg(feature = "libos")] {
pub use trapframe::syscall_fn_entry as syscall_entry;
} else {
pub use dummpy_syscall_entry as syscall_entry;
pub fn dummpy_syscall_entry() {
unreachable!("dummpy_syscall_entry")
}
}
}

View File

@ -2,15 +2,6 @@ use crate::{KernelConfig, KernelHandler, KCONFIG, KHANDLER};
hal_fn_impl! {
impl mod crate::hal_fn::boot {
fn cmdline() -> String {
let root_proc = std::env::args().skip(1).collect::<Vec<_>>().join("?");
let mut cmdline = format!("ROOTPROC={}", root_proc);
if let Ok(level) = std::env::var("LOG") {
cmdline += &format!(":LOG={}", level);
}
cmdline
}
fn primary_init_early(cfg: KernelConfig, handler: &'static impl KernelHandler) {
KCONFIG.init_once_by(cfg);
KHANDLER.init_once_by(handler);

View File

@ -5,10 +5,12 @@ use std::path::Path;
async fn main() {
env_logger::init();
kernel_hal::init();
let args = env::args().skip(1).collect();
let envs = vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin".into()];
let rootfs_path = Path::new(&env::var("CARGO_MANIFEST_DIR").unwrap()).join("../rootfs");
let hostfs = rcore_fs_hostfs::HostFS::new(rootfs_path);
let proc = linux_loader::run(args, envs, hostfs);
let code = proc.wait_for_exit().await;
std::process::exit(code as i32);

View File

@ -35,10 +35,7 @@ pub fn run(args: Vec<String>, envs: Vec<String>, rootfs: Arc<dyn FileSystem>) ->
let proc = Process::create_linux(&job, rootfs.clone()).unwrap();
let thread = Thread::create_linux(&proc).unwrap();
let loader = LinuxElfLoader {
#[cfg(feature = "libos")]
syscall_entry: kernel_hal::context::syscall_entry as usize,
#[cfg(not(feature = "libos"))]
syscall_entry: 0,
stack_pages: 8,
root_inode: rootfs.root_inode(),
};
@ -181,10 +178,7 @@ async fn handle_syscall(thread: &CurrentThread, regs: &mut GeneralRegs) {
let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9];
let mut syscall = Syscall {
thread,
#[cfg(feature = "libos")]
syscall_entry: kernel_hal::context::syscall_entry as usize,
#[cfg(not(feature = "libos"))]
syscall_entry: 0,
thread_fn,
regs,
};
@ -211,10 +205,7 @@ async fn handle_syscall(thread: &CurrentThread, cx: &mut UserContext) {
let mut syscall = Syscall {
thread,
#[cfg(feature = "libos")]
syscall_entry: kernel_hal::context::syscall_entry as usize,
#[cfg(not(feature = "libos"))]
syscall_entry: 0,
context: cx,
thread_fn,
};

View File

@ -25,7 +25,7 @@ def print_cases(cases, file=None):
print(case, file=file)
subprocess.run("cd .. && cargo build -p zcore --release --features 'libos linux'",
subprocess.run("cd .. && cargo build -p zcore --release --features 'linux libos'",
shell=True, check=True)
for path in sorted(glob.glob("../rootfs/libc-test/src/*/*.exe")):

View File

@ -5,15 +5,15 @@ import argparse
TIMEOUT = 300
ZIRCON_LOADER_PATH = 'zircon-loader'
PREBUILT_PATH = '../prebuilt/zircon/x64'
ZBI_PATH = '../prebuilt/zircon/x64/core-tests.zbi'
CMDLINE_BASE = 'LOG=warn:userboot=test/core-standalone-test:userboot.shutdown:core-tests='
parser = argparse.ArgumentParser()
parser.add_argument('testcase', nargs=1)
args = parser.parse_args()
child = pexpect.spawn("cargo run -p '%s' -- '%s' '%s' --debug " %
(ZIRCON_LOADER_PATH, PREBUILT_PATH, CMDLINE_BASE+args.testcase[0]),
child = pexpect.spawn("cargo run -p zcore --features 'zircon libos' -- '%s' '%s'" %
(ZBI_PATH, CMDLINE_BASE+args.testcase[0]),
timeout=TIMEOUT, encoding='utf-8')
child.logfile = sys.stdout

View File

@ -11,7 +11,7 @@ RESULT_FILE = BASE + 'test-result-libos.txt'
CHECK_FILE = BASE + 'test-check-passed.txt'
TEST_CASE_ALL = BASE + 'testcases-all.txt'
TEST_CASE_EXCEPTION = BASE + 'testcases-failed-libos.txt'
PREBUILT_PATH = '../prebuilt/zircon/x64'
ZBI_PATH = '../prebuilt/zircon/x64/core-tests.zbi'
CMDLINE_BASE = 'LOG=warn:userboot=test/core-standalone-test:userboot.shutdown:core-tests='
class Tee:
@ -41,8 +41,8 @@ with open(TEST_CASE_EXCEPTION, "r") as tcf:
check_case = all_case - exception_case
for line in check_case:
child = pexpect.spawn("cargo run -p '%s' -- '%s' '%s' --debug" %
(ZIRCON_LOADER_PATH, PREBUILT_PATH, CMDLINE_BASE+line),
child = pexpect.spawn("cargo run -p zcore --features 'zircon libos' -- '%s' '%s'" %
(ZBI_PATH, CMDLINE_BASE+line),
timeout=TIMEOUT, encoding='utf-8')
child.logfile = Tee(OUTPUT_FILE, 'a')

View File

@ -24,7 +24,7 @@ link_user_img = ["init_ram_disk"]
zircon = ["zircon-loader"]
linux = ["linux-loader", "linux-object", "rcore-fs", "rcore-fs-sfs"]
libos = ["async-std", "chrono", "rcore-fs-hostfs", "linux-loader/libos"]
libos = ["async-std", "chrono", "rcore-fs-hostfs", "linux-loader/libos", "zircon-loader/libos"]
board_qemu = []
board_d1 = ["link_user_img"]

View File

@ -8,21 +8,44 @@ LINUX ?=
LIBOS ?=
GRAPHIC ?=
HYPERVISOR ?=
SMP ?= 1
ACCEL ?=
V ?=
USER ?=
ZBI ?= bringup
CMDLINE ?=
ARGS ?= /bin/busybox
SMP ?= 1
ACCEL ?=
OBJDUMP ?= rust-objdump --print-imm-hex --x86-asm-syntax=intel
OBJCOPY ?= rust-objcopy --binary-architecture=$(ARCH)
ifeq ($(LINUX), 1)
user_img := $(ARCH).img
else ifeq ($(USER), 1)
user_img := ../zircon-user/target/zcore-user.zbi
else
user_img := ../prebuilt/zircon/x64/$(ZBI).zbi
endif
ifeq ($(PLATFORM), libos)
LIBOS := 1
endif
ifeq ($(LIBOS), 1)
build_path := ../target/$(MODE)
PLATFORM := libos
ifeq ($(LINUX), 1)
ARGS ?= /bin/busybox
else
ARGS ?= $(user_img) $(CMDLINE)
endif
else
build_path := ../target/$(ARCH)/$(MODE)
endif
################ Internal variables ################
qemu := qemu-system-$(ARCH)
build_path := ../target/$(ARCH)/$(MODE)
kernel_elf := $(build_path)/zcore
kernel_img := $(build_path)/zcore.bin
esp := $(build_path)/esp
@ -35,13 +58,6 @@ else
sed := sed -i
endif
ifeq ($(LINUX), 1)
user_img := $(ARCH).img
else ifeq ($(USER), 1)
user_img := ../zircon-user/target/zcore-user.zbi
else
user_img := ../prebuilt/zircon/x64/$(ZBI).zbi
endif
################ Export environments ###################
@ -57,10 +73,6 @@ else
features := zircon
endif
ifeq ($(PLATFORM), libos)
LIBOS := 1
endif
ifeq ($(LIBOS), 1)
ifneq ($(ARCH), $(shell uname -m))
$(error "ARCH" must be "$(shell uname -m)" for libos mode)
@ -170,7 +182,7 @@ run:
test:
cargo test $(build_args)
debug: build
gdb --args ../target/$(MODE)/zcore $(ARGS)
gdb --args $(kernel_elf) $(ARGS)
else
build: $(kernel_img)
run: build justrun

View File

@ -1,5 +1,5 @@
#[allow(dead_code)]
pub fn init_ram_disk() -> &'static mut [u8] {
fn init_ram_disk() -> &'static mut [u8] {
if cfg!(feature = "link_user_img") {
extern "C" {
fn _user_img_start();
@ -33,8 +33,8 @@ cfg_if! {
#[cfg(not(feature = "libos"))]
pub fn rootfs() -> Arc<dyn FileSystem> {
use linux_object::fs::rcore_fs_wrapper::{Block, BlockCache, MemBuf};
use rcore_fs::dev::Device;
use linux_object::fs::rcore_fs_wrapper::{MemBuf, Block, BlockCache};
let device: Arc<dyn Device> = if cfg!(feature = "init_ram_disk") {
Arc::new(MemBuf::new(init_ram_disk()))
@ -45,6 +45,22 @@ cfg_if! {
info!("Opening the rootfs...");
rcore_fs_sfs::SimpleFileSystem::open(device).expect("failed to open device SimpleFS")
}
} else if #[cfg(feature = "zircon")] {
#[cfg(feature = "libos")]
pub fn zbi() -> impl AsRef<[u8]> {
let args = std::env::args().collect::<Vec<_>>();
if args.len() < 2 {
println!("Usage: {} ZBI_FILE [CMDLINE]", args[0]);
std::process::exit(-1);
}
std::fs::read(&args[1]).expect("failed to read zbi file")
}
#[cfg(not(feature = "libos"))]
pub fn zbi() -> impl AsRef<[u8]> {
init_ram_disk()
}
}
}

View File

@ -27,30 +27,23 @@ fn primary_main(config: kernel_hal::KernelConfig) {
memory::init_heap();
kernel_hal::primary_init_early(config, &handler::ZcoreKernelHandler);
let cmdline = kernel_hal::boot::cmdline();
let boot_options = utils::parse_cmdline(&cmdline);
logging::set_max_level(boot_options.get("LOG").unwrap_or(&""));
info!("Boot options: {:#?}", boot_options);
let options = utils::boot_options();
logging::set_max_level(&options.log_level);
info!("Boot options: {:#?}", options);
memory::init_frame_allocator(&kernel_hal::mem::free_pmem_regions());
kernel_hal::primary_init();
cfg_if! {
if #[cfg(feature = "linux")] {
let args = boot_options
.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")
.split('?').map(Into::into).collect(); // parse "arg0?arg1?arg2"
let args = options.root_proc.split('?').map(Into::into).collect(); // parse "arg0?arg1?arg2"
let envs = alloc::vec!["PATH=/usr/sbin:/usr/bin:/sbin:/bin".into()];
let rootfs = fs::rootfs();
let proc = linux_loader::run(args, envs, rootfs);
utils::wait_for_exit(Some(proc))
} else if #[cfg(feature = "zircon")] {
let images = zircon_loader::Images::<&[u8]> {
userboot: include_bytes!("../../prebuilt/zircon/x64/userboot.so"),
vdso: include_bytes!("../../prebuilt/zircon/x64/libzircon.so"),
zbi: fs::init_ram_disk(),
};
let proc = zircon_loader::run_userboot(&images, &cmdline);
let zbi = fs::zbi();
let proc = zircon_loader::run_userboot(zbi, &options.cmdline);
utils::wait_for_exit(Some(proc))
} else {
panic!("One of the features `linux` or `zircon` must be specified!");

View File

@ -1,27 +1,80 @@
use alloc::{collections::BTreeMap, sync::Arc};
#![allow(dead_code)]
#![allow(unused_variables)]
use alloc::{collections::BTreeMap, string::String, sync::Arc};
use zircon_object::task::Process;
pub type BootOptions<'a> = BTreeMap<&'a str, &'a str>;
#[derive(Debug)]
pub struct BootOptions {
pub cmdline: String,
pub log_level: String,
#[cfg(feature = "linux")]
pub root_proc: String,
}
pub fn parse_cmdline(cmdline: &str) -> BootOptions {
let mut args = BootOptions::new();
fn parse_cmdline(cmdline: &str) -> BTreeMap<&str, &str> {
let mut options = BTreeMap::new();
for opt in cmdline.split(':') {
// parse "key=value"
let mut iter = opt.trim().splitn(2, '=');
if let Some(key) = iter.next() {
if let Some(value) = iter.next() {
args.insert(key.trim(), value.trim());
options.insert(key.trim(), value.trim());
}
}
}
options
}
pub fn boot_options() -> BootOptions {
cfg_if! {
if #[cfg(feature = "libos")] {
let log_level = std::env::var("LOG").unwrap_or_default();
let cmdline = if cfg!(feature = "zircon") {
std::env::args().nth(2).unwrap_or_default()
} else {
String::new()
};
BootOptions {
cmdline,
log_level,
#[cfg(feature = "linux")]
root_proc: std::env::args().skip(1).collect::<Vec<_>>().join("?"),
}
} else {
let cmdline = kernel_hal::boot::cmdline();
let options = parse_cmdline(&cmdline);
BootOptions {
cmdline: cmdline.clone(),
log_level: String::from(*options.get("LOG").unwrap_or(&"")),
#[cfg(feature = "linux")]
root_proc: String::from(*options.get("ROOTPROC").unwrap_or(&"/bin/busybox?sh")),
}
}
}
args
}
#[allow(unused_variables)]
pub fn wait_for_exit(proc: Option<Arc<Process>>) -> ! {
#[cfg(feature = "libos")]
if let Some(proc) = proc {
let future = async move { proc.wait_for_exit().await };
let future = async move {
use zircon_object::object::{KernelObject, Signal};
let object: Arc<dyn KernelObject> = proc.clone();
let signal = if cfg!(feature = "zircon") {
Signal::USER_SIGNAL_0
} else {
Signal::PROCESS_TERMINATED
};
object.wait_signal(signal).await;
let code = proc.exit_code().unwrap_or(-1);
info!(
"process {:?}({}) exited with code {:?}",
proc.name(),
proc.id(),
code
);
code
};
// If the graphic mode is on, run the process in another thread.
#[cfg(feature = "graphic")]

View File

@ -9,15 +9,16 @@ description = "Zircon user program (userboot) loader"
[dependencies]
log = "0.4"
cfg-if = "1.0"
xmas-elf = "0.7"
zircon-object = { path = "../zircon-object", features = ["elf"] }
zircon-syscall = { path = "../zircon-syscall" }
kernel-hal = { path = "../kernel-hal" }
env_logger = { version = "0.8", optional = true }
structopt = { version = "0.3", default-features = false, optional = true }
async-std = { version = "1.10", features = ["attributes"], optional = true }
[features]
default = ["std", "libos"]
libos = ["kernel-hal/libos"]
std = ["env_logger", "structopt", "async-std", "zircon-object/aspace-separate", "zircon-syscall/std"]
default = ["libos"]
libos = ["kernel-hal/libos", "zircon-object/aspace-separate", "zircon-syscall/std"]
[dev-dependencies]
env_logger = "0.9"
async-std = { version = "1.10", features = ["attributes"] }

View File

@ -0,0 +1,20 @@
use std::sync::Arc;
use zircon_object::object::{KernelObject, Signal};
#[async_std::main]
async fn main() {
env_logger::init();
kernel_hal::init();
let args = std::env::args().collect::<Vec<_>>();
if args.len() < 2 {
println!("Usage: {} ZBI_FILE [CMDLINE]", args[0]);
std::process::exit(-1);
}
let zbi = std::fs::read(&args[1]).expect("failed to read zbi file");
let cmdline = args.get(2).map(String::as_str).unwrap_or("");
let proc: Arc<dyn KernelObject> = zircon_loader::run_userboot(zbi, cmdline);
proc.wait_signal(Signal::USER_SIGNAL_0).await;
}

View File

@ -32,14 +32,34 @@ const K_COUNTERS: usize = 10;
const K_FISTINSTRUMENTATIONDATA: usize = 11;
const K_HANDLECOUNT: usize = 15;
/// Program images to run.
pub struct Images<T: AsRef<[u8]>> {
pub userboot: T,
pub vdso: T,
pub zbi: T,
macro_rules! boot_firmware {
($name: expr) => {{
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
boot_firmware!($name, "../../prebuilt/zircon/x64")
} else if #[cfg(target_arch = "aarch64")] {
boot_firmware!($name, "../../prebuilt/zircon/arm64")
} else {
compile_error!("Unsupported architecture for zircon mode!")
}
}
}};
($name: expr, $base_dir: expr) => {{
#[cfg(feature = "libos")]
{
include_bytes!(concat!($base_dir, "/", $name, "-libos.so"))
}
#[cfg(not(feature = "libos"))]
{
include_bytes!(concat!($base_dir, "/", $name, ".so"))
}
}};
}
pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Process> {
pub fn run_userboot(zbi: impl AsRef<[u8]>, cmdline: &str) -> Arc<Process> {
let userboot = boot_firmware!("userboot");
let vdso = boot_firmware!("libzircon");
let job = Job::root();
let proc = Process::create(&job, "userboot").unwrap();
let thread = Thread::create(&proc, "userboot").unwrap();
@ -54,7 +74,7 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
// userboot
let (entry, userboot_size) = {
let elf = ElfFile::new(images.userboot.as_ref()).unwrap();
let elf = ElfFile::new(userboot).unwrap();
let size = elf.load_segment_size();
let vmar = vmar
.allocate(None, size, VmarFlags::CAN_MAP_RXW, PAGE_SIZE)
@ -65,9 +85,9 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
// vdso
let vdso_vmo = {
let elf = ElfFile::new(images.vdso.as_ref()).unwrap();
let vdso_vmo = VmObject::new_paged(images.vdso.as_ref().len() / PAGE_SIZE + 1);
vdso_vmo.write(0, images.vdso.as_ref()).unwrap();
let elf = ElfFile::new(vdso).unwrap();
let vdso_vmo = VmObject::new_paged(vdso.len() / PAGE_SIZE + 1);
vdso_vmo.write(0, vdso).unwrap();
let size = elf.load_segment_size();
let vmar = vmar
.allocate_at(
@ -78,7 +98,7 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
)
.unwrap();
vmar.map_from_elf(&elf, vdso_vmo.clone()).unwrap();
#[cfg(feature = "std")]
#[cfg(feature = "libos")]
{
let offset = elf
.get_symbol_address("zcore_syscall_entry")
@ -94,8 +114,8 @@ pub fn run_userboot(images: &Images<impl AsRef<[u8]>>, cmdline: &str) -> Arc<Pro
// zbi
let zbi_vmo = {
let vmo = VmObject::new_paged(images.zbi.as_ref().len() / PAGE_SIZE + 1);
vmo.write(0, images.zbi.as_ref()).unwrap();
let vmo = VmObject::new_paged(zbi.as_ref().len() / PAGE_SIZE + 1);
vmo.write(0, zbi.as_ref()).unwrap();
vmo.set_name("zbi");
vmo
};
@ -267,7 +287,7 @@ async fn handle_syscall(thread: &CurrentThread) {
#[cfg(target_arch = "aarch64")]
let num = regs.x16 as u32;
// LibOS: Function call ABI
#[cfg(feature = "std")]
#[cfg(feature = "libos")]
#[cfg(target_arch = "x86_64")]
let args = unsafe {
let a6 = (regs.rsp as *const usize).read();
@ -277,7 +297,7 @@ async fn handle_syscall(thread: &CurrentThread) {
]
};
// RealOS: Zircon syscall ABI
#[cfg(not(feature = "std"))]
#[cfg(not(feature = "libos"))]
#[cfg(target_arch = "x86_64")]
let args = [
regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9, regs.r12, regs.r13,

View File

@ -1,96 +0,0 @@
#![deny(warnings, unused_must_use)]
extern crate log;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use structopt::StructOpt;
use zircon_loader::*;
use zircon_object::object::*;
#[derive(Debug, StructOpt)]
#[structopt()]
struct Opt {
#[structopt(parse(from_os_str))]
prebuilt_path: PathBuf,
#[structopt(default_value = "")]
cmdline: String,
#[structopt(short, long)]
debug: bool,
}
#[async_std::main]
async fn main() {
kernel_hal::init();
init_logger();
let opt = Opt::from_args();
let images = open_images(&opt.prebuilt_path, opt.debug).expect("failed to read file");
let proc: Arc<dyn KernelObject> = run_userboot(&images, &opt.cmdline);
drop(images);
proc.wait_signal(Signal::USER_SIGNAL_0).await;
}
fn open_images(path: &Path, debug: bool) -> std::io::Result<Images<Vec<u8>>> {
Ok(Images {
userboot: std::fs::read(path.join("userboot-libos.so"))?,
vdso: std::fs::read(path.join("libzircon-libos.so"))?,
zbi: if debug {
std::fs::read(path.join("core-tests.zbi"))?
} else {
std::fs::read(path.join("bringup.zbi"))?
},
})
}
fn init_logger() {
env_logger::builder()
.format(|buf, record| {
use env_logger::fmt::Color;
use log::Level;
use std::io::Write;
let (tid, pid) = kernel_hal::thread::get_tid();
let mut style = buf.style();
match record.level() {
Level::Trace => style.set_color(Color::Black).set_intense(true),
Level::Debug => style.set_color(Color::White),
Level::Info => style.set_color(Color::Green),
Level::Warn => style.set_color(Color::Yellow),
Level::Error => style.set_color(Color::Red).set_bold(true),
};
let now = kernel_hal::timer::timer_now();
let level = style.value(record.level());
let args = record.args();
writeln!(buf, "[{:?} {:>5} {}:{}] {}", now, level, pid, tid, args)
})
.init();
}
#[cfg(test)]
mod tests {
use super::*;
#[async_std::test]
async fn userboot() {
kernel_hal::init();
let opt = Opt {
#[cfg(target_arch = "x86_64")]
prebuilt_path: PathBuf::from("../prebuilt/zircon/x64"),
#[cfg(target_arch = "aarch64")]
prebuilt_path: PathBuf::from("../prebuilt/zircon/arm64"),
cmdline: String::from(""),
debug: false,
};
let images = open_images(&opt.prebuilt_path, opt.debug).expect("failed to read file");
let proc: Arc<dyn KernelObject> = run_userboot(&images, &opt.cmdline);
drop(images);
proc.wait_signal(Signal::PROCESS_TERMINATED).await;
}
}

View File

@ -0,0 +1,8 @@
#[cfg(target_arch = "x86_64")]
#[async_std::test]
async fn userboot() {
kernel_hal::init();
let zbi = std::fs::read("../prebuilt/zircon/x64/bringup.zbi").expect("failed to read zbi file");
let proc = zircon_loader::run_userboot(zbi, "");
proc.wait_for_exit().await;
}

View File

@ -294,6 +294,15 @@ impl Process {
self.inner.lock().status
}
/// Get process exit code if it exited, else returns `None`.
pub fn exit_code(&self) -> Option<i64> {
if let Status::Exited(code) = self.status() {
Some(code)
} else {
None
}
}
/// Get the extension.
pub fn ext(&self) -> &Box<dyn Any + Send + Sync> {
&self.ext
@ -529,7 +538,7 @@ impl Process {
pub async fn wait_for_exit(self: &Arc<Self>) -> i64 {
let object: Arc<dyn KernelObject> = self.clone();
object.wait_signal(Signal::PROCESS_TERMINATED).await;
if let Status::Exited(code) = self.status() {
let code = self.exit_code().expect("process not exited!");
info!(
"process {:?}({}) exited with code {:?}",
self.name(),
@ -537,9 +546,6 @@ impl Process {
code
);
code
} else {
unreachable!();
}
}
}