[libos] Replace file table with internally implemented mutex
This commit is contained in:
parent
9a174aee01
commit
bfc97f5ba2
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user