|
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