[libos] Replace file table with internally implemented mutex

This commit is contained in:
ClawSeven 2024-04-28 20:46:39 +08:00 committed by volcano
parent 9a174aee01
commit bfc97f5ba2
9 changed files with 23 additions and 22 deletions

@ -8,7 +8,7 @@ use crate::prelude::*;
/// An event notifier broadcasts interesting events to registered observers. /// An event notifier broadcasts interesting events to registered observers.
pub struct Notifier<E: Event, F: EventFilter<E> = DummyEventFilter<E>> { pub struct Notifier<E: Event, F: EventFilter<E> = DummyEventFilter<E>> {
subscribers: SgxMutex<VecDeque<Subscriber<E, F>>>, subscribers: Mutex<VecDeque<Subscriber<E, F>>>,
} }
struct Subscriber<E: Event, F: EventFilter<E>> { struct Subscriber<E: Event, F: EventFilter<E>> {
@ -20,7 +20,7 @@ struct Subscriber<E: Event, F: EventFilter<E>> {
impl<E: Event, F: EventFilter<E>> Notifier<E, F> { impl<E: Event, F: EventFilter<E>> Notifier<E, F> {
/// Create an event notifier. /// Create an event notifier.
pub fn new() -> Self { pub fn new() -> Self {
let subscribers = SgxMutex::new(VecDeque::new()); let subscribers = Mutex::new(VecDeque::new());
Self { subscribers } Self { subscribers }
} }
@ -31,7 +31,7 @@ impl<E: Event, F: EventFilter<E>> Notifier<E, F> {
filter: Option<F>, filter: Option<F>,
metadata: Option<Weak<dyn Any + Send + Sync>>, metadata: Option<Weak<dyn Any + Send + Sync>>,
) { ) {
let mut subscribers = self.subscribers.lock().unwrap(); let mut subscribers = self.subscribers.lock();
subscribers.push_back(Subscriber { subscribers.push_back(Subscriber {
observer, observer,
filter, filter,
@ -41,13 +41,13 @@ impl<E: Event, F: EventFilter<E>> Notifier<E, F> {
/// Unregister an observer. /// Unregister an observer.
pub fn unregister(&self, observer: &Weak<dyn Observer<E>>) { pub fn unregister(&self, observer: &Weak<dyn Observer<E>>) {
let mut subscribers = self.subscribers.lock().unwrap(); let mut subscribers = self.subscribers.lock();
subscribers.retain(|subscriber| !Weak::ptr_eq(&subscriber.observer, observer)); subscribers.retain(|subscriber| !Weak::ptr_eq(&subscriber.observer, observer));
} }
/// Broadcast an event to all registered observers. /// Broadcast an event to all registered observers.
pub fn broadcast(&self, event: &E) { pub fn broadcast(&self, event: &E) {
let subscribers = self.subscribers.lock().unwrap(); let subscribers = self.subscribers.lock();
for subscriber in subscribers.iter() { for subscriber in subscribers.iter() {
if let Some(filter) = subscriber.filter.as_ref() { if let Some(filter) = subscriber.filter.as_ref() {
if !filter.filter(event) { if !filter.filter(event) {

@ -10,7 +10,7 @@ pub fn do_dup(old_fd: FileDesc) -> Result<FileDesc> {
pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<FileDesc> { pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<FileDesc> {
let current = current!(); let current = current!();
let mut files = current.files().lock().unwrap(); let mut files = current.files().lock();
let file = files.get(old_fd)?; let file = files.get(old_fd)?;
let soft_rlimit_nofile = current!() let soft_rlimit_nofile = current!()
.rlimits() .rlimits()
@ -34,7 +34,7 @@ pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<FileDesc> {
pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<FileDesc> { pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<FileDesc> {
let creation_flags = CreationFlags::from_bits_truncate(flags); let creation_flags = CreationFlags::from_bits_truncate(flags);
let current = current!(); let current = current!();
let mut files = current.files().lock().unwrap(); let mut files = current.files().lock();
let file = files.get(old_fd)?; let file = files.get(old_fd)?;
let soft_rlimit_nofile = current!() let soft_rlimit_nofile = current!()
.rlimits() .rlimits()

@ -63,7 +63,7 @@ pub fn do_fcntl(fd: FileDesc, cmd: &mut FcntlCmd) -> Result<isize> {
debug!("fcntl: fd: {:?}, cmd: {:?}", &fd, cmd); debug!("fcntl: fd: {:?}, cmd: {:?}", &fd, cmd);
let current = current!(); let current = current!();
let mut file_table = current.files().lock().unwrap(); let mut file_table = current.files().lock();
let ret = match cmd { let ret = match cmd {
FcntlCmd::DupFd(min_fd) => { FcntlCmd::DupFd(min_fd) => {

@ -46,7 +46,7 @@ impl DirProcINode for LockedProcFdDirINode {
.process_ref .process_ref
.main_thread() .main_thread()
.ok_or(FsError::EntryNotFound)?; .ok_or(FsError::EntryNotFound)?;
let fds = main_thread.files().lock().unwrap().fds(); let fds = main_thread.files().lock().fds();
let fd = fds.iter().nth(i - 2).ok_or(FsError::EntryNotFound)?; let fd = fds.iter().nth(i - 2).ok_or(FsError::EntryNotFound)?;
Ok(fd.to_string()) Ok(fd.to_string())
} }
@ -72,7 +72,7 @@ impl DirProcINode for LockedProcFdDirINode {
return Ok(()); return Ok(());
} }
}; };
let fds = main_thread.files().lock().unwrap().fds(); let fds = main_thread.files().lock().fds();
let start_offset = *offset; let start_offset = *offset;
for fd in fds.iter().skip(start_offset - 2) { for fd in fds.iter().skip(start_offset - 2) {
rcore_fs::visit_entry!( rcore_fs::visit_entry!(

@ -108,14 +108,14 @@ impl EpollFile {
fn register_to_file_table(&self) { fn register_to_file_table(&self) {
let weak_observer = self.weak_self.clone() as Weak<dyn Observer<_>>; let weak_observer = self.weak_self.clone() as Weak<dyn Observer<_>>;
let thread = current!(); let thread = current!();
let file_table = thread.files().lock().unwrap(); let file_table = thread.files().lock();
file_table.notifier().register(weak_observer, None, None); file_table.notifier().register(weak_observer, None, None);
} }
fn unregister_from_file_table(&self) { fn unregister_from_file_table(&self) {
let weak_observer = self.weak_self.clone() as Weak<dyn Observer<_>>; let weak_observer = self.weak_self.clone() as Weak<dyn Observer<_>>;
let thread = current!(); let thread = current!();
let file_table = thread.files().lock().unwrap(); let file_table = thread.files().lock();
file_table.notifier().unregister(&weak_observer); file_table.notifier().unregister(&weak_observer);
} }

@ -253,7 +253,7 @@ fn new_process_common(
let vm_ref = Arc::new(vm); let vm_ref = Arc::new(vm);
let files_ref = { let files_ref = {
let files = init_files(current_ref, file_actions, host_stdio_fds, &reuse_tid)?; let files = init_files(current_ref, file_actions, host_stdio_fds, &reuse_tid)?;
Arc::new(SgxMutex::new(files)) Arc::new(Mutex::new(files))
}; };
let fs_ref = Arc::new(RwLock::new(current_ref.fs().read().unwrap().clone())); let fs_ref = Arc::new(RwLock::new(current_ref.fs().read().unwrap().clone()));
let sched_ref = Arc::new(SgxMutex::new(current_ref.sched().lock().unwrap().clone())); let sched_ref = Arc::new(SgxMutex::new(current_ref.sched().lock().unwrap().clone()));
@ -361,7 +361,7 @@ fn init_files(
let should_inherit_file_table = current_ref.process().pid() > 0; let should_inherit_file_table = current_ref.process().pid() > 0;
if should_inherit_file_table { if should_inherit_file_table {
// Fork: clone file table // Fork: clone file table
let mut cloned_file_table = current_ref.files().lock().unwrap().clone(); let mut cloned_file_table = current_ref.files().lock().clone();
// By default, file descriptors remain open across an execve(). // By default, file descriptors remain open across an execve().
// File descriptors that are marked close-on-exec are closed, which will cause // File descriptors that are marked close-on-exec are closed, which will cause

@ -77,7 +77,7 @@ pub fn do_vfork(mut context: *mut CpuContext) -> Result<isize> {
let parent_pid = current.process().pid(); let parent_pid = current.process().pid();
let mut vfork_file_tables = VFORK_PARENT_FILE_TABLES.lock().unwrap(); let mut vfork_file_tables = VFORK_PARENT_FILE_TABLES.lock().unwrap();
let parent_file_table = { let parent_file_table = {
let mut current_file_table = current.files().lock().unwrap(); let mut current_file_table = current.files().lock();
let new_file_table = current_file_table.clone(); let new_file_table = current_file_table.clone();
// FileTable contains non-cloned struct, so here we do a memory replacement to use new // FileTable contains non-cloned struct, so here we do a memory replacement to use new
// file table in child and store the original file table in TLS. // file table in child and store the original file table in TLS.
@ -156,7 +156,7 @@ fn restore_parent_process(mut context: *mut CpuContext, current_ref: &ThreadRef)
// Close all child opened files // Close all child opened files
close_files_opened_by_child(current_ref, &parent_file_table)?; close_files_opened_by_child(current_ref, &parent_file_table)?;
let mut current_file_table = current_ref.files().lock().unwrap(); let mut current_file_table = current_ref.files().lock();
*current_file_table = parent_file_table; *current_file_table = parent_file_table;
// Get child pid and restore CpuContext // Get child pid and restore CpuContext
@ -195,7 +195,7 @@ pub fn check_vfork_for_exec(current_ref: &ThreadRef) -> Option<(ThreadId, Option
} }
fn close_files_opened_by_child(current: &ThreadRef, parent_file_table: &FileTable) -> Result<()> { fn close_files_opened_by_child(current: &ThreadRef, parent_file_table: &FileTable) -> Result<()> {
let current_file_table = current.files().lock().unwrap(); let current_file_table = current.files().lock();
let child_open_fds: Vec<FileDesc> = current_file_table let child_open_fds: Vec<FileDesc> = current_file_table
.table() .table()
.iter() .iter()

@ -14,6 +14,7 @@ use crate::misc::ResourceLimits;
use crate::prelude::*; use crate::prelude::*;
use crate::sched::{NiceValue, SchedAgent}; use crate::sched::{NiceValue, SchedAgent};
use crate::signal::{SigDispositions, SigQueues}; use crate::signal::{SigDispositions, SigQueues};
use crate::util::sync::Mutex;
use crate::vm::ProcessVM; use crate::vm::ProcessVM;
use self::pgrp::ProcessGrp; use self::pgrp::ProcessGrp;
@ -74,7 +75,7 @@ pub type gid_t = u32;
pub type ProcessRef = Arc<Process>; pub type ProcessRef = Arc<Process>;
pub type ThreadRef = Arc<Thread>; pub type ThreadRef = Arc<Thread>;
pub type FileTableRef = Arc<SgxMutex<FileTable>>; pub type FileTableRef = Arc<Mutex<FileTable>>;
pub type ProcessVMRef = Arc<ProcessVM>; pub type ProcessVMRef = Arc<ProcessVM>;
pub type FsViewRef = Arc<RwLock<FsView>>; pub type FsViewRef = Arc<RwLock<FsView>>;
pub type SchedAgentRef = Arc<SgxMutex<SchedAgent>>; pub type SchedAgentRef = Arc<SgxMutex<SchedAgent>>;

@ -133,12 +133,12 @@ impl Thread {
/// Get a file from the file table. /// Get a file from the file table.
pub fn file(&self, fd: FileDesc) -> Result<FileRef> { pub fn file(&self, fd: FileDesc) -> Result<FileRef> {
self.files().lock().unwrap().get(fd) self.files().lock().get(fd)
} }
/// Add a file to the file table. /// Add a file to the file table.
pub fn add_file(&self, new_file: FileRef, close_on_spawn: bool) -> FileDesc { pub fn add_file(&self, new_file: FileRef, close_on_spawn: bool) -> FileDesc {
self.files().lock().unwrap().put(new_file, close_on_spawn) self.files().lock().put(new_file, close_on_spawn)
} }
/// Close a file from the file table. It will release the POSIX advisory locks owned /// Close a file from the file table. It will release the POSIX advisory locks owned
@ -147,7 +147,7 @@ impl Thread {
// Deadlock note: EpollFile's drop method needs to access file table. So // Deadlock note: EpollFile's drop method needs to access file table. So
// if the drop method is invoked inside the del method, then there will be // if the drop method is invoked inside the del method, then there will be
// a deadlock. // a deadlock.
let file = self.files().lock().unwrap().del(fd)?; let file = self.files().lock().del(fd)?;
file.release_advisory_locks(); file.release_advisory_locks();
Ok(()) Ok(())
} }
@ -156,7 +156,7 @@ impl Thread {
/// by current process. /// by current process.
pub fn close_all_files(&self) { pub fn close_all_files(&self) {
// Deadlock note: Same with the issue in close_file method // Deadlock note: Same with the issue in close_file method
let files = self.files().lock().unwrap().del_all(); let files = self.files().lock().del_all();
for file in files { for file in files {
file.release_advisory_locks(); file.release_advisory_locks();
} }