starry/
entry.rs

1use alloc::{string::String, sync::Arc};
2use axfs::{CURRENT_DIR, CURRENT_DIR_PATH, api::set_current_dir};
3use axhal::arch::UspaceContext;
4use axprocess::{Pid, init_proc};
5use axsignal::Signo;
6use axsync::Mutex;
7use starry_api::file::FD_TABLE;
8use starry_core::{
9    mm::{copy_from_kernel, load_user_app, map_trampoline, new_user_aspace_empty},
10    task::{ProcessData, TaskExt, ThreadData, add_thread_to_table, new_user_task},
11};
12
13pub fn run_user_app(args: &[String], envs: &[String]) -> Option<i32> {
14    let mut uspace = new_user_aspace_empty()
15        .and_then(|mut it| {
16            copy_from_kernel(&mut it)?;
17            map_trampoline(&mut it)?;
18            Ok(it)
19        })
20        .expect("Failed to create user address space");
21
22    let exe_path = args[0].clone();
23    let (dir, name) = exe_path.rsplit_once('/').unwrap_or(("", &exe_path));
24    set_current_dir(dir).expect("Failed to set current dir");
25
26    let (entry_vaddr, ustack_top) = load_user_app(&mut uspace, args, envs)
27        .unwrap_or_else(|e| panic!("Failed to load user app: {}", e));
28
29    let uctx = UspaceContext::new(entry_vaddr.into(), ustack_top, 2333);
30
31    let mut task = new_user_task(name, uctx, None);
32    task.ctx_mut().set_page_table_root(uspace.page_table_root());
33
34    let process_data = ProcessData::new(
35        exe_path,
36        Arc::new(Mutex::new(uspace)),
37        Arc::default(),
38        Some(Signo::SIGCHLD),
39    );
40
41    FD_TABLE
42        .deref_from(&process_data.ns)
43        .init_new(FD_TABLE.copy_inner());
44    CURRENT_DIR
45        .deref_from(&process_data.ns)
46        .init_new(CURRENT_DIR.copy_inner());
47    CURRENT_DIR_PATH
48        .deref_from(&process_data.ns)
49        .init_new(CURRENT_DIR_PATH.copy_inner());
50
51    let tid = task.id().as_u64() as Pid;
52    let process = init_proc().fork(tid).data(process_data).build();
53
54    let thread = process
55        .new_thread(tid)
56        .data(ThreadData::new(process.data().unwrap()))
57        .build();
58    add_thread_to_table(&thread);
59
60    task.init_task_ext(TaskExt::new(thread));
61
62    let task = axtask::spawn_task(task);
63
64    // TODO: we need a way to wait on the process but not only the main task
65    task.join()
66}