Switch Context::files to RwLock
This commit is contained in:
@@ -127,7 +127,7 @@ impl ContextSnapshot {
|
||||
pub fn new(context: &Context) -> Self {
|
||||
let name = context.name.read().clone();
|
||||
let mut files = Vec::new();
|
||||
for descriptor_opt in context.files.lock().iter() {
|
||||
for descriptor_opt in context.files.read().iter() {
|
||||
let description = if let Some(descriptor) = descriptor_opt {
|
||||
let description = descriptor.description.read();
|
||||
Some(FileDescription {
|
||||
@@ -239,7 +239,7 @@ pub struct Context {
|
||||
/// The current working directory
|
||||
pub cwd: Arc<RwLock<Vec<u8>>>,
|
||||
/// The open files in the scheme
|
||||
pub files: Arc<Mutex<Vec<Option<FileDescriptor>>>>,
|
||||
pub files: Arc<RwLock<Vec<Option<FileDescriptor>>>>,
|
||||
/// Signal actions
|
||||
pub actions: Arc<Mutex<Vec<(SigAction, usize)>>>,
|
||||
/// The pointer to the user-space registers, saved after certain
|
||||
@@ -294,7 +294,7 @@ impl Context {
|
||||
grants: Arc::new(Mutex::new(UserGrants::default())),
|
||||
name: Arc::new(RwLock::new(String::new().into_boxed_str())),
|
||||
cwd: Arc::new(RwLock::new(Vec::new())),
|
||||
files: Arc::new(Mutex::new(Vec::new())),
|
||||
files: Arc::new(RwLock::new(Vec::new())),
|
||||
actions: Arc::new(Mutex::new(vec![(
|
||||
SigAction {
|
||||
sa_handler: unsafe { mem::transmute(SIG_DFL) },
|
||||
@@ -416,7 +416,7 @@ impl Context {
|
||||
/// Add a file to the lowest available slot greater than or equal to min.
|
||||
/// Return the file descriptor number or None if no slot was found
|
||||
pub fn add_file_min(&self, file: FileDescriptor, min: usize) -> Option<FileHandle> {
|
||||
let mut files = self.files.lock();
|
||||
let mut files = self.files.write();
|
||||
for (i, file_option) in files.iter_mut().enumerate() {
|
||||
if file_option.is_none() && i >= min {
|
||||
*file_option = Some(file);
|
||||
@@ -439,7 +439,7 @@ impl Context {
|
||||
|
||||
/// Get a file
|
||||
pub fn get_file(&self, i: FileHandle) -> Option<FileDescriptor> {
|
||||
let files = self.files.lock();
|
||||
let files = self.files.read();
|
||||
if i.into() < files.len() {
|
||||
files[i.into()].clone()
|
||||
} else {
|
||||
@@ -450,7 +450,7 @@ impl Context {
|
||||
/// Insert a file with a specific handle number. This is used by dup2
|
||||
/// Return the file descriptor number or None if the slot was not empty, or i was invalid
|
||||
pub fn insert_file(&self, i: FileHandle, file: FileDescriptor) -> Option<FileHandle> {
|
||||
let mut files = self.files.lock();
|
||||
let mut files = self.files.write();
|
||||
if i.into() < super::CONTEXT_MAX_FILES {
|
||||
while i.into() >= files.len() {
|
||||
files.push(None);
|
||||
@@ -469,7 +469,7 @@ impl Context {
|
||||
/// Remove a file
|
||||
// TODO: adjust files vector to smaller size if possible
|
||||
pub fn remove_file(&self, i: FileHandle) -> Option<FileDescriptor> {
|
||||
let mut files = self.files.lock();
|
||||
let mut files = self.files.write();
|
||||
if i.into() < files.len() {
|
||||
files[i.into()].take()
|
||||
} else {
|
||||
|
||||
@@ -35,7 +35,7 @@ impl EventQueue {
|
||||
let contexts = context::contexts();
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
let files = context.files.lock();
|
||||
let files = context.files.read();
|
||||
match files.get(event.id).ok_or(Error::new(EBADF))? {
|
||||
Some(file) => file.clone(),
|
||||
None => return Err(Error::new(EBADF))
|
||||
|
||||
@@ -16,7 +16,7 @@ pub fn resource() -> Result<Vec<u8>> {
|
||||
let contexts = context::contexts();
|
||||
for (id, context_lock) in contexts.iter() {
|
||||
let context = context_lock.read();
|
||||
rows.push((*id, context.name.read().clone(), context.files.lock().clone()));
|
||||
rows.push((*id, context.name.read().clone(), context.files.read().clone()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -349,7 +349,7 @@ impl Scheme for UserScheme {
|
||||
// TODO: Faster, cleaner mechanism to get descriptor
|
||||
let scheme = inner.scheme_id.load(Ordering::SeqCst);
|
||||
let mut desc_res = Err(Error::new(EBADF));
|
||||
for context_file_opt in context.files.lock().iter() {
|
||||
for context_file_opt in context.files.read().iter() {
|
||||
if let Some(context_file) = context_file_opt {
|
||||
let (context_scheme, context_number) = {
|
||||
let desc = context_file.description.read();
|
||||
@@ -402,7 +402,7 @@ impl Scheme for UserScheme {
|
||||
// TODO: Faster, cleaner mechanism to get descriptor
|
||||
let scheme = inner.scheme_id.load(Ordering::SeqCst);
|
||||
let mut desc_res = Err(Error::new(EBADF));
|
||||
for context_file_opt in context.files.lock().iter() {
|
||||
for context_file_opt in context.files.read().iter() {
|
||||
if let Some(context_file) = context_file_opt {
|
||||
let (context_scheme, context_number) = {
|
||||
let desc = context_file.description.read();
|
||||
|
||||
@@ -377,7 +377,7 @@ pub fn fcntl(fd: FileHandle, cmd: usize, arg: usize) -> Result<usize> {
|
||||
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
|
||||
let context = context_lock.read();
|
||||
|
||||
let mut files = context.files.lock();
|
||||
let mut files = context.files.write();
|
||||
match *files.get_mut(fd.into()).ok_or(Error::new(EBADF))? {
|
||||
Some(ref mut file) => match cmd {
|
||||
F_GETFD => {
|
||||
|
||||
@@ -246,7 +246,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
|
||||
if flags.contains(CLONE_FILES) {
|
||||
files = Arc::clone(&context.files);
|
||||
} else {
|
||||
files = Arc::new(Mutex::new(context.files.lock().clone()));
|
||||
files = Arc::new(RwLock::new(context.files.read().clone()));
|
||||
}
|
||||
|
||||
if flags.contains(CLONE_SIGHAND) {
|
||||
@@ -259,7 +259,7 @@ pub fn clone(flags: CloneFlags, stack_base: usize) -> Result<ContextId> {
|
||||
// If not cloning files, dup to get a new number from scheme
|
||||
// This has to be done outside the context lock to prevent deadlocks
|
||||
if !flags.contains(CLONE_FILES) {
|
||||
for (_fd, file_opt) in files.lock().iter_mut().enumerate() {
|
||||
for (_fd, file_opt) in files.write().iter_mut().enumerate() {
|
||||
let new_file_opt = if let Some(ref file) = *file_opt {
|
||||
Some(FileDescriptor {
|
||||
description: Arc::clone(&file.description),
|
||||
@@ -818,7 +818,7 @@ fn fexec_noreturn(
|
||||
(vfork, context.ppid, files)
|
||||
};
|
||||
|
||||
for (_fd, file_opt) in files.lock().iter_mut().enumerate() {
|
||||
for (_fd, file_opt) in files.write().iter_mut().enumerate() {
|
||||
let mut cloexec = false;
|
||||
if let Some(ref file) = *file_opt {
|
||||
if file.cloexec {
|
||||
@@ -1060,12 +1060,12 @@ pub fn exit(status: usize) -> ! {
|
||||
let pid = {
|
||||
let mut context = context_lock.write();
|
||||
{
|
||||
let mut lock = context.files.lock();
|
||||
let mut lock = context.files.write();
|
||||
if Arc::strong_count(&context.files) == 1 {
|
||||
mem::swap(lock.deref_mut(), &mut close_files);
|
||||
}
|
||||
}
|
||||
context.files = Arc::new(Mutex::new(Vec::new()));
|
||||
context.files = Arc::new(RwLock::new(Vec::new()));
|
||||
context.id
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user