[Lldb-commits] [lldb] Refactor `ThreadList::WillResume()` to prepare to support reverse execution (PR #120817)

Robert O'Callahan via lldb-commits lldb-commits at lists.llvm.org
Mon Jan 13 21:09:19 PST 2025


================
@@ -582,31 +531,92 @@ bool ThreadList::WillResume() {
   // There are two special kinds of thread that have priority for "StopOthers":
   // a "ShouldRunBeforePublicStop thread, or the currently selected thread.  If
   // we find one satisfying that critereon, put it here.
-  ThreadSP stop_others_thread_sp;
-
+  ThreadSP thread_to_run;
   for (pos = m_threads.begin(); pos != end; ++pos) {
     ThreadSP thread_sp(*pos);
     if (thread_sp->GetResumeState() != eStateSuspended &&
         thread_sp->GetCurrentPlan()->StopOthers()) {
-      if ((*pos)->IsOperatingSystemPluginThread() &&
-          !(*pos)->GetBackingThread())
+      if (thread_sp->IsOperatingSystemPluginThread() &&
+          !thread_sp->GetBackingThread())
         continue;
 
       // You can't say "stop others" and also want yourself to be suspended.
       assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
       run_me_only_list.AddThread(thread_sp);
 
       if (thread_sp == GetSelectedThread())
-        stop_others_thread_sp = thread_sp;
-        
+        thread_to_run = thread_sp;
+
       if (thread_sp->ShouldRunBeforePublicStop()) {
         // This takes precedence, so if we find one of these, service it:
-        stop_others_thread_sp = thread_sp;
+        thread_to_run = thread_sp;
         break;
       }
     }
   }
 
+  if (run_me_only_list.GetSize(false) > 0 && !thread_to_run) {
+    if (run_me_only_list.GetSize(false) == 1) {
+      thread_to_run = run_me_only_list.GetThreadAtIndex(0);
+    } else {
+      int random_thread =
+          (int)((run_me_only_list.GetSize(false) * (double)rand()) /
+                (RAND_MAX + 1.0));
+      thread_to_run = run_me_only_list.GetThreadAtIndex(random_thread);
+    }
+  }
+
+  // Give all the threads that are likely to run a last chance to set up their
+  // state before we negotiate who is actually going to get a chance to run...
+  // Don't set to resume suspended threads, and if any thread wanted to stop
+  // others, only call setup on the threads that request StopOthers...
+  bool wants_solo_run = run_me_only_list.GetSize(false) > 0;
+  for (pos = m_threads.begin(); pos != end; ++pos) {
+    ThreadSP thread_sp(*pos);
+    // See if any thread wants to run stopping others.  If it does, then we
+    // won't setup the other threads for resume, since they aren't going to get
+    // a chance to run.  This is necessary because the SetupForResume might add
+    // "StopOthers" plans which would then get to be part of the who-gets-to-run
+    // negotiation, but they're coming in after the fact, and the threads that
+    // are already set up should take priority.
+    if (thread_sp->GetResumeState() != eStateSuspended &&
+        (!wants_solo_run || (*pos)->GetCurrentPlan()->StopOthers())) {
+      if (thread_sp->IsOperatingSystemPluginThread() &&
+          !thread_sp->GetBackingThread())
+        continue;
+      if (thread_sp->SetupForResume()) {
+        // You can't say "stop others" and also want yourself to be suspended.
+        assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
+        run_me_only_list.AddThread(thread_sp);
----------------
rocallahan wrote:

>  you aren't going to add threads here that didn't get added in the first loop

This is not actually true. Threads not in `run_me_only_list` can return true for `SetupForResume()` and be added to the list for the first time here. However, it's certainly a problem that threads can be added to the list twice, and it's confusing because later it only matters whether the list is non-empty or not. I've fixed this now: instead of adding threads to the list, we just set `thread_to_run` and later test whether `thread_to_run` is null to determine if we're running a single thread or not.

https://github.com/llvm/llvm-project/pull/120817


More information about the lldb-commits mailing list