refactor: better Pid type
This commit is contained in:
parent
4ffbb8c115
commit
e965c25181
@ -127,7 +127,7 @@ extern "C" fn __aa64_exc_sync_handler(exc: &mut ExceptionFrame) {
|
||||
|
||||
if num == SystemCall::Fork {
|
||||
match unsafe { syscall::sys_fork(exc) } {
|
||||
Ok(pid) => exc.x[0] = pid.value() as usize,
|
||||
Ok(pid) => exc.x[0] = u32::from(pid) as usize,
|
||||
Err(err) => {
|
||||
exc.x[0] = err.to_negative_isize() as usize;
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ pub trait TtyDevice<const N: usize>: SerialDevice {
|
||||
},
|
||||
IoctlCmd::TtySetPgrp => {
|
||||
let src = arg::struct_ref::<u32>(ptr)?;
|
||||
self.ring().inner.lock().fg_pgid = Some(unsafe { Pid::from_raw(*src) });
|
||||
self.ring().inner.lock().fg_pgid = Some(Pid::try_from(*src)?);
|
||||
Ok(0)
|
||||
},
|
||||
_ => Err(Errno::InvalidArgument)
|
||||
|
@ -293,7 +293,7 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
}
|
||||
SystemCall::WaitPid => {
|
||||
// TODO special "pid" values
|
||||
let pid = unsafe { Pid::from_raw(args[0] as u32) };
|
||||
let pid = Pid::try_from(args[0] as u32)?;
|
||||
let status = arg::struct_mut::<i32>(args[1])?;
|
||||
|
||||
match Process::waitpid(pid) {
|
||||
@ -312,7 +312,7 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
SystemCall::GetPid => Ok(Process::current().id().value() as usize),
|
||||
SystemCall::GetPid => Ok(u32::from(Process::current().id()) as usize),
|
||||
SystemCall::GetTid => Ok(Thread::current().id() as usize),
|
||||
SystemCall::Sleep => {
|
||||
let rem_buf = arg::option_buf_ref(args[1], size_of::<u64>() * 2)?;
|
||||
@ -358,7 +358,7 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
let proc = if pid == 0 {
|
||||
current
|
||||
} else {
|
||||
let pid = unsafe { Pid::from_raw(pid) };
|
||||
let pid = Pid::try_from(pid)?;
|
||||
let proc = Process::get(pid).ok_or(Errno::DoesNotExist)?;
|
||||
if proc.sid() != current.sid() {
|
||||
return Err(Errno::PermissionDenied);
|
||||
@ -366,7 +366,7 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
proc
|
||||
};
|
||||
|
||||
Ok(proc.sid().value() as usize)
|
||||
Ok(u32::from(proc.sid()) as usize)
|
||||
}
|
||||
SystemCall::GetPgid => {
|
||||
// TODO handle kernel processes here?
|
||||
@ -375,13 +375,13 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
let proc = if pid == 0 {
|
||||
current
|
||||
} else {
|
||||
let pid = unsafe { Pid::from_raw(pid) };
|
||||
let pid = Pid::try_from(pid)?;
|
||||
Process::get(pid).ok_or(Errno::DoesNotExist)?
|
||||
};
|
||||
|
||||
Ok(proc.pgid().value() as usize)
|
||||
Ok(u32::from(proc.pgid()) as usize)
|
||||
}
|
||||
SystemCall::GetPpid => Ok(Process::current().ppid().unwrap().value() as usize),
|
||||
SystemCall::GetPpid => Ok(u32::from(Process::current().ppid().unwrap()) as usize),
|
||||
SystemCall::SetSid => {
|
||||
let proc = Process::current();
|
||||
let mut io = proc.io.lock();
|
||||
@ -392,7 +392,7 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
|
||||
let id = proc.id();
|
||||
proc.set_sid(id);
|
||||
Ok(id.value() as usize)
|
||||
Ok(u32::from(id) as usize)
|
||||
}
|
||||
SystemCall::SetPgid => {
|
||||
let pid = args[0] as u32;
|
||||
@ -407,7 +407,7 @@ pub fn syscall(num: SystemCall, args: &[usize]) -> Result<usize, Errno> {
|
||||
todo!();
|
||||
}
|
||||
|
||||
Ok(proc.pgid().value() as usize)
|
||||
Ok(u32::from(proc.pgid()) as usize)
|
||||
}
|
||||
|
||||
// System
|
||||
|
@ -196,11 +196,11 @@ pub fn sys_fstatat(
|
||||
/// System call
|
||||
#[inline(always)]
|
||||
pub unsafe fn sys_fork() -> Result<Option<Pid>, Errno> {
|
||||
Errno::from_syscall(syscall!(SystemCall::Fork)).map(|res| {
|
||||
Errno::from_syscall(syscall!(SystemCall::Fork)).and_then(|res| {
|
||||
if res != 0 {
|
||||
Some(unsafe { Pid::from_raw(res as u32) })
|
||||
Pid::try_from(res as u32).map(Some)
|
||||
} else {
|
||||
None
|
||||
Ok(None)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -229,7 +229,7 @@ pub fn sys_waitpid(pid: Pid, status: &mut i32) -> Result<(), Errno> {
|
||||
Errno::from_syscall_unit(unsafe {
|
||||
syscall!(
|
||||
SystemCall::WaitPid,
|
||||
argn!(pid.value()),
|
||||
argn!(u32::from(pid)),
|
||||
argp!(status as *mut i32)
|
||||
)
|
||||
})
|
||||
@ -362,21 +362,21 @@ pub fn sys_ex_gettid() -> u32 {
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_getpid() -> Pid {
|
||||
unsafe { Pid::from_raw(syscall!(SystemCall::GetPid) as u32) }
|
||||
Pid::try_from(unsafe { syscall!(SystemCall::GetPid) as u32 }).unwrap()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_getpgid(pid: Pid) -> Result<Pid, Errno> {
|
||||
Errno::from_syscall(unsafe { syscall!(SystemCall::GetPgid, argn!(pid.value())) })
|
||||
.map(|e| unsafe { Pid::from_raw(e as u32) })
|
||||
pub fn sys_getpgid(pid: Option<Pid>) -> Result<Pid, Errno> {
|
||||
Errno::from_syscall(unsafe { syscall!(SystemCall::GetPgid, argn!(Pid::from_option(pid))) })
|
||||
.and_then(|e| Pid::try_from(e as u32))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn sys_setpgid(pid: Pid, pgid: Pid) -> Result<Pid, Errno> {
|
||||
pub fn sys_setpgid(pid: Option<Pid>, pgid: Option<Pid>) -> Result<Pid, Errno> {
|
||||
Errno::from_syscall(unsafe {
|
||||
syscall!(SystemCall::SetPgid, argn!(pid.value()), argn!(pgid.value()))
|
||||
syscall!(SystemCall::SetPgid, argn!(Pid::from_option(pid)), argn!(Pid::from_option(pgid)))
|
||||
})
|
||||
.map(|e| unsafe { Pid::from_raw(e as u32) })
|
||||
.and_then(|e| Pid::try_from(e as u32))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@ -404,7 +404,7 @@ pub fn sys_getgid() -> GroupId {
|
||||
#[inline(always)]
|
||||
pub fn sys_setsid() -> Result<Pid, Errno> {
|
||||
Errno::from_syscall(unsafe { syscall!(SystemCall::SetSid) })
|
||||
.map(|e| unsafe { Pid::from_raw(e as u32) })
|
||||
.and_then(|e| Pid::try_from(e as u32) )
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -12,6 +12,11 @@ pub struct ExitCode(i32);
|
||||
#[repr(transparent)]
|
||||
pub struct Pid(u32);
|
||||
|
||||
/// Wrapper type for thread ID
|
||||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
|
||||
#[repr(transparent)]
|
||||
pub struct Tid(u32);
|
||||
|
||||
#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct Pgid(u32);
|
||||
@ -57,10 +62,14 @@ impl Pid {
|
||||
pub const IDLE: Self = Self(Self::KERNEL_BIT);
|
||||
|
||||
const KERNEL_BIT: u32 = 1 << 31;
|
||||
const USER_MAX: u32 = 256;
|
||||
|
||||
/// Constructs an instance of user-space PID
|
||||
pub const fn user(id: u32) -> Self {
|
||||
assert!(id < 256, "PID is too high");
|
||||
assert!(id < Self::USER_MAX, "PID is too high");
|
||||
if id == 0 {
|
||||
panic!("User PID cannot be zero");
|
||||
}
|
||||
Self(id)
|
||||
}
|
||||
|
||||
@ -83,18 +92,16 @@ impl Pid {
|
||||
self.0 as u8
|
||||
}
|
||||
|
||||
/// Returns bit value of this pid
|
||||
pub const fn value(self) -> u32 {
|
||||
self.0
|
||||
pub fn from_option(m: Option<Self>) -> u32 {
|
||||
if let Some(pid) = m {
|
||||
u32::from(pid)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs [Pid] from raw [u32] value
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: does not check `num`
|
||||
pub const unsafe fn from_raw(num: u32) -> Self {
|
||||
Self(num)
|
||||
pub fn to_option(m: u32) -> Option<Self> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,6 +116,26 @@ impl fmt::Debug for Pid {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u32> for Pid {
|
||||
type Error = Errno;
|
||||
|
||||
fn try_from(raw: u32) -> Result<Pid, Errno> {
|
||||
if raw & Self::KERNEL_BIT != 0 {
|
||||
Ok(Pid::kernel(raw & !Self::KERNEL_BIT))
|
||||
} else if raw != 0 && raw < Self::USER_MAX {
|
||||
Ok(Pid::user(raw))
|
||||
} else {
|
||||
Err(Errno::InvalidArgument)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Pid> for u32 {
|
||||
fn from(pid: Pid) -> u32 {
|
||||
pid.0
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Pid> for Pgid {
|
||||
type Error = Errno;
|
||||
|
||||
|
@ -37,7 +37,7 @@ impl From<isize> for SignalDestination {
|
||||
impl From<SignalDestination> for isize {
|
||||
fn from(p: SignalDestination) -> isize {
|
||||
match p {
|
||||
SignalDestination::Process(pid) => pid.value() as isize,
|
||||
SignalDestination::Process(pid) => u32::from(pid) as isize,
|
||||
SignalDestination::Group(pgid) => -(u32::from(pgid) as isize),
|
||||
SignalDestination::This => 0,
|
||||
SignalDestination::All => -1
|
||||
|
@ -67,11 +67,11 @@ fn execute(line: &str) -> Result<ExitCode, Errno> {
|
||||
if let Some(pid) = unsafe { sys_fork()? } {
|
||||
let mut status = 0;
|
||||
sys_waitpid(pid, &mut status)?;
|
||||
let pgid = sys_getpgid(unsafe { Pid::from_raw(0) }).unwrap();
|
||||
let pgid = sys_getpgid(None).unwrap();
|
||||
io::tcsetpgrp(FileDescriptor::STDIN, pgid).unwrap();
|
||||
Ok(ExitCode::from(status))
|
||||
} else {
|
||||
let pgid = sys_setpgid(unsafe { Pid::from_raw(0) }, unsafe { Pid::from_raw(0) }).unwrap();
|
||||
let pgid = sys_setpgid(None, None).unwrap();
|
||||
io::tcsetpgrp(FileDescriptor::STDIN, pgid).unwrap();
|
||||
sys_execve(&filename, &args).unwrap();
|
||||
sys_exit(ExitCode::from(-1));
|
||||
@ -84,7 +84,7 @@ fn main() -> i32 {
|
||||
let mut stdin = io::stdin();
|
||||
|
||||
signal::set_handler(Signal::Interrupt, SignalHandler::Ignore);
|
||||
let pgid = sys_setpgid(unsafe { Pid::from_raw(0) }, unsafe { Pid::from_raw(0) }).unwrap();
|
||||
let pgid = sys_setpgid(None, None).unwrap();
|
||||
io::tcsetpgrp(FileDescriptor::STDIN, pgid).unwrap();
|
||||
|
||||
loop {
|
||||
|
@ -78,13 +78,13 @@ fn login_as(uid: UserId, gid: GroupId, shell: &str) -> Result<(), Errno> {
|
||||
if let Some(pid) = unsafe { sys_fork() }? {
|
||||
let mut status = 0;
|
||||
sys_waitpid(pid, &mut status).ok();
|
||||
let pgid = sys_getpgid(unsafe { Pid::from_raw(0) }).unwrap();
|
||||
let pgid = sys_getpgid(None).unwrap();
|
||||
io::tcsetpgrp(FileDescriptor::STDIN, pgid).unwrap();
|
||||
Ok(())
|
||||
} else {
|
||||
sys_setuid(uid).expect("setuid failed");
|
||||
sys_setgid(gid).expect("setgid failed");
|
||||
let pgid = sys_setpgid(unsafe { Pid::from_raw(0) }, unsafe { Pid::from_raw(0) }).unwrap();
|
||||
let pgid = sys_setpgid(None, None).unwrap();
|
||||
io::tcsetpgrp(FileDescriptor::STDIN, pgid).unwrap();
|
||||
sys_execve(shell, &[shell]).expect("execve() failed");
|
||||
panic!();
|
||||
|
Loading…
x
Reference in New Issue
Block a user