+impl<'mir, 'tcx: 'mir> EvalContextPrivExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
+trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
+ /// Schedule TLS destructors for the main thread on Windows. The
+ /// implementation assumes that we do not support concurrency on Windows
+ /// yet.
+ fn schedule_windows_tls_dtors(&mut self) -> InterpResult<'tcx> {
+ let this = self.eval_context_mut();
+ let active_thread = this.get_active_thread();
+ assert_eq!(this.get_total_thread_count(), 1, "concurrency on Windows is not supported");
+ // Windows has a special magic linker section that is run on certain events.
+ // Instead of searching for that section and supporting arbitrary hooks in there
+ // (that would be basically https://github.com/rust-lang/miri/issues/450),
+ // we specifically look up the static in libstd that we know is placed
+ // in that section.
+ let thread_callback = this.eval_path_scalar(&["std", "sys", "windows", "thread_local_key", "p_thread_callback"])?;
+ let thread_callback = this.memory.get_fn(thread_callback.check_init()?)?.as_instance()?;
+
+ // The signature of this function is `unsafe extern "system" fn(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID)`.
+ let reason = this.eval_path_scalar(&["std", "sys", "windows", "c", "DLL_THREAD_DETACH"])?;
+ let ret_place = MPlaceTy::dangling(this.machine.layouts.unit, this).into();
+ this.call_function(
+ thread_callback,
+ Abi::System { unwind: false },
+ &[Scalar::null_ptr(this).into(), reason.into(), Scalar::null_ptr(this).into()],
+ Some(&ret_place),
+ StackPopCleanup::None { cleanup: true },
+ )?;
+
+ this.enable_thread(active_thread);
+ Ok(())
+ }
+
+ /// Schedule the MacOS thread destructor of the thread local storage to be
+ /// executed. Returns `true` if scheduled.
+ ///
+ /// Note: It is safe to call this function also on other Unixes.
+ fn schedule_macos_tls_dtor(&mut self) -> InterpResult<'tcx, bool> {