[Lldb-commits] [lldb] Improving performance of multiple threads stepping over the same brea… (PR #180101)

via lldb-commits lldb-commits at lists.llvm.org
Thu Feb 12 10:18:51 PST 2026


================
@@ -589,14 +621,69 @@ bool ThreadList::WillResume(RunDirection &direction) {
           assert(thread_sp->GetCurrentPlan()->GetDirection() == direction);
           // You can't say "stop others" and also want yourself to be suspended.
           assert(thread_sp->GetCurrentPlan()->RunState() != eStateSuspended);
+
----------------
barsolo2000 wrote:

@jimingham , I might be wrong, but from my understanding, the flow of WillResume is:
1. Cleanup, we clear `m_threads_stepping_over_bp` and pop all existing `StepOverBreakpoint` plans. On the first cycle there are no plans yet. on later cycles, this pops leftover plans from threads that didn't finish their step in the previous cycle. we call SetReenableBreakpointsite() before each pop.
After this cleanup, no thread has a StepOverBreakpoint plan.

2. StopOthers scans: we scan for threads whose current plan has stopothers()=true. since we just popped all stepoverbreakpoint plans, these wont contibue here. the only way thread_to_run gets set in this scan is if some thread has non-breapoint stopothers plan. in our case, we shouldnt have a thread that has such plan, so thread_to_ryb remains nullptr and we fall to the else branch.

3. the else branch: 
we create the breakpoint_groups, loop through all the threads and call `SetupToStepOverBreakpointIfNeeded` on each one (line 617), this function checks if the thread is sitting on a bp that needs stepping over (we use `m_stopped_at_unexecuted_bp` which lives on the `thread`, not the plan, so it survives the pop). If we indeed need to step over, it pushes a new `StepOverBreakpoint` plan.

Immediately after `SetupToStepOverBreakpointIfNeeded` returns true,  we get the bp address via `GetBreakpointLoadAddress()` and group it in `breakpoint_groups[bp_addr].push_back(thread_sp);`. We also check `ShouldRunBeforePublicStop()` and set `found_run_before_public_stop` if found.

4. if no `found_run_before_public_stop` was found, we process the groups and if the group has more than 1 thread at the same breakpoint. we register each threads in `m_threads_stepping_over_bp` for tracking, set `SetDeferReenableBreakpointSite(true)` on each plan so re-enable goes through the callback instead of directly, and pick the largest group for batched_step_threads.

5. we get to `if (!batched_step_threads.empty())` if we have a batched vCont. Each thread in the batch calls `ShouldResume(eStateStepping)`, which triggers `DoWillResume` on its plan. That what disable the bp (one z0), all other threads get ShouldResume(eStateSuspeneded). The process sends a single batched vCont.

6.In later cycles: When the process stops again, some threads may have completed their step (plan pops, calls `ThreadFinishedSteppingOverBreakpoint` to decrement the tracking count) and some may not (plan stays on the stack). then willresume is called again, step 1 (from above) pops the leftover plans, and step 3 recreatess plans only for threads that still need to step (those whose `m_stopped_at_unexecuted_bp` hasn't been cleared), which creates a natual re-batching. 10->5->2->1 (for example). the bp stays disabled throughout all cycles, only the last thread finsihes does `ThreadFinishedSteppingOverBreakpoint` see an empty tracking set and sends the single Z0.

we call `SetupToStepOverBreakpointIfNeeded` both in the if statement (line 597) and in the else statement in line 617. 

again, I might be 100% WRONG and confused. so please, lmk if im mistaken


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


More information about the lldb-commits mailing list