WIP: write skeleton for fork, new-thread
This commit is contained in:
@@ -12,6 +12,7 @@ crate-type = ["staticlib"]
|
||||
[dependencies]
|
||||
hashbrown = { version = "0.14", default-features = false, features = [
|
||||
"inline-more",
|
||||
"ahash",
|
||||
] }
|
||||
linked_list_allocator = "0.10"
|
||||
redox-initfs = { git = "https://gitlab.redox-os.org/redox-os/redox-initfs.git", default-features = false }
|
||||
@@ -20,6 +21,7 @@ redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" }
|
||||
#redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc", default-features = false }
|
||||
redox-rt = { git = "https://gitlab.redox-os.org/4lDO2/relibc.git", branch = "userspace_proc", default-features = false }
|
||||
redox-path = "0.3.1"
|
||||
slab = { version = "0.4.9", default-features = false }
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
|
||||
+4
-8
@@ -1,9 +1,5 @@
|
||||
use core::mem;
|
||||
use syscall::{
|
||||
data::Map,
|
||||
flag::MapFlags,
|
||||
number::SYS_FMAP,
|
||||
};
|
||||
use syscall::{data::Map, flag::MapFlags, number::SYS_FMAP};
|
||||
|
||||
pub const USERMODE_END: usize = 0x0000_8000_0000_0000;
|
||||
pub const STACK_START: usize = USERMODE_END - STACK_SIZE;
|
||||
@@ -13,9 +9,9 @@ static MAP: Map = Map {
|
||||
offset: 0,
|
||||
size: STACK_SIZE,
|
||||
flags: MapFlags::PROT_READ
|
||||
.union(MapFlags::PROT_WRITE)
|
||||
.union(MapFlags::MAP_PRIVATE)
|
||||
.union(MapFlags::MAP_FIXED_NOREPLACE),
|
||||
.union(MapFlags::PROT_WRITE)
|
||||
.union(MapFlags::MAP_PRIVATE)
|
||||
.union(MapFlags::MAP_FIXED_NOREPLACE),
|
||||
address: STACK_START, // highest possible user address
|
||||
};
|
||||
|
||||
|
||||
+7
-4
@@ -49,7 +49,9 @@ pub fn main() -> ! {
|
||||
);
|
||||
});
|
||||
|
||||
spawn("process manager", move |write_fd| crate::procmngr::run(write_fd));
|
||||
spawn("process manager", move |write_fd| {
|
||||
crate::procmngr::run(write_fd)
|
||||
});
|
||||
|
||||
const CWD: &[u8] = b"/scheme/initfs";
|
||||
const DEFAULT_SCHEME: &[u8] = b"initfs";
|
||||
@@ -73,12 +75,13 @@ pub fn main() -> ! {
|
||||
|
||||
let image_file = FdGuard::new(syscall::open(path, O_RDONLY).expect("failed to open init"));
|
||||
let open_via_dup = FdGuard::new(
|
||||
syscall::open("/scheme/thisproc/current", 0)
|
||||
.expect("failed to open open_via_dup"),
|
||||
syscall::open("/scheme/thisproc/current", 0).expect("failed to open open_via_dup"),
|
||||
);
|
||||
let memory = FdGuard::new(syscall::open("/scheme/memory", 0).expect("failed to open memory"));
|
||||
|
||||
redox_rt::proc::make_init();
|
||||
unsafe {
|
||||
redox_rt::proc::make_init();
|
||||
}
|
||||
|
||||
fexec_impl(
|
||||
image_file,
|
||||
|
||||
+5
-10
@@ -9,14 +9,9 @@ use hashbrown::HashMap;
|
||||
use redox_initfs::{types::Timespec, InitFs, Inode, InodeDir, InodeKind, InodeStruct};
|
||||
|
||||
use redox_path::canonicalize_to_standard;
|
||||
use redox_scheme::CallerCtx;
|
||||
use redox_scheme::OpenResult;
|
||||
use redox_scheme::RequestKind;
|
||||
use redox_scheme::SchemeMut;
|
||||
use redox_scheme::{CallerCtx, OpenResult, RequestKind, Scheme};
|
||||
|
||||
use redox_scheme::SignalBehavior;
|
||||
use redox_scheme::Socket;
|
||||
use redox_scheme::V2;
|
||||
use redox_scheme::{SignalBehavior, Socket};
|
||||
use syscall::data::Stat;
|
||||
use syscall::dirent::DirEntry;
|
||||
use syscall::dirent::DirentBuf;
|
||||
@@ -93,7 +88,7 @@ fn inode_len(inode: InodeStruct<'static>) -> Result<usize> {
|
||||
})
|
||||
}
|
||||
|
||||
impl SchemeMut for InitFsScheme {
|
||||
impl Scheme for InitFsScheme {
|
||||
fn xopen(&mut self, path: &str, flags: usize, _ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
let mut components = path
|
||||
// trim leading and trailing slash
|
||||
@@ -317,7 +312,7 @@ impl SchemeMut for InitFsScheme {
|
||||
pub fn run(bytes: &'static [u8], sync_pipe: usize) -> ! {
|
||||
let mut scheme = InitFsScheme::new(bytes);
|
||||
|
||||
let socket = Socket::<V2>::create("initfs").expect("failed to open initfs scheme socket");
|
||||
let socket = Socket::create("initfs").expect("failed to open initfs scheme socket");
|
||||
|
||||
let _ = syscall::write(sync_pipe, &[0]);
|
||||
let _ = syscall::close(sync_pipe);
|
||||
@@ -332,7 +327,7 @@ pub fn run(bytes: &'static [u8], sync_pipe: usize) -> ! {
|
||||
}) else {
|
||||
continue;
|
||||
};
|
||||
let resp = req.handle_scheme_mut(&mut scheme);
|
||||
let resp = req.handle_scheme(&mut scheme);
|
||||
|
||||
if !socket
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
|
||||
+149
-14
@@ -1,14 +1,21 @@
|
||||
use core::cell::RefCell;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec::Vec;
|
||||
use alloc::vec;
|
||||
|
||||
use hashbrown::hash_map::DefaultHashBuilder;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use redox_rt::proc::FdGuard;
|
||||
use redox_scheme::{CallerCtx, OpenResult, RequestKind, SchemeMut, SignalBehavior, Socket, V2};
|
||||
use syscall::{Result, O_CREAT};
|
||||
use redox_scheme::{
|
||||
CallerCtx, OpenResult, RequestKind, Response, Scheme, SendFdRequest, SignalBehavior, Socket,
|
||||
};
|
||||
use slab::Slab;
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::{Error, FobtainFdFlags, Result, EBADF, EBADFD, EEXIST, EINVAL, ENOENT, O_CREAT};
|
||||
|
||||
pub fn run(write_fd: usize) {
|
||||
let socket = Socket::<V2>::create("proc").expect("failed to open proc scheme socket");
|
||||
let socket = Socket::create("proc").expect("failed to open proc scheme socket");
|
||||
let mut scheme = ProcScheme::new();
|
||||
|
||||
let _ = syscall::write(1, b"process manager started\n").unwrap();
|
||||
@@ -16,16 +23,17 @@ pub fn run(write_fd: usize) {
|
||||
let _ = syscall::close(write_fd);
|
||||
|
||||
loop {
|
||||
let RequestKind::Call(req) = (match socket
|
||||
let Some(req) = socket
|
||||
.next_request(SignalBehavior::Restart)
|
||||
.expect("bootstrap: failed to read scheme request from kernel")
|
||||
{
|
||||
Some(req) => req.kind(),
|
||||
None => break,
|
||||
}) else {
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
let resp = req.handle_scheme_mut(&mut scheme);
|
||||
let resp = match req.kind() {
|
||||
RequestKind::Call(req) => req.handle_scheme(&mut scheme),
|
||||
RequestKind::SendFd(req) => scheme.on_sendfd(&socket, &req),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !socket
|
||||
.write_response(resp, SignalBehavior::Restart)
|
||||
@@ -43,6 +51,13 @@ struct Process {
|
||||
ppid: ProcessId,
|
||||
pgid: ProcessId,
|
||||
sid: ProcessId,
|
||||
|
||||
ruid: u32,
|
||||
euid: u32,
|
||||
rgid: u32,
|
||||
egid: u32,
|
||||
rns: u32,
|
||||
ens: u32,
|
||||
}
|
||||
struct Thread {
|
||||
fd: FdGuard,
|
||||
@@ -51,22 +66,142 @@ struct Thread {
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
struct ProcessId(usize);
|
||||
|
||||
const INIT_PID: ProcessId = ProcessId(1);
|
||||
|
||||
struct ProcScheme {
|
||||
processes: HashMap<ProcessId, Process, DefaultHashBuilder>,
|
||||
process_groups: HashSet<ProcessId, DefaultHashBuilder>,
|
||||
sessions: HashSet<ProcessId, DefaultHashBuilder>,
|
||||
handles: Slab<Handle>,
|
||||
|
||||
init_claimed: bool,
|
||||
next_id: ProcessId,
|
||||
}
|
||||
|
||||
enum Handle {
|
||||
Init,
|
||||
Proc(ProcessId),
|
||||
}
|
||||
|
||||
impl ProcScheme {
|
||||
pub fn new() -> ProcScheme {
|
||||
ProcScheme {
|
||||
processes: HashMap::new(),
|
||||
process_groups: HashSet::new(),
|
||||
sessions: HashSet::new(),
|
||||
handles: Slab::new(),
|
||||
init_claimed: false,
|
||||
next_id: ProcessId(2),
|
||||
}
|
||||
}
|
||||
fn new_id(&mut self) -> ProcessId {
|
||||
let id = self.next_id;
|
||||
self.next_id.0 += 1;
|
||||
id
|
||||
}
|
||||
fn on_sendfd(&mut self, socket: &Socket, req: &SendFdRequest) -> Response {
|
||||
match self.handles[req.id()] {
|
||||
ref mut st @ Handle::Init => {
|
||||
let mut fd_out = usize::MAX;
|
||||
if let Err(e) = req.obtain_fd(socket, FobtainFdFlags::empty(), Err(&mut fd_out)) {
|
||||
return Response::for_sendfd(&req, Err(e));
|
||||
};
|
||||
let thread = Rc::new(RefCell::new(Thread {
|
||||
fd: FdGuard::new(fd_out),
|
||||
}));
|
||||
self.processes.insert(
|
||||
INIT_PID,
|
||||
Process {
|
||||
threads: vec![thread],
|
||||
ppid: INIT_PID,
|
||||
sid: INIT_PID,
|
||||
pgid: INIT_PID,
|
||||
ruid: 0,
|
||||
euid: 0,
|
||||
rgid: 0,
|
||||
egid: 0,
|
||||
rns: 1,
|
||||
ens: 1,
|
||||
},
|
||||
);
|
||||
self.process_groups.insert(INIT_PID);
|
||||
self.sessions.insert(INIT_PID);
|
||||
|
||||
*st = Handle::Proc(INIT_PID);
|
||||
Response::for_sendfd(&req, Ok(0))
|
||||
}
|
||||
_ => Response::for_sendfd(&req, Err(Error::new(EBADF))),
|
||||
}
|
||||
}
|
||||
fn fork(&mut self, parent_pid: ProcessId) -> Result<ProcessId> {
|
||||
let child_pid = self.new_id();
|
||||
|
||||
let Process {
|
||||
pgid,
|
||||
sid,
|
||||
euid,
|
||||
ruid,
|
||||
egid,
|
||||
rgid,
|
||||
ens,
|
||||
rns,
|
||||
..
|
||||
} = *self.processes.get(&parent_pid).ok_or(Error::new(EBADFD))?;
|
||||
|
||||
self.processes.insert(
|
||||
child_pid,
|
||||
Process {
|
||||
threads: Vec::new(),
|
||||
ppid: parent_pid,
|
||||
pgid,
|
||||
sid,
|
||||
ruid,
|
||||
rgid,
|
||||
euid,
|
||||
egid,
|
||||
rns,
|
||||
ens,
|
||||
},
|
||||
);
|
||||
Ok(child_pid)
|
||||
}
|
||||
fn new_thread(&mut self, pid: ProcessId) -> Result<FdGuard> {
|
||||
let proc = self.processes.get_mut(&pid).ok_or(Error::new(EBADFD))?;
|
||||
proc.threads
|
||||
.push(Rc::new(RefCell::new(Thread { fd: todo!() })));
|
||||
}
|
||||
}
|
||||
impl Scheme for ProcScheme {
|
||||
fn xopen(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
if path == "init" {
|
||||
if core::mem::replace(&mut self.init_claimed, true) {
|
||||
return Err(Error::new(EEXIST));
|
||||
}
|
||||
return Ok(OpenResult::ThisScheme {
|
||||
number: self
|
||||
.handles
|
||||
.insert(Handle::Init),
|
||||
flags: NewFdFlags::empty(),
|
||||
});
|
||||
}
|
||||
Err(Error::new(ENOENT))
|
||||
}
|
||||
fn xdup(&mut self, old_id: usize, buf: &[u8], ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
match self.handles[old_id] {
|
||||
Handle::Proc(pid) => match buf {
|
||||
b"fork" => {
|
||||
let child_pid = self.fork(pid)?;
|
||||
Ok(OpenResult::ThisScheme {
|
||||
number: self.handles.insert(Handle::Proc(child_pid)),
|
||||
flags: NewFdFlags::empty(),
|
||||
})
|
||||
},
|
||||
b"new-thread" => Ok(OpenResult::OtherScheme {
|
||||
fd: self.new_thread(pid)?.take(),
|
||||
}),
|
||||
_ => return Err(Error::new(EINVAL)),
|
||||
},
|
||||
Handle::Init => Err(Error::new(EBADF)),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl SchemeMut for ProcScheme {
|
||||
fn xopen(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<OpenResult> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user