2019-02-11 04:23:21 +09:00
|
|
|
use crate::ffi::CStr;
|
|
|
|
|
use crate::io;
|
|
|
|
|
use crate::sys::{unsupported, Void};
|
|
|
|
|
use crate::time::Duration;
|
2017-10-22 20:01:00 -07:00
|
|
|
|
|
|
|
|
pub struct Thread(Void);
|
|
|
|
|
|
|
|
|
|
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
|
|
|
|
|
|
|
|
|
|
impl Thread {
|
2018-11-30 10:39:12 +05:30
|
|
|
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
|
2019-04-10 00:46:28 +08:00
|
|
|
pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
|
2017-10-22 20:01:00 -07:00
|
|
|
-> io::Result<Thread>
|
|
|
|
|
{
|
|
|
|
|
unsupported()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn yield_now() {
|
|
|
|
|
// do nothing
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn set_name(_name: &CStr) {
|
|
|
|
|
// nope
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-15 10:51:24 -07:00
|
|
|
#[cfg(not(target_feature = "atomics"))]
|
2017-10-22 20:01:00 -07:00
|
|
|
pub fn sleep(_dur: Duration) {
|
|
|
|
|
panic!("can't sleep");
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-15 10:51:24 -07:00
|
|
|
#[cfg(target_feature = "atomics")]
|
|
|
|
|
pub fn sleep(dur: Duration) {
|
2019-02-11 04:23:21 +09:00
|
|
|
use crate::arch::wasm32;
|
|
|
|
|
use crate::cmp;
|
2018-08-15 10:51:24 -07:00
|
|
|
|
|
|
|
|
// Use an atomic wait to block the current thread artificially with a
|
|
|
|
|
// timeout listed. Note that we should never be notified (return value
|
|
|
|
|
// of 0) or our comparison should never fail (return value of 1) so we
|
|
|
|
|
// should always only resume execution through a timeout (return value
|
|
|
|
|
// 2).
|
|
|
|
|
let mut nanos = dur.as_nanos();
|
|
|
|
|
while nanos > 0 {
|
|
|
|
|
let amt = cmp::min(i64::max_value() as u128, nanos);
|
|
|
|
|
let mut x = 0;
|
2018-12-17 12:06:06 -08:00
|
|
|
let val = unsafe { wasm32::i32_atomic_wait(&mut x, 0, amt as i64) };
|
2018-08-15 10:51:24 -07:00
|
|
|
debug_assert_eq!(val, 2);
|
|
|
|
|
nanos -= amt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-22 20:01:00 -07:00
|
|
|
pub fn join(self) {
|
|
|
|
|
match self.0 {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub mod guard {
|
Use a range to identify SIGSEGV in stack guards
Previously, the `guard::init()` and `guard::current()` functions were
returning a `usize` address representing the top of the stack guard,
respectively for the main thread and for spawned threads. The `SIGSEGV`
handler on `unix` targets checked if a fault was within one page below
that address, if so reporting it as a stack overflow.
Now `unix` targets report a `Range<usize>` representing the guard
memory, so it can cover arbitrary guard sizes. Non-`unix` targets which
always return `None` for guards now do so with `Option<!>`, so they
don't pay any overhead.
For `linux-gnu` in particular, the previous guard upper-bound was
`stackaddr + guardsize`, as the protected memory was *inside* the stack.
This was a glibc bug, and starting from 2.27 they are moving the guard
*past* the end of the stack. However, there's no simple way for us to
know where the guard page actually lies, so now we declare it as the
whole range of `stackaddr ± guardsize`, and any fault therein will be
called a stack overflow. This fixes #47863.
2018-01-31 11:41:29 -08:00
|
|
|
pub type Guard = !;
|
|
|
|
|
pub unsafe fn current() -> Option<Guard> { None }
|
|
|
|
|
pub unsafe fn init() -> Option<Guard> { None }
|
2017-10-22 20:01:00 -07:00
|
|
|
}
|
std: Implement TLS for wasm32-unknown-unknown
This adds an implementation of thread local storage for the
`wasm32-unknown-unknown` target when the `atomics` feature is
implemented. This, however, comes with a notable caveat of that it
requires a new feature of the standard library, `wasm-bindgen-threads`,
to be enabled.
Thread local storage for wasm (when `atomics` are enabled and there's
actually more than one thread) is powered by the assumption that an
external entity can fill in some information for us. It's not currently
clear who will fill in this information nor whose responsibility it
should be long-term. In the meantime there's a strategy being gamed out
in the `wasm-bindgen` project specifically, and the hope is that we can
continue to test and iterate on the standard library without committing
to a particular strategy yet.
As to the details of `wasm-bindgen`'s strategy, LLVM doesn't currently
have the ability to emit custom `global` values (thread locals in a
`WebAssembly.Module`) so we leverage the `wasm-bindgen` CLI tool to do
it for us. To that end we have a few intrinsics, assuming two global values:
* `__wbindgen_current_id` - gets the current thread id as a 32-bit
integer. It's `wasm-bindgen`'s responsibility to initialize this
per-thread and then inform libstd of the id. Currently `wasm-bindgen`
performs this initialization as part of the `start` function.
* `__wbindgen_tcb_{get,set}` - in addition to a thread id it's assumed
that there's a global available for simply storing a pointer's worth
of information (a thread control block, which currently only contains
thread local storage). This would ideally be a native `global`
injected by LLVM, but we don't have a great way to support that right
now.
To reiterate, this is all intended to be unstable and purely intended
for testing out Rust on the web with threads. The story is very likely
to change in the future and we want to make sure that we're able to do
that!
2018-10-09 23:10:25 -07:00
|
|
|
|
2019-06-10 08:12:14 -07:00
|
|
|
cfg_if::cfg_if! {
|
std: Implement TLS for wasm32-unknown-unknown
This adds an implementation of thread local storage for the
`wasm32-unknown-unknown` target when the `atomics` feature is
implemented. This, however, comes with a notable caveat of that it
requires a new feature of the standard library, `wasm-bindgen-threads`,
to be enabled.
Thread local storage for wasm (when `atomics` are enabled and there's
actually more than one thread) is powered by the assumption that an
external entity can fill in some information for us. It's not currently
clear who will fill in this information nor whose responsibility it
should be long-term. In the meantime there's a strategy being gamed out
in the `wasm-bindgen` project specifically, and the hope is that we can
continue to test and iterate on the standard library without committing
to a particular strategy yet.
As to the details of `wasm-bindgen`'s strategy, LLVM doesn't currently
have the ability to emit custom `global` values (thread locals in a
`WebAssembly.Module`) so we leverage the `wasm-bindgen` CLI tool to do
it for us. To that end we have a few intrinsics, assuming two global values:
* `__wbindgen_current_id` - gets the current thread id as a 32-bit
integer. It's `wasm-bindgen`'s responsibility to initialize this
per-thread and then inform libstd of the id. Currently `wasm-bindgen`
performs this initialization as part of the `start` function.
* `__wbindgen_tcb_{get,set}` - in addition to a thread id it's assumed
that there's a global available for simply storing a pointer's worth
of information (a thread control block, which currently only contains
thread local storage). This would ideally be a native `global`
injected by LLVM, but we don't have a great way to support that right
now.
To reiterate, this is all intended to be unstable and purely intended
for testing out Rust on the web with threads. The story is very likely
to change in the future and we want to make sure that we're able to do
that!
2018-10-09 23:10:25 -07:00
|
|
|
if #[cfg(all(target_feature = "atomics", feature = "wasm-bindgen-threads"))] {
|
|
|
|
|
#[link(wasm_import_module = "__wbindgen_thread_xform__")]
|
|
|
|
|
extern {
|
|
|
|
|
fn __wbindgen_current_id() -> u32;
|
|
|
|
|
fn __wbindgen_tcb_get() -> u32;
|
|
|
|
|
fn __wbindgen_tcb_set(ptr: u32);
|
|
|
|
|
}
|
|
|
|
|
pub fn my_id() -> u32 {
|
|
|
|
|
unsafe { __wbindgen_current_id() }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These are currently only ever used in `thread_local_atomics.rs`, if
|
|
|
|
|
// you'd like to use them be sure to update that and make sure everyone
|
|
|
|
|
// agrees what's what.
|
|
|
|
|
pub fn tcb_get() -> *mut u8 {
|
2019-02-11 04:23:21 +09:00
|
|
|
use crate::mem;
|
std: Implement TLS for wasm32-unknown-unknown
This adds an implementation of thread local storage for the
`wasm32-unknown-unknown` target when the `atomics` feature is
implemented. This, however, comes with a notable caveat of that it
requires a new feature of the standard library, `wasm-bindgen-threads`,
to be enabled.
Thread local storage for wasm (when `atomics` are enabled and there's
actually more than one thread) is powered by the assumption that an
external entity can fill in some information for us. It's not currently
clear who will fill in this information nor whose responsibility it
should be long-term. In the meantime there's a strategy being gamed out
in the `wasm-bindgen` project specifically, and the hope is that we can
continue to test and iterate on the standard library without committing
to a particular strategy yet.
As to the details of `wasm-bindgen`'s strategy, LLVM doesn't currently
have the ability to emit custom `global` values (thread locals in a
`WebAssembly.Module`) so we leverage the `wasm-bindgen` CLI tool to do
it for us. To that end we have a few intrinsics, assuming two global values:
* `__wbindgen_current_id` - gets the current thread id as a 32-bit
integer. It's `wasm-bindgen`'s responsibility to initialize this
per-thread and then inform libstd of the id. Currently `wasm-bindgen`
performs this initialization as part of the `start` function.
* `__wbindgen_tcb_{get,set}` - in addition to a thread id it's assumed
that there's a global available for simply storing a pointer's worth
of information (a thread control block, which currently only contains
thread local storage). This would ideally be a native `global`
injected by LLVM, but we don't have a great way to support that right
now.
To reiterate, this is all intended to be unstable and purely intended
for testing out Rust on the web with threads. The story is very likely
to change in the future and we want to make sure that we're able to do
that!
2018-10-09 23:10:25 -07:00
|
|
|
assert_eq!(mem::size_of::<*mut u8>(), mem::size_of::<u32>());
|
|
|
|
|
unsafe { __wbindgen_tcb_get() as *mut u8 }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn tcb_set(ptr: *mut u8) {
|
|
|
|
|
unsafe { __wbindgen_tcb_set(ptr as u32); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FIXME: still need something for hooking exiting a thread to free
|
|
|
|
|
// data...
|
|
|
|
|
|
|
|
|
|
} else if #[cfg(target_feature = "atomics")] {
|
|
|
|
|
pub fn my_id() -> u32 {
|
|
|
|
|
panic!("thread ids not implemented on wasm with atomics yet")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn tcb_get() -> *mut u8 {
|
|
|
|
|
panic!("thread local data not implemented on wasm with atomics yet")
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-17 12:06:06 -08:00
|
|
|
pub fn tcb_set(_ptr: *mut u8) {
|
std: Implement TLS for wasm32-unknown-unknown
This adds an implementation of thread local storage for the
`wasm32-unknown-unknown` target when the `atomics` feature is
implemented. This, however, comes with a notable caveat of that it
requires a new feature of the standard library, `wasm-bindgen-threads`,
to be enabled.
Thread local storage for wasm (when `atomics` are enabled and there's
actually more than one thread) is powered by the assumption that an
external entity can fill in some information for us. It's not currently
clear who will fill in this information nor whose responsibility it
should be long-term. In the meantime there's a strategy being gamed out
in the `wasm-bindgen` project specifically, and the hope is that we can
continue to test and iterate on the standard library without committing
to a particular strategy yet.
As to the details of `wasm-bindgen`'s strategy, LLVM doesn't currently
have the ability to emit custom `global` values (thread locals in a
`WebAssembly.Module`) so we leverage the `wasm-bindgen` CLI tool to do
it for us. To that end we have a few intrinsics, assuming two global values:
* `__wbindgen_current_id` - gets the current thread id as a 32-bit
integer. It's `wasm-bindgen`'s responsibility to initialize this
per-thread and then inform libstd of the id. Currently `wasm-bindgen`
performs this initialization as part of the `start` function.
* `__wbindgen_tcb_{get,set}` - in addition to a thread id it's assumed
that there's a global available for simply storing a pointer's worth
of information (a thread control block, which currently only contains
thread local storage). This would ideally be a native `global`
injected by LLVM, but we don't have a great way to support that right
now.
To reiterate, this is all intended to be unstable and purely intended
for testing out Rust on the web with threads. The story is very likely
to change in the future and we want to make sure that we're able to do
that!
2018-10-09 23:10:25 -07:00
|
|
|
panic!("thread local data not implemented on wasm with atomics yet")
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// stubbed out because no functions actually access these intrinsics
|
|
|
|
|
// unless atomics are enabled
|
|
|
|
|
}
|
|
|
|
|
}
|