use alloc::arc::Arc; use alloc::boxed::Box; use collections::Vec; use spin::Mutex; use arch; use super::file::File; use super::memory::{Memory, SharedMemory}; #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum Status { Runnable, Blocked, Exited(usize) } /// A context, which identifies either a process or a thread #[derive(Debug)] pub struct Context { /// The ID of this context pub id: usize, /// Status of context pub status: Status, /// Context running or not pub running: bool, /// The architecture specific context pub arch: arch::context::Context, /// Kernel stack pub kstack: Option>, /// Executable image pub image: Vec, /// User heap pub heap: Option, /// User stack pub stack: Option, /// The open files in the scheme pub files: Arc>>> } impl Context { /// Create a new context pub fn new(id: usize) -> Context { Context { id: id, status: Status::Blocked, running: false, arch: arch::context::Context::new(), kstack: None, image: Vec::new(), heap: None, stack: None, files: Arc::new(Mutex::new(Vec::new())) } } /// Add a file to the lowest available slot. /// Return the file descriptor number or None if no slot was found pub fn add_file(&mut self, file: File) -> Option { let mut files = self.files.lock(); for (i, mut file_option) in files.iter_mut().enumerate() { if file_option.is_none() { *file_option = Some(file); return Some(i); } } let len = files.len(); if len < super::CONTEXT_MAX_FILES { files.push(Some(file)); Some(len) } else { None } } /// Get a file pub fn get_file(&self, i: usize) -> Option { let files = self.files.lock(); if i < files.len() { files[i] } else { None } } /// Remove a file // TODO: adjust files vector to smaller size if possible pub fn remove_file(&mut self, i: usize) -> Option { let mut files = self.files.lock(); if i < files.len() { files[i].take() } else { None } } }