This commit is contained in:
jD91mZM2
2019-07-07 12:17:48 +02:00
parent 35c1d5210c
commit 43ff8801bc
9 changed files with 70 additions and 53 deletions
+1 -1
View File
@@ -46,10 +46,10 @@ pub mod sys_statvfs;
pub mod sys_time;
pub mod sys_timeb;
//pub mod sys_times;
pub mod sys_user;
pub mod _wctype;
pub mod sys_uio;
pub mod sys_un;
pub mod sys_user;
pub mod sys_utsname;
pub mod sys_wait;
pub mod termios;
+1 -1
View File
@@ -5,8 +5,8 @@ use header::errno;
use header::fcntl::*;
use header::string::strchr;
use io::LineWriter;
use platform::types::*;
use platform;
use platform::types::*;
use sync::Mutex;
use super::constants::*;
+3 -3
View File
@@ -14,10 +14,10 @@ use header::errno::{self, STR_ERROR};
use header::string::{self, strlen};
use header::{fcntl, stdlib, unistd};
use io::{self, BufRead, LineWriter, Read, Write};
use platform::types::*;
use platform::{Pal, Sys};
use platform::{errno, WriteByte};
use platform;
use platform::types::*;
use platform::{errno, WriteByte};
use platform::{Pal, Sys};
use sync::Mutex;
pub use self::constants::*;
+1 -1
View File
@@ -1,7 +1,7 @@
//! ptrace compatibility layer for Redox OS
use platform::types::*;
use platform::{Sys, PalPtrace};
use platform::{PalPtrace, Sys};
pub const PTRACE_PEEKTEXT: c_int = 1;
pub const PTRACE_PEEKDATA: c_int = 2;
+12 -8
View File
@@ -4,7 +4,7 @@ use platform::types::*;
#[repr(C)]
pub struct user_fpregs_struct {
cwd: u16,
cwd: u16,
swd: u16,
ftw: u16,
fop: u16,
@@ -12,14 +12,14 @@ pub struct user_fpregs_struct {
rdp: u64,
mxcsr: u32,
mxcr_mask: u32,
st_space: [u32; 32],
st_space: [u32; 32],
xmm_space: [u32; 64],
padding: [u32; 24]
padding: [u32; 24],
}
#[repr(C)]
pub struct user_regs_struct {
r15: c_ulong,
r15: c_ulong,
r14: c_ulong,
r13: c_ulong,
r12: c_ulong,
@@ -29,14 +29,14 @@ pub struct user_regs_struct {
r10: c_ulong,
r9: c_ulong,
r8: c_ulong,
rax: c_ulong,
rax: c_ulong,
rcx: c_ulong,
rdx: c_ulong,
rsi: c_ulong,
rdi: c_ulong,
orig_rax: c_ulong,
rip: c_ulong,
cs: c_ulong,
cs: c_ulong,
eflags: c_ulong,
rsp: c_ulong,
ss: c_ulong,
@@ -45,8 +45,12 @@ pub struct user_regs_struct {
ds: c_ulong,
es: c_ulong,
fs: c_ulong,
gs: c_ulong
gs: c_ulong,
}
#[no_mangle]
pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb(a: user_fpregs_struct, b: user_regs_struct) {}
pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb(
a: user_fpregs_struct,
b: user_regs_struct,
) {
}
+1 -3
View File
@@ -11,9 +11,7 @@ use crate::sync::{Mutex, Once};
use alloc::collections::BTreeMap;
#[derive(Default)]
struct State {
}
struct State {}
static STATE: Once<Mutex<State>> = Once::new();
+19 -13
View File
@@ -6,8 +6,8 @@ pub use self::once::Once;
use core::cell::UnsafeCell;
use core::ops::Deref;
use core::sync::atomic::AtomicI32 as AtomicInt;
use core::sync::atomic;
use core::sync::atomic::AtomicI32 as AtomicInt;
use platform::types::*;
use platform::{Pal, Sys};
@@ -18,28 +18,36 @@ const FUTEX_WAKE: c_int = 1;
enum AttemptStatus {
Desired,
Waiting,
Other
Other,
}
/// Convenient wrapper around the "futex" system call for
/// synchronization implementations
struct AtomicLock {
atomic: UnsafeCell<AtomicInt>
atomic: UnsafeCell<AtomicInt>,
}
impl AtomicLock {
pub const fn new(value: c_int) -> Self {
Self {
atomic: UnsafeCell::new(AtomicInt::new(value))
atomic: UnsafeCell::new(AtomicInt::new(value)),
}
}
pub fn notify_one(&self) {
Sys::futex(unsafe { &mut *self.atomic.get() }.get_mut(), FUTEX_WAKE, 1);
}
pub fn notify_all(&self) {
Sys::futex(unsafe { &mut *self.atomic.get() }.get_mut(), FUTEX_WAKE, c_int::max_value());
Sys::futex(
unsafe { &mut *self.atomic.get() }.get_mut(),
FUTEX_WAKE,
c_int::max_value(),
);
}
pub fn wait_if(&self, value: c_int) {
Sys::futex(unsafe { &mut *self.atomic.get() }.get_mut(), FUTEX_WAIT, value);
Sys::futex(
unsafe { &mut *self.atomic.get() }.get_mut(),
FUTEX_WAIT,
value,
);
}
/// A general way to efficiently wait for what might be a long time, using two closures:
///
@@ -63,7 +71,7 @@ impl AtomicLock {
pub fn wait_until<F1, F2>(&self, attempt: F1, mark_long: F2, long: c_int)
where
F1: Fn(&AtomicInt) -> AttemptStatus,
F2: Fn(&AtomicInt) -> AttemptStatus
F2: Fn(&AtomicInt) -> AttemptStatus,
{
// First, try spinning for really short durations
for _ in 0..999 {
@@ -84,9 +92,9 @@ impl AtomicLock {
}
if
// If we or somebody else already initiated a long
// wait, OR
previous == AttemptStatus::Waiting ||
// If we or somebody else already initiated a long
// wait, OR
previous == AttemptStatus::Waiting ||
// Otherwise, unless our attempt to initiate a long
// wait informed us that we might be done waiting
mark_long(self) != AttemptStatus::Desired
@@ -102,8 +110,6 @@ impl Deref for AtomicLock {
type Target = AtomicInt;
fn deref(&self) -> &Self::Target {
unsafe {
&*self.atomic.get()
}
unsafe { &*self.atomic.get() }
}
}
+11 -7
View File
@@ -5,8 +5,8 @@ use core::sync::atomic::Ordering::SeqCst;
use platform::types::*;
const UNLOCKED: c_int = 0;
const LOCKED: c_int = 1;
const WAITING: c_int = 2;
const LOCKED: c_int = 1;
const WAITING: c_int = 2;
pub struct Mutex<T> {
lock: AtomicLock,
@@ -40,7 +40,8 @@ impl<T> Mutex<T> {
/// on failure. You should probably not worry about this, it's used for
/// internal optimizations.
pub unsafe fn manual_try_lock(&self) -> Result<&mut T, c_int> {
self.lock.compare_exchange(UNLOCKED, LOCKED, SeqCst, SeqCst)
self.lock
.compare_exchange(UNLOCKED, LOCKED, SeqCst, SeqCst)
.map(|_| &mut *self.content.get())
}
/// Lock the mutex, returning the inner content. After doing this, it's
@@ -53,15 +54,18 @@ impl<T> Mutex<T> {
.map(|_| AttemptStatus::Desired)
.unwrap_or_else(|e| match e {
WAITING => AttemptStatus::Waiting,
_ => AttemptStatus::Other
_ => AttemptStatus::Other,
})
},
|lock| match lock.compare_exchange_weak(LOCKED, WAITING, SeqCst, SeqCst).unwrap_or_else(|e| e) {
|lock| match lock
.compare_exchange_weak(LOCKED, WAITING, SeqCst, SeqCst)
.unwrap_or_else(|e| e)
{
UNLOCKED => AttemptStatus::Desired,
WAITING => AttemptStatus::Waiting,
_ => AttemptStatus::Other
_ => AttemptStatus::Other,
},
WAITING
WAITING,
);
&mut *self.content.get()
}
+21 -16
View File
@@ -5,13 +5,13 @@ use core::sync::atomic::Ordering::SeqCst;
use platform::types::*;
const UNINITIALIZED: c_int = 0;
const INITIALIZING: c_int = 1;
const WAITING: c_int = 2;
const INITIALIZED: c_int = 3;
const INITIALIZING: c_int = 1;
const WAITING: c_int = 2;
const INITIALIZED: c_int = 3;
pub struct Once<T> {
status: AtomicLock,
data: UnsafeCell<MaybeUninit<T>>
data: UnsafeCell<MaybeUninit<T>>,
}
unsafe impl<T: Send> Send for Once<T> {}
unsafe impl<T: Send> Sync for Once<T> {}
@@ -19,13 +19,17 @@ impl<T> Once<T> {
pub const fn new() -> Self {
Self {
status: AtomicLock::new(UNINITIALIZED),
data: UnsafeCell::new(MaybeUninit::uninit())
data: UnsafeCell::new(MaybeUninit::uninit()),
}
}
pub fn call_once<F>(&self, f: F) -> &mut T
where F: FnOnce() -> T
where
F: FnOnce() -> T,
{
match self.status.compare_and_swap(UNINITIALIZED, INITIALIZING, SeqCst) {
match self
.status
.compare_and_swap(UNINITIALIZED, INITIALIZING, SeqCst)
{
UNINITIALIZED => {
// We now have a lock, let's initiate things!
let ret = unsafe { &mut *self.data.get() }.write(f());
@@ -35,28 +39,29 @@ impl<T> Once<T> {
// At least one thread is waiting on this to finish
self.status.notify_all();
}
},
}
INITIALIZING | WAITING => self.status.wait_until(
|lock| match lock.load(SeqCst) {
WAITING => AttemptStatus::Waiting,
INITIALIZED => AttemptStatus::Desired,
_ => AttemptStatus::Other
_ => AttemptStatus::Other,
},
|lock| match lock.compare_exchange_weak(INITIALIZING, WAITING, SeqCst, SeqCst).unwrap_or_else(|e| e) {
|lock| match lock
.compare_exchange_weak(INITIALIZING, WAITING, SeqCst, SeqCst)
.unwrap_or_else(|e| e)
{
WAITING => AttemptStatus::Waiting,
INITIALIZED => AttemptStatus::Desired,
_ => AttemptStatus::Other
_ => AttemptStatus::Other,
},
WAITING
WAITING,
),
INITIALIZED => (),
_ => unreachable!("invalid state for Once<T>")
_ => unreachable!("invalid state for Once<T>"),
}
// At this point the data must be initialized!
unsafe {
&mut *(&mut *self.data.get()).as_mut_ptr()
}
unsafe { &mut *(&mut *self.data.get()).as_mut_ptr() }
}
}
impl<T> Default for Once<T> {