Converting pids into a new type ContextId

Keeping pid (and file descriptor, and scheme id, ...) as usize is a
footgun. Let's remove it.
This commit is contained in:
David Teller 2016-11-13 15:36:52 +01:00
parent d16515ea12
commit 37a34ab7f7
10 changed files with 52 additions and 44 deletions

View file

@ -9,6 +9,10 @@ use context::memory::{Grant, Memory, SharedMemory, Tls};
use syscall::data::Event; use syscall::data::Event;
use sync::{WaitMap, WaitQueue}; use sync::{WaitMap, WaitQueue};
/// Unique identifier for a context (i.e. `pid`).
use ::core::sync::atomic::AtomicUsize;
int_like!(ContextId, AtomicContextId, usize, AtomicUsize);
/// The status of a context - used for scheduling /// The status of a context - used for scheduling
/// See syscall::process::waitpid and the sync module for examples of usage /// See syscall::process::waitpid and the sync module for examples of usage
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
@ -22,9 +26,9 @@ pub enum Status {
#[derive(Debug)] #[derive(Debug)]
pub struct Context { pub struct Context {
/// The ID of this context /// The ID of this context
pub id: usize, pub id: ContextId,
/// The ID of the parent context /// The ID of the parent context
pub ppid: usize, pub ppid: ContextId,
/// The real user id /// The real user id
pub ruid: u32, pub ruid: u32,
/// The real group id /// The real group id
@ -42,7 +46,7 @@ pub struct Context {
/// Context is halting parent /// Context is halting parent
pub vfork: bool, pub vfork: bool,
/// Context is being waited on /// Context is being waited on
pub waitpid: Arc<WaitMap<usize, usize>>, pub waitpid: Arc<WaitMap<ContextId, usize>>,
/// Context should wake up at specified time /// Context should wake up at specified time
pub wake: Option<(u64, u64)>, pub wake: Option<(u64, u64)>,
/// The architecture specific context /// The architecture specific context
@ -75,10 +79,10 @@ pub struct Context {
impl Context { impl Context {
/// Create a new context /// Create a new context
pub fn new(id: usize) -> Context { pub fn new(id: ContextId) -> Context {
Context { Context {
id: id, id: id,
ppid: 0, ppid: ContextId::from(0),
ruid: 0, ruid: 0,
rgid: 0, rgid: 0,
euid: 0, euid: 0,

View file

@ -17,7 +17,7 @@ pub struct RegKey {
#[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct ProcessKey { pub struct ProcessKey {
context_id: usize, context_id: context::context::ContextId,
fd: usize, fd: usize,
} }

View file

@ -7,11 +7,11 @@ use spin::RwLock;
use arch; use arch;
use syscall::error::{Result, Error, EAGAIN}; use syscall::error::{Result, Error, EAGAIN};
use super::context::Context; use super::context::{Context, ContextId};
/// Context list type /// Context list type
pub struct ContextList { pub struct ContextList {
map: BTreeMap<usize, Arc<RwLock<Context>>>, map: BTreeMap<ContextId, Arc<RwLock<Context>>>,
next_id: usize next_id: usize
} }
@ -25,7 +25,7 @@ impl ContextList {
} }
/// Get the nth context. /// Get the nth context.
pub fn get(&self, id: usize) -> Option<&Arc<RwLock<Context>>> { pub fn get(&self, id: ContextId) -> Option<&Arc<RwLock<Context>>> {
self.map.get(&id) self.map.get(&id)
} }
@ -34,7 +34,7 @@ impl ContextList {
self.map.get(&super::CONTEXT_ID.load(Ordering::SeqCst)) self.map.get(&super::CONTEXT_ID.load(Ordering::SeqCst))
} }
pub fn iter(&self) -> ::collections::btree_map::Iter<usize, Arc<RwLock<Context>>> { pub fn iter(&self) -> ::collections::btree_map::Iter<ContextId, Arc<RwLock<Context>>> {
self.map.iter() self.map.iter()
} }
@ -44,7 +44,7 @@ impl ContextList {
self.next_id = 1; self.next_id = 1;
} }
while self.map.contains_key(&self.next_id) { while self.map.contains_key(&ContextId::from(self.next_id)) {
self.next_id += 1; self.next_id += 1;
} }
@ -52,7 +52,7 @@ impl ContextList {
return Err(Error::new(EAGAIN)); return Err(Error::new(EAGAIN));
} }
let id = self.next_id; let id = ContextId::from(self.next_id);
self.next_id += 1; self.next_id += 1;
assert!(self.map.insert(id, Arc::new(RwLock::new(Context::new(id)))).is_none()); assert!(self.map.insert(id, Arc::new(RwLock::new(Context::new(id)))).is_none());
@ -85,7 +85,7 @@ impl ContextList {
Ok(context_lock) Ok(context_lock)
} }
pub fn remove(&mut self, id: usize) -> Option<Arc<RwLock<Context>>> { pub fn remove(&mut self, id: ContextId) -> Option<Arc<RwLock<Context>>> {
self.map.remove(&id) self.map.remove(&id)
} }
} }

View file

@ -1,11 +1,12 @@
//! Context management //! Context management
use alloc::boxed::Box; use alloc::boxed::Box;
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use core::sync::atomic::Ordering;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
pub use self::context::{Context, Status}; pub use self::context::{Context, Status};
pub use self::list::ContextList; pub use self::list::ContextList;
pub use self::switch::switch; pub use self::switch::switch;
pub use context::context::ContextId;
/// Context struct /// Context struct
mod context; mod context;
@ -35,7 +36,7 @@ pub const CONTEXT_MAX_FILES: usize = 65536;
static CONTEXTS: Once<RwLock<ContextList>> = Once::new(); static CONTEXTS: Once<RwLock<ContextList>> = Once::new();
#[thread_local] #[thread_local]
static CONTEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT; static CONTEXT_ID: context::AtomicContextId = context::AtomicContextId::default();
pub fn init() { pub fn init() {
let mut contexts = contexts_mut(); let mut contexts = contexts_mut();
@ -69,6 +70,6 @@ pub fn contexts_mut() -> RwLockWriteGuard<'static, ContextList> {
CONTEXTS.call_once(init_contexts).write() CONTEXTS.call_once(init_contexts).write()
} }
pub fn context_id() -> usize { pub fn context_id() -> context::ContextId {
CONTEXT_ID.load(Ordering::SeqCst) CONTEXT_ID.load(Ordering::SeqCst)
} }

View file

@ -44,13 +44,13 @@ extern crate spin;
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
/// Context management
pub mod context;
#[macro_use] #[macro_use]
#[macro_export]
/// Shared data structures /// Shared data structures
pub mod common; pub mod common;
/// Context management
pub mod context;
/// ELF file parsing /// ELF file parsing
#[cfg(all(not(test), target_arch = "x86_64"))] #[cfg(all(not(test), target_arch = "x86_64"))]
@ -105,7 +105,7 @@ pub extern fn userspace_init() {
/// Allow exception handlers to send signal to arch-independant kernel /// Allow exception handlers to send signal to arch-independant kernel
#[no_mangle] #[no_mangle]
pub extern fn ksignal(signal: usize) { pub extern fn ksignal(signal: usize) {
println!("SIGNAL {}, CPU {}, PID {}", signal, cpu_id(), context::context_id()); println!("SIGNAL {}, CPU {}, PID {:?}", signal, cpu_id(), context::context_id());
{ {
let contexts = context::contexts(); let contexts = context::contexts();
if let Some(context_lock) = contexts.current() { if let Some(context_lock) = contexts.current() {

View file

@ -83,8 +83,8 @@ pub fn resource() -> Result<Vec<u8>> {
let name = str::from_utf8(&name_bytes).unwrap_or(""); let name = str::from_utf8(&name_bytes).unwrap_or("");
string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n", string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
context.id, context.id.into(),
context.ppid, context.ppid.into(),
context.euid, context.euid,
context.egid, context.egid,
stat_string, stat_string,

View file

@ -53,7 +53,7 @@ impl UserInner {
self.call_inner(Packet { self.call_inner(Packet {
id: self.next_id.fetch_add(1, Ordering::SeqCst), id: self.next_id.fetch_add(1, Ordering::SeqCst),
pid: pid, pid: pid.into(),
uid: uid, uid: uid,
gid: gid, gid: gid,
a: a, a: a,
@ -297,7 +297,7 @@ impl Scheme for UserScheme {
inner.call_inner(Packet { inner.call_inner(Packet {
id: id, id: id,
pid: pid, pid: pid.into(),
uid: uid, uid: uid,
gid: gid, gid: gid,
a: SYS_FMAP, a: SYS_FMAP,

View file

@ -25,7 +25,7 @@ pub fn file_op(a: usize, fd: usize, c: usize, d: usize) -> Result<usize> {
let mut packet = Packet { let mut packet = Packet {
id: 0, id: 0,
pid: pid, pid: pid.into(),
uid: uid, uid: uid,
gid: gid, gid: gid,
a: a, a: a,

View file

@ -14,6 +14,8 @@ use self::data::TimeSpec;
use self::error::{Error, Result, ENOSYS}; use self::error::{Error, Result, ENOSYS};
use self::number::*; use self::number::*;
use context::ContextId;
/// Filesystem syscalls /// Filesystem syscalls
pub mod fs; pub mod fs;
@ -54,13 +56,13 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
}, },
_ => match a { _ => match a {
SYS_EXIT => exit(b), SYS_EXIT => exit(b),
SYS_WAITPID => waitpid(b, c, d), SYS_WAITPID => waitpid(ContextId::from(b), c, d).map(ContextId::into),
SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?),
SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?),
SYS_GETPID => getpid(), SYS_GETPID => getpid().map(ContextId::into),
SYS_BRK => brk(b), SYS_BRK => brk(b),
SYS_IOPL => iopl(b), SYS_IOPL => iopl(b),
SYS_CLONE => clone(b, stack), SYS_CLONE => clone(b, stack).map(ContextId::into),
SYS_YIELD => sched_yield(), SYS_YIELD => sched_yield(),
SYS_NANOSLEEP => nanosleep(validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?, validate_slice_mut(c as *mut TimeSpec, 1).ok().map(|rem| &mut rem[0])), SYS_NANOSLEEP => nanosleep(validate_slice(b as *const TimeSpec, 1).map(|req| &req[0])?, validate_slice_mut(c as *mut TimeSpec, 1).ok().map(|rem| &mut rem[0])),
SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?), SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),

View file

@ -13,6 +13,7 @@ use arch::paging::{ActivePageTable, InactivePageTable, Page, PhysicalAddress, Vi
use arch::paging::temporary_page::TemporaryPage; use arch::paging::temporary_page::TemporaryPage;
use arch::start::usermode; use arch::start::usermode;
use context; use context;
use context::ContextId;
use context::memory::Grant; use context::memory::Grant;
use elf::{self, program_header}; use elf::{self, program_header};
use scheme; use scheme;
@ -54,7 +55,7 @@ pub fn brk(address: usize) -> Result<usize> {
} }
} }
pub fn clone(flags: usize, stack_base: usize) -> Result<usize> { pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
let ppid; let ppid;
let pid; let pid;
{ {
@ -665,10 +666,10 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
if let Some(context_lock) = contexts.get(ppid) { if let Some(context_lock) = contexts.get(ppid) {
let mut context = context_lock.write(); let mut context = context_lock.write();
if ! context.unblock() { if ! context.unblock() {
println!("{} not blocked for exec vfork unblock", ppid); println!("{:?} not blocked for exec vfork unblock", ppid);
} }
} else { } else {
println!("{} not found for exec vfork unblock", ppid); println!("{:?} not found for exec vfork unblock", ppid);
} }
} }
}, },
@ -756,7 +757,7 @@ pub fn exit(status: usize) -> ! {
let mut parent = parent_lock.write(); let mut parent = parent_lock.write();
if vfork { if vfork {
if ! parent.unblock() { if ! parent.unblock() {
println!("{} not blocked for exit vfork unblock", ppid); println!("{:?} not blocked for exit vfork unblock", ppid);
} }
} }
parent.waitpid.clone() parent.waitpid.clone()
@ -767,7 +768,7 @@ pub fn exit(status: usize) -> ! {
} }
waitpid.send(pid, status); waitpid.send(pid, status);
} else { } else {
println!("{} not found for exit vfork unblock", ppid); println!("{:?} not found for exit vfork unblock", ppid);
} }
} }
} }
@ -798,7 +799,7 @@ pub fn getgid() -> Result<usize> {
Ok(context.rgid as usize) Ok(context.rgid as usize)
} }
pub fn getpid() -> Result<usize> { pub fn getpid() -> Result<ContextId> {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read(); let context = context_lock.read();
@ -817,7 +818,7 @@ pub fn iopl(_level: usize) -> Result<usize> {
Ok(0) Ok(0)
} }
pub fn kill(pid: usize, sig: usize) -> Result<usize> { pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
use syscall::flag::*; use syscall::flag::*;
let _context_lock = { let _context_lock = {
@ -827,19 +828,19 @@ pub fn kill(pid: usize, sig: usize) -> Result<usize> {
}; };
let term = || { let term = || {
println!("Terminate {}", pid); println!("Terminate {:?}", pid);
}; };
let core = || { let core = || {
println!("Core {}", pid); println!("Core {:?}", pid);
}; };
let stop = || { let stop = || {
println!("Stop {}", pid); println!("Stop {:?}", pid);
}; };
let cont = || { let cont = || {
println!("Continue {}", pid); println!("Continue {:?}", pid);
}; };
match sig { match sig {
@ -1001,7 +1002,7 @@ pub fn virttophys(virtual_address: usize) -> Result<usize> {
} }
} }
fn reap(pid: usize) -> Result<usize> { fn reap(pid: ContextId) -> Result<ContextId> {
// Spin until not running // Spin until not running
let mut running = false; let mut running = false;
while running { while running {
@ -1019,7 +1020,7 @@ fn reap(pid: usize) -> Result<usize> {
contexts.remove(pid).ok_or(Error::new(ESRCH)).and(Ok(pid)) contexts.remove(pid).ok_or(Error::new(ESRCH)).and(Ok(pid))
} }
pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> { pub fn waitpid(pid: ContextId, status_ptr: usize, flags: usize) -> Result<ContextId> {
let waitpid = { let waitpid = {
let contexts = context::contexts(); let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@ -1034,13 +1035,13 @@ pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> {
&mut tmp &mut tmp
}; };
if pid == 0 { if pid.into() == 0 {
if flags & WNOHANG == WNOHANG { if flags & WNOHANG == WNOHANG {
if let Some((w_pid, status)) = waitpid.receive_any_nonblock() { if let Some((w_pid, status)) = waitpid.receive_any_nonblock() {
status_slice[0] = status; status_slice[0] = status;
reap(w_pid) reap(w_pid)
} else { } else {
Ok(0) Ok(ContextId::from(0))
} }
} else { } else {
let (w_pid, status) = waitpid.receive_any(); let (w_pid, status) = waitpid.receive_any();
@ -1053,7 +1054,7 @@ pub fn waitpid(pid: usize, status_ptr: usize, flags: usize) -> Result<usize> {
status_slice[0] = status; status_slice[0] = status;
reap(pid) reap(pid)
} else { } else {
Ok(0) Ok(ContextId::from(0))
} }
} else { } else {
let status = waitpid.receive(&pid); let status = waitpid.receive(&pid);