================ @@ -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); ---------------- jimingham wrote:
And anyway, if wants_solo_run is false, you end up adding every thread that needs to step over a breakpoint to the run_me_only list, but then don't do anything with any of them. https://github.com/llvm/llvm-project/pull/120817 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits