Skip to content

Commit 368fafb

Browse files
author
Jethro Beekman
committed
SGX target: implement synchronization primitives and threading
1 parent fb97c07 commit 368fafb

File tree

13 files changed

+809
-69
lines changed

13 files changed

+809
-69
lines changed

src/libstd/io/lazy.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const fn done<T>() -> *mut Arc<T> { 1_usize as *mut _ }
2626
unsafe impl<T> Sync for Lazy<T> {}
2727

2828
impl<T> Lazy<T> {
29+
#[unstable(feature = "sys_internals", issue = "0")] // FIXME: min_const_fn
2930
pub const fn new() -> Lazy<T> {
3031
Lazy {
3132
lock: Mutex::new(),

src/libstd/sys/sgx/abi/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub(super) mod panic;
2020
pub mod thread;
2121
pub mod tls;
2222
#[macro_use]
23-
mod usercalls;
23+
pub mod usercalls;
2424

2525
global_asm!(concat!(usercalls_asm!(), include_str!("entry.S")));
2626

@@ -70,7 +70,7 @@ pub extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5:
7070
let _tls_guard = unsafe { tls.activate() };
7171

7272
if secondary {
73-
unimplemented!("thread entrypoint");
73+
super::thread::Thread::entry();
7474

7575
(0, 0)
7676
} else {

src/libstd/sys/sgx/abi/usercalls/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,22 @@ mod alloc;
1616
#[macro_use]
1717
mod raw;
1818

19+
pub fn launch_thread() -> IoResult<()> {
20+
unsafe { raw::launch_thread().from_sgx_result() }
21+
}
22+
1923
pub fn exit(panic: bool) -> ! {
2024
unsafe { raw::exit(panic) }
2125
}
2226

27+
pub fn wait(event_mask: u64, timeout: u64) -> IoResult<u64> {
28+
unsafe { raw::wait(event_mask, timeout).from_sgx_result() }
29+
}
30+
31+
pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {
32+
unsafe { raw::send(event_set, tcs).from_sgx_result() }
33+
}
34+
2335
pub fn alloc(size: usize, alignment: usize) -> IoResult<*mut u8> {
2436
unsafe { raw::alloc(size, alignment).from_sgx_result() }
2537
}

src/libstd/sys/sgx/condvar.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,42 @@
1111
use sys::mutex::Mutex;
1212
use time::Duration;
1313

14-
pub struct Condvar { }
14+
use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex};
15+
16+
pub struct Condvar {
17+
inner: SpinMutex<WaitVariable<()>>,
18+
}
1519

1620
impl Condvar {
21+
#[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
1722
pub const fn new() -> Condvar {
18-
Condvar { }
23+
Condvar { inner: SpinMutex::new(WaitVariable::new(())) }
1924
}
2025

2126
#[inline]
2227
pub unsafe fn init(&mut self) {}
2328

2429
#[inline]
2530
pub unsafe fn notify_one(&self) {
31+
let _ = WaitQueue::notify_one(self.inner.lock());
2632
}
2733

2834
#[inline]
2935
pub unsafe fn notify_all(&self) {
36+
let _ = WaitQueue::notify_all(self.inner.lock());
3037
}
3138

32-
pub unsafe fn wait(&self, _mutex: &Mutex) {
33-
panic!("can't block with web assembly")
39+
pub unsafe fn wait(&self, mutex: &Mutex) {
40+
let guard = self.inner.lock();
41+
mutex.unlock();
42+
WaitQueue::wait(guard);
43+
mutex.lock()
3444
}
3545

3646
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
37-
panic!("can't block with web assembly");
47+
panic!("timeout not supported in SGX");
3848
}
3949

4050
#[inline]
41-
pub unsafe fn destroy(&self) {
42-
}
51+
pub unsafe fn destroy(&self) {}
4352
}

src/libstd/sys/sgx/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use os::raw::c_char;
1818
use sync::atomic::{AtomicBool, Ordering};
1919

2020
pub mod abi;
21+
mod waitqueue;
2122

2223
pub mod alloc;
2324
pub mod args;

src/libstd/sys/sgx/mutex.rs

+96-24
Original file line numberDiff line numberDiff line change
@@ -8,71 +8,143 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use cell::UnsafeCell;
11+
use fortanix_sgx_abi::Tcs;
12+
13+
use super::abi::thread;
14+
15+
use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false};
1216

1317
pub struct Mutex {
14-
locked: UnsafeCell<bool>,
18+
inner: SpinMutex<WaitVariable<bool>>,
1519
}
1620

17-
unsafe impl Send for Mutex {}
18-
unsafe impl Sync for Mutex {} // FIXME
19-
21+
// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
2022
impl Mutex {
23+
#[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
2124
pub const fn new() -> Mutex {
22-
Mutex { locked: UnsafeCell::new(false) }
25+
Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
2326
}
2427

2528
#[inline]
26-
pub unsafe fn init(&mut self) {
27-
}
29+
pub unsafe fn init(&mut self) {}
2830

2931
#[inline]
3032
pub unsafe fn lock(&self) {
31-
let locked = self.locked.get();
32-
assert!(!*locked, "cannot recursively acquire mutex");
33-
*locked = true;
33+
let mut guard = self.inner.lock();
34+
if *guard.lock_var() {
35+
// Another thread has the lock, wait
36+
WaitQueue::wait(guard)
37+
// Another thread has passed the lock to us
38+
} else {
39+
// We are just now obtaining the lock
40+
*guard.lock_var_mut() = true;
41+
}
3442
}
3543

3644
#[inline]
3745
pub unsafe fn unlock(&self) {
38-
*self.locked.get() = false;
46+
let guard = self.inner.lock();
47+
if let Err(mut guard) = WaitQueue::notify_one(guard) {
48+
// No other waiters, unlock
49+
*guard.lock_var_mut() = false;
50+
} else {
51+
// There was a thread waiting, just pass the lock
52+
}
3953
}
4054

4155
#[inline]
4256
pub unsafe fn try_lock(&self) -> bool {
43-
let locked = self.locked.get();
44-
if *locked {
57+
let mut guard = try_lock_or_false!(self.inner);
58+
if *guard.lock_var() {
59+
// Another thread has the lock
4560
false
4661
} else {
47-
*locked = true;
62+
// We are just now obtaining the lock
63+
*guard.lock_var_mut() = true;
4864
true
4965
}
5066
}
5167

5268
#[inline]
53-
pub unsafe fn destroy(&self) {
54-
}
69+
pub unsafe fn destroy(&self) {}
70+
}
71+
72+
struct ReentrantLock {
73+
owner: Option<Tcs>,
74+
count: usize
5575
}
5676

57-
// FIXME
5877
pub struct ReentrantMutex {
78+
inner: SpinMutex<WaitVariable<ReentrantLock>>,
5979
}
6080

6181
impl ReentrantMutex {
62-
pub unsafe fn uninitialized() -> ReentrantMutex {
63-
ReentrantMutex { }
82+
#[unstable(feature = "sgx_internals", issue = "0")] // FIXME: min_const_fn
83+
pub const fn uninitialized() -> ReentrantMutex {
84+
ReentrantMutex { inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 })) }
6485
}
6586

87+
#[inline]
6688
pub unsafe fn init(&mut self) {}
6789

68-
pub unsafe fn lock(&self) {}
90+
#[inline]
91+
pub unsafe fn lock(&self) {
92+
let mut guard = self.inner.lock();
93+
match guard.lock_var().owner {
94+
Some(tcs) if tcs != thread::current() => {
95+
// Another thread has the lock, wait
96+
WaitQueue::wait(guard);
97+
// Another thread has passed the lock to us
98+
},
99+
_ => {
100+
// We are just now obtaining the lock
101+
guard.lock_var_mut().owner = Some(thread::current());
102+
guard.lock_var_mut().count += 1;
103+
},
104+
}
105+
}
69106

70107
#[inline]
71-
pub unsafe fn try_lock(&self) -> bool {
72-
true
108+
pub unsafe fn unlock(&self) {
109+
let mut guard = self.inner.lock();
110+
if guard.lock_var().count > 1 {
111+
guard.lock_var_mut().count -= 1;
112+
} else {
113+
match WaitQueue::notify_one(guard) {
114+
Err(mut guard) => {
115+
// No other waiters, unlock
116+
guard.lock_var_mut().count = 0;
117+
guard.lock_var_mut().owner = None;
118+
},
119+
Ok(mut guard) => {
120+
// There was a thread waiting, just pass the lock
121+
if let NotifiedTcs::Single(tcs) = guard.notified_tcs() {
122+
guard.lock_var_mut().owner = Some(tcs)
123+
} else {
124+
unreachable!() // called notify_one
125+
}
126+
}
127+
}
128+
}
73129
}
74130

75-
pub unsafe fn unlock(&self) {}
131+
#[inline]
132+
pub unsafe fn try_lock(&self) -> bool {
133+
let mut guard = try_lock_or_false!(self.inner);
134+
match guard.lock_var().owner {
135+
Some(tcs) if tcs != thread::current() => {
136+
// Another thread has the lock
137+
false
138+
},
139+
_ => {
140+
// We are just now obtaining the lock
141+
guard.lock_var_mut().owner = Some(thread::current());
142+
guard.lock_var_mut().count += 1;
143+
true
144+
},
145+
}
146+
}
76147

148+
#[inline]
77149
pub unsafe fn destroy(&self) {}
78150
}

src/libstd/sys/sgx/os.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ pub fn env() -> Env {
9292
}
9393

9494
pub fn getenv(_k: &OsStr) -> io::Result<Option<OsString>> {
95-
unsupported()
95+
Ok(None)
9696
}
9797

9898
pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> {

0 commit comments

Comments
 (0)