+ /// Wakes up threads joining on the active one and deallocates thread-local statics.
+ /// The `AllocId` that can now be freed is returned.
+ fn thread_terminated(
+ &mut self,
+ data_race: &Option<Rc<data_race::GlobalState>>,
+ ) -> Vec<AllocId> {
+ let mut free_tls_statics = Vec::new();
+ {
+ let mut thread_local_statics = self.thread_local_alloc_ids.borrow_mut();
+ thread_local_statics.retain(|&(_def_id, thread), &mut alloc_id| {
+ if thread != self.active_thread {
+ // Keep this static around.
+ return true;
+ }
+ // Delete this static from the map and from memory.
+ // We cannot free directly here as we cannot use `?` in this context.
+ free_tls_statics.push(alloc_id);
+ return false;
+ });
+ }
+ // Set the thread into a terminated state in the data-race detector
+ if let Some(data_race) = data_race {
+ data_race.thread_terminated();
+ }
+ // Check if we need to unblock any threads.
+ for (i, thread) in self.threads.iter_enumerated_mut() {
+ if thread.state == ThreadState::BlockedOnJoin(self.active_thread) {
+ // The thread has terminated, mark happens-before edge to joining thread
+ if let Some(data_race) = data_race {
+ data_race.thread_joined(i, self.active_thread);
+ }
+ trace!("unblocking {:?} because {:?} terminated", i, self.active_thread);
+ thread.state = ThreadState::Enabled;
+ }
+ }
+ return free_tls_statics;
+ }
+