Implement a proper mutex type for future usage
This commit is contained in:
@@ -5,6 +5,7 @@ use core::sync::atomic::AtomicBool;
|
||||
|
||||
use fs::File;
|
||||
use io::LineWriter;
|
||||
use mutex::Mutex;
|
||||
use platform::types::*;
|
||||
|
||||
pub struct GlobalFile(UnsafeCell<FILE>);
|
||||
@@ -13,7 +14,7 @@ impl GlobalFile {
|
||||
let file = File::new(file);
|
||||
let writer = LineWriter::new(unsafe { file.get_ref() });
|
||||
GlobalFile(UnsafeCell::new(FILE {
|
||||
lock: AtomicBool::new(false),
|
||||
lock: Mutex::new(()),
|
||||
|
||||
file,
|
||||
flags: constants::F_PERM | flags,
|
||||
|
||||
@@ -7,6 +7,7 @@ use header::errno;
|
||||
use header::fcntl::*;
|
||||
use header::string::strchr;
|
||||
use io::LineWriter;
|
||||
use mutex::Mutex;
|
||||
use platform::types::*;
|
||||
use platform;
|
||||
|
||||
@@ -68,7 +69,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
|
||||
let writer = LineWriter::new(file.get_ref());
|
||||
|
||||
Some(Box::into_raw(Box::new(FILE {
|
||||
lock: AtomicBool::new(false),
|
||||
lock: Mutex::new(()),
|
||||
|
||||
file,
|
||||
flags,
|
||||
|
||||
+21
-18
@@ -17,6 +17,7 @@ use header::fcntl;
|
||||
use header::stdlib::mkstemp;
|
||||
use header::string::strlen;
|
||||
use io::{self, BufRead, LineWriter, SeekFrom, Read, Write};
|
||||
use mutex::Mutex;
|
||||
use platform::types::*;
|
||||
use platform::{Pal, Sys};
|
||||
use platform::{errno, WriteByte};
|
||||
@@ -59,7 +60,7 @@ impl<'a> DerefMut for Buffer<'a> {
|
||||
/// This struct gets exposed to the C API.
|
||||
pub struct FILE {
|
||||
// Can't use spin crate because *_unlocked functions are things in C :(
|
||||
lock: AtomicBool,
|
||||
lock: Mutex<()>,
|
||||
|
||||
file: File,
|
||||
flags: c_int,
|
||||
@@ -148,7 +149,9 @@ impl WriteByte for FILE {
|
||||
}
|
||||
impl FILE {
|
||||
pub fn lock(&mut self) -> LockGuard {
|
||||
flockfile(self);
|
||||
unsafe {
|
||||
flockfile(self);
|
||||
}
|
||||
LockGuard(self)
|
||||
}
|
||||
}
|
||||
@@ -168,7 +171,9 @@ impl<'a> DerefMut for LockGuard<'a> {
|
||||
}
|
||||
impl<'a> Drop for LockGuard<'a> {
|
||||
fn drop(&mut self) {
|
||||
funlockfile(self.0);
|
||||
unsafe {
|
||||
funlockfile(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +201,7 @@ pub extern "C" fn cuserid(_s: *mut c_char) -> *mut c_char {
|
||||
#[no_mangle]
|
||||
pub extern "C" fn fclose(stream: *mut FILE) -> c_int {
|
||||
let stream = unsafe { &mut *stream };
|
||||
flockfile(stream);
|
||||
unsafe { flockfile(stream); }
|
||||
|
||||
let mut r = stream.flush().is_err();
|
||||
let close = Sys::close(*stream.file) < 0;
|
||||
@@ -208,7 +213,7 @@ pub extern "C" fn fclose(stream: *mut FILE) -> c_int {
|
||||
// Reference files aren't closed on drop, so pretend to be a reference
|
||||
stream.file.reference = true;
|
||||
} else {
|
||||
funlockfile(stream);
|
||||
unsafe { funlockfile(stream); }
|
||||
}
|
||||
|
||||
r as c_int
|
||||
@@ -347,10 +352,8 @@ pub extern "C" fn fileno(stream: *mut FILE) -> c_int {
|
||||
/// Do not call any functions other than those with the `_unlocked` postfix while the file is
|
||||
/// locked
|
||||
#[no_mangle]
|
||||
pub extern "C" fn flockfile(file: *mut FILE) {
|
||||
while ftrylockfile(file) != 0 {
|
||||
atomic::spin_loop_hint();
|
||||
}
|
||||
pub unsafe extern "C" fn flockfile(file: *mut FILE) {
|
||||
(*file).lock.manual_lock();
|
||||
}
|
||||
|
||||
/// Open the file in mode `mode`
|
||||
@@ -427,7 +430,7 @@ pub extern "C" fn freopen(
|
||||
stream: &mut FILE,
|
||||
) -> *mut FILE {
|
||||
let mut flags = unsafe { helpers::parse_mode_flags(mode) };
|
||||
flockfile(stream);
|
||||
unsafe { flockfile(stream); }
|
||||
|
||||
let _ = stream.flush();
|
||||
if filename.is_null() {
|
||||
@@ -437,14 +440,14 @@ pub extern "C" fn freopen(
|
||||
}
|
||||
flags &= !(fcntl::O_CREAT | fcntl::O_EXCL | fcntl::O_CLOEXEC);
|
||||
if fcntl::sys_fcntl(*stream.file, fcntl::F_SETFL, flags) < 0 {
|
||||
funlockfile(stream);
|
||||
unsafe { funlockfile(stream); }
|
||||
fclose(stream);
|
||||
return ptr::null_mut();
|
||||
}
|
||||
} else {
|
||||
let new = fopen(filename, mode);
|
||||
if new.is_null() {
|
||||
funlockfile(stream);
|
||||
unsafe { funlockfile(stream); }
|
||||
fclose(stream);
|
||||
return ptr::null_mut();
|
||||
}
|
||||
@@ -454,7 +457,7 @@ pub extern "C" fn freopen(
|
||||
} else if Sys::dup2(*new.file, *stream.file) < 0
|
||||
|| fcntl::sys_fcntl(*stream.file, fcntl::F_SETFL, flags & fcntl::O_CLOEXEC) < 0
|
||||
{
|
||||
funlockfile(stream);
|
||||
unsafe { funlockfile(stream); }
|
||||
fclose(new);
|
||||
fclose(stream);
|
||||
return ptr::null_mut();
|
||||
@@ -462,7 +465,7 @@ pub extern "C" fn freopen(
|
||||
stream.flags = (stream.flags & constants::F_PERM) | new.flags;
|
||||
fclose(new);
|
||||
}
|
||||
funlockfile(stream);
|
||||
unsafe { funlockfile(stream); }
|
||||
stream
|
||||
}
|
||||
|
||||
@@ -521,14 +524,14 @@ pub extern "C" fn ftello(stream: *mut FILE) -> off_t {
|
||||
|
||||
/// Try to lock the file. Returns 0 for success, 1 for failure
|
||||
#[no_mangle]
|
||||
pub extern "C" fn ftrylockfile(file: *mut FILE) -> c_int {
|
||||
unsafe { &mut *file }.lock.compare_and_swap(false, true, Ordering::Acquire) as c_int
|
||||
pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> c_int {
|
||||
if (*file).lock.manual_try_lock().is_ok() { 0 } else { 1 }
|
||||
}
|
||||
|
||||
/// Unlock the file
|
||||
#[no_mangle]
|
||||
pub extern "C" fn funlockfile(file: *mut FILE) {
|
||||
unsafe { &mut *file }.lock.store(false, Ordering::Release);
|
||||
pub unsafe extern "C" fn funlockfile(file: *mut FILE) {
|
||||
(*file).lock.manual_unlock();
|
||||
}
|
||||
|
||||
/// Write `nitems` of size `size` from `ptr` to `stream`
|
||||
|
||||
Reference in New Issue
Block a user