Hi everyone,
I am sending a 3 patch series to address the concerns, Thank you very much for the review. Here are my thoughts.
>> per step when program has atleast 3 or more threads running. A simple
>> walk through a function took around a minute. In compiler codes this is
>> slow.
>>
>> TO measure this properly I wrote a benchmark pasted below. The program spawns
>> 20 worker threads , then stops inside a function with 10 simple
>> that GDB steps over one by one. The GDB batch script breaks at that
>Seems to be missing a word after "simple". Statements?
Made the corrections.
>> None of this work is wrong but it is needed when threads actually come
>> and go. But during a next or step sequence through a function, the
>> thread list does not change. Paying for a full rescan on every stop is
>> something not needed I think.
>I mean, it *could* change, you could do "next" over a function that
>spawns a thread, a background thread (one other than the one you step)
>could spawn a thread, another thread could have exited, etc.
Yes, in the v3 version I have handle this.
GDB resumes all threads (to let the callee execute), using ptid.tid()
== 0. That path in
resume()
sets last_resume_step = 0.
So when the return-address breakpoint fires, step_stop
= false and the full sync runs and any new thread is caught.
>It's unrelated to this patch, but I happen to be looking at aix-thread.c
>because of it and I must ask if these things are still relevant, given
>the AIX versions and configurations you support nowadays:
The first patch in the coming series addresses these. Thanks for pointing out.
>Ulrich already pointed out that you could have one thread appear and one
>disappear, and the count will not change.
Yes, this is something I did not think. Thanks to both of you. The v3 patch implementation is based on single step only. No thread counts used.
>So yeah, what about doing "next" over a call that spawns a thread, or a
>background thread existing while you do a next?
The fix is safe for both scenarios because
step_stop=true
is only set when software single-step breakpoints were inserted for the resumed thread which means GDB knows the thread executed exactly one instruction and could not have called
pthread_create
or pthread_exit.
For next
over a function call that spawns a thread, GDB resumes all threads (ptid.tid()==0),
which explicitly clears last_resume_step=0
at line 1087, so step_stop
is never true and sync_threadlists()
runs in full, picking up the new thread. For a background thread exiting during
next,
the single-step skips only apply to the internal one-instruction steps of the stepped thread; as soon as GDB resumes all threads for the next source-line boundary it clears
last_resume_step=0,
so the following stop calls sync_threadlists()
and detects the exit. In both cases sync_threadlists()
is always called on any stop where thread population could have changed. The optimization only fires for stops that are pure single-step traps of a single thread. No new thread can be created or destroyed in one instruction, so skipping the session update
on those stops is correct. This is what my thought process is.
>> +/* Number of thread descriptors to fetch per getthrds() call. The original
>> + code fetched one at a time, which costs one syscall per thread. Fetching
>> + in batches reduces that to one syscall per GETTHRDS_BATCH threads. */
>No need to document what the original code did. Just keep the first
>sentence.
Sure, corrected the same in second patch of the coming series.
>> +#define GETTHRDS_BATCH 64
>Prefer:
>constexpr int GETTHRDS_BATCH = 64;
Done this in v3 version of the patch.
>> +
>> /* Search through the list of all kernel threads for the thread
>> that has stopped on a SIGTRAP signal, and return its TID.
>> Return 0 if none found. */
>This predates your patch, but is the comment for the get_signaled_thread
>function accurate? It says it looks for a thread that has stopped on a
>SIGTRAP signal, but the implementation seems to look for any signal, not
>just SIGTRAP.
I have corrected this.
>> - while (1)
>> + while ((count = getthrds (pid, thrinf, sizeof (thrinf[0]),
>> + &ktid, GETTHRDS_BATCH)) > 0)
>>Prefer declaring the variable in the while statement, and separating the
>>comparison from the assignment. This should work:
>> while (int count = getthrds (pid, thrinf, sizeof (thrinf[0]), &ktid,
>> GETTHRDS_BATCH));
>> count > 0)
>> {
>> + for (i = 0; i < count; i++)
>> + if (thrinf[i].ti_cursig)
>> + return thrinf[i].ti_tid;
>Declare variable `i` in the for loop.
The above two are addressed in v3 version of this patch. Simon, that works with for loop and not with while.
Have a nice day ahead.
Thanks and regards,
Aditya.