| 108 | /// Called automatically by enter_vm(). |
| 109 | #[cfg(feature = "threading")] |
| 110 | fn init_thread_slot_if_needed(vm: &VirtualMachine) { |
| 111 | CURRENT_THREAD_SLOT.with(|slot| { |
| 112 | if slot.borrow().is_none() { |
| 113 | let thread_id = crate::stdlib::_thread::get_ident(); |
| 114 | let mut registry = vm.state.thread_frames.lock(); |
| 115 | let new_slot = Arc::new(ThreadSlot { |
| 116 | frames: parking_lot::Mutex::new(Vec::new()), |
| 117 | exception: crate::PyAtomicRef::from(None::<PyBaseExceptionRef>), |
| 118 | #[cfg(unix)] |
| 119 | state: core::sync::atomic::AtomicI32::new( |
| 120 | if vm.state.stop_the_world.requested.load(Ordering::Acquire) { |
| 121 | // Match init_threadstate(): new thread-state starts |
| 122 | // suspended while stop-the-world is active. |
| 123 | THREAD_SUSPENDED |
| 124 | } else { |
| 125 | THREAD_DETACHED |
| 126 | }, |
| 127 | ), |
| 128 | #[cfg(unix)] |
| 129 | stop_requested: core::sync::atomic::AtomicBool::new(false), |
| 130 | #[cfg(unix)] |
| 131 | thread: std::thread::current(), |
| 132 | }); |
| 133 | registry.insert(thread_id, new_slot.clone()); |
| 134 | drop(registry); |
| 135 | *slot.borrow_mut() = Some(new_slot); |
| 136 | } |
| 137 | }); |
| 138 | } |
| 139 | |
| 140 | /// Transition DETACHED → ATTACHED. Blocks if the thread was SUSPENDED by |
| 141 | /// a stop-the-world request (like `_PyThreadState_Attach` + `tstate_wait_attach`). |