|
1 | 1 | #![allow(dead_code)] // stack_guard isn't used right now on all platforms |
2 | | -#![allow(unused_unsafe)] // thread_local with `const {}` triggers this liny |
3 | 2 |
|
4 | | -use crate::cell::RefCell; |
| 3 | +use crate::cell::Cell; |
5 | 4 | use crate::sys::thread::guard::Guard; |
6 | 5 | use crate::thread::Thread; |
7 | 6 |
|
8 | | -struct ThreadInfo { |
9 | | - stack_guard: Option<Guard>, |
10 | | - thread: Thread, |
11 | | -} |
12 | | - |
13 | | -thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = const { RefCell::new(None) } } |
14 | | - |
15 | | -impl ThreadInfo { |
16 | | - fn with<R, F>(f: F) -> Option<R> |
17 | | - where |
18 | | - F: FnOnce(&mut ThreadInfo) -> R, |
19 | | - { |
20 | | - THREAD_INFO |
21 | | - .try_with(move |thread_info| { |
22 | | - let mut thread_info = thread_info.borrow_mut(); |
23 | | - let thread_info = thread_info.get_or_insert_with(|| ThreadInfo { |
24 | | - stack_guard: None, |
25 | | - thread: Thread::new(None), |
26 | | - }); |
27 | | - f(thread_info) |
28 | | - }) |
29 | | - .ok() |
30 | | - } |
| 7 | +thread_local! { |
| 8 | + static THREAD: Cell<Option<Thread>> = const { Cell::new(None) }; |
| 9 | + // Use a separate thread local for the stack guard page location. |
| 10 | + // Since `Guard` does not implement drop, this is always available |
| 11 | + // on systems with ELF-TLS, in particular during TLS destruction. |
| 12 | + static STACK_GUARD: Cell<Option<Guard>> = const { Cell::new(None) }; |
31 | 13 | } |
32 | 14 |
|
33 | 15 | pub fn current_thread() -> Option<Thread> { |
34 | | - ThreadInfo::with(|info| info.thread.clone()) |
| 16 | + THREAD |
| 17 | + .try_with(|thread| { |
| 18 | + let t = thread.take().unwrap_or_else(|| Thread::new(None)); |
| 19 | + let t2 = t.clone(); |
| 20 | + thread.set(Some(t)); |
| 21 | + t2 |
| 22 | + }) |
| 23 | + .ok() |
35 | 24 | } |
36 | 25 |
|
37 | 26 | pub fn stack_guard() -> Option<Guard> { |
38 | | - ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o) |
| 27 | + STACK_GUARD |
| 28 | + .try_with(|guard| { |
| 29 | + let g = guard.take(); |
| 30 | + let g2 = g.clone(); |
| 31 | + guard.set(g); |
| 32 | + g2 |
| 33 | + }) |
| 34 | + .ok() |
| 35 | + .flatten() |
39 | 36 | } |
40 | 37 |
|
41 | 38 | pub fn set(stack_guard: Option<Guard>, thread: Thread) { |
42 | | - THREAD_INFO.with(move |thread_info| { |
43 | | - let mut thread_info = thread_info.borrow_mut(); |
44 | | - rtassert!(thread_info.is_none()); |
45 | | - *thread_info = Some(ThreadInfo { stack_guard, thread }); |
46 | | - }); |
| 39 | + rtassert!(STACK_GUARD.replace(stack_guard).is_none()); |
| 40 | + rtassert!(THREAD.replace(Some(thread)).is_none()); |
47 | 41 | } |
0 commit comments