[PATCH 1/4] gdb: make remote target track resumed but no vCont-resumed threads
Simon Marchi
simon.marchi@polymtl.ca
Thu Dec 24 18:04:39 GMT 2020
On 2020-12-23 7:09 p.m., Andrew Burgess wrote:
> * Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> [2020-12-23 17:40:25 -0500]:
>
>> From: Simon Marchi <simon.marchi@efficios.com>
>>
>> The next patch moves the target commit_resume method to be a
>> process_stratum_target-only method. The only non-process targets that
>> currently implement the commit_resume method are the btrace and full
>> record targets. The only reason they need to do so is to prevent a
>> commit resume from reaching the beneath (process) target if they are
>> currently replaying.
>>
>> This is important if a record target is used on top of the remote target
>> (the only process target implementing the commit_resume method).
>> Currently, the remote target checks the `thread_info::executing` flag of
>> a thread to know if it should commit resume that thread:
>>
>> if (!tp->executing || remote_thr->vcont_resumed)
>> continue;
>>
>> The `tp->executing` flag is set by infrun when it has asked the target
>> stack to resume the thread, and therefore if the thread is executing
>> from its point of view. It _not_ equivalent to whether the remote
>> target was asked to resume this thread.
>>
>> Indeed, if infrun asks the target stack to resume some thread while the
>> record target is replaying, the record target won't forward the resume
>> request the remote target beneath, because we don't actually want to
>> resume the thread on the execution target. But the `tp->executing` flag
>> is still set, because from the point of view of infrun, the thread
>> executes. So, if the commit_resume call wasn't intercepted by the
>> record target and did reach the remote target, the remote target would
>> say "Oh, this thread should be executing and I haven't vCont-resumed it!
>> I must vCont-resume it!". But that would be wrong, because it was never
>> asked to resume this thread, the resume request did not reach it. This
>> is why the record targets currently need to implement commit_resume: to
>> prevent the beneath target from commit_resuming threads it wasn't asked
>> to resume.
>>
>> Since commit_resume will become a method on process_stratum_target in
>> the following patch, record targets won't have a chance to intercept the
>> calls and that would result in the remote target commit_resuming threads
>> it shouldn't. To avoid this, this patch makes the remote target track
>> its own thread resumption state. That means, tracking which threads it
>> was asked to resume via target_ops::resume. Regardless of the context
>> of this patch, I think this change makes it easier to understand how
>> resume / commit_resume works in the remote target. It makes the target
>> more self-contained, as it only depends on what it gets asked to do via
>> the target methods, and not on tp->executing, which is a flag maintained
>> from the point of view of infrun.
>>
>> From the point of view of the remote target, there are three states a
>> thread can be in:
>>
>> 1. not resumed
>> 2. resumed but pending vCont-resume
>> 3. resumed and already vCont-resumed
>>
>> As of this patch, valid state transitions are:
>>
>> - 1 -> 2 (through the target resume method)
>> - 2 -> 3 (through the target commit_resume method)
>> - 3 -> 1 (through a remote stop notification / reporting an event to the
>> event loop)
>>
>> A subsequent patch will make it possible to go from 2 to 1, in case
>> infrun asks to stop a thread that was resumed but not commit-resumed
>> yet, but I don't think it can happen as of now.
>>
>> In terms of code, this patch replaces the vcont_resumed field with an
>> enumeration that explicitly represents the three states described above.
>> The last_resume_sig and last_resume_step fields are moved to a structure
>> which is clearly identified as only used when the thread is in the
>> "resumed but pending vCont-resume" state.
>
> If I understand this patch correctly, this new state tracking only
> applies for the commit_resume use case, which is only used in a
> specific set of modes?
>
> I ask because of this patch:
>
> https://sourceware.org/pipermail/gdb-patches/2020-December/174277.html
>
> in which I propose adding a new check of the thread->executing flag.
>
> If I understand this correctly then I don't think the new state
> tracking would actually help my case, right?
Indeed, this new state tracking only applies when the remote target
operates in non-stop mode.
The tp->executing check you add is probably fine, because in practice,
if you have a record target on top of the remote target, I don't think
you can have some threads being replayed and some threads executing
for real. And if you receive a stop reply, it's because you had
something executing for real. So you won't fall into the case where
tp->executing is true, but the thread isn't resumed on the remote target.
However, it's perhaps confusing that the remote target uses this new
state tracking, but only in non-stop mode. And it would be confusing if
in some places, to check whether a thread is running, we check
tp->executing, and in other places we check remote_thread->resumed_state.
It would be much nicer if the remote target could always trust
remote_thread->resumed_state.
So perhaps the thread's resume state should be tracked by the remote
target in all modes. The enum would be:
enum class resume_state
{
/* Not resumed - we haven't been asked to resume this thread. */
NOT_RESUMED,
/* We have been asked to resume this thread, but haven't sent a vCont action
for it yet. We'll need to consider it next time commit_resume is
called. This state is only used when the remote target is in non-stop
mode. */
RESUMED_PENDING_VCONT,
/* Fully resumed. */
RESUMED,
};
In all-stop, threads would go from NOT_RESUMED to RESUMED directly. In
non-stop, they would go through the intermediary RESUMED_PENDING_VCONT
state. With this, your patch could check whether
remote_thread->resume_state is resume_state::RESUMED.
I haven't read the explanation in your patch completely though, so take
that with a grain of salt.
>
> Also I spotted a typo, see below.
>
> Thanks,
> Andrew
>
>>
>> gdb/ChangeLog:
>>
>> * remote.c (enum class resume_state): New.
>> (struct pending_vcont_resume_info): New.
>> (struct remote_thread_info) <resume_state, set_not_resumed,
>> set_pending_vcont_resume, pending_vcont_resume_info,
>> set_vcont_resumed, m_resume_state, m_pending_vcont_resume_info>:
>> New.
>> <last_resume_step, last_resume_sig, vcont_resumed>: Remove.
>> (remote_target::remote_add_thread): Adjust.
>> (remote_target::process_initial_stop_replies): Adjust.
>> (remote_target::resume): Adjust.
>> (remote_target::commit_resume): Rely on state in
>> remote_thread_info and not on tp->executing.
>> (remote_target::process_stop_reply): Adjust.
>>
>> Change-Id: I10480919ccb4552faa62575e447a36dbe7c2d523
>> ---
>> gdb/remote.c | 151 +++++++++++++++++++++++++++++++++++++++------------
>> 1 file changed, 115 insertions(+), 36 deletions(-)
>>
>> diff --git a/gdb/remote.c b/gdb/remote.c
>> index 71f814efb365..1b5e5f5727b3 100644
>> --- a/gdb/remote.c
>> +++ b/gdb/remote.c
>> @@ -1050,6 +1050,38 @@ static struct cmd_list_element *remote_show_cmdlist;
>>
>> static bool use_range_stepping = true;
>>
>> +/* From the remote target's point of view, each thread is in one of these three
>> + states. */
>> +enum class resume_state
>> +{
>> + /* Not resumed - we haven't been asked to resume this thread. */
>> + NOT_RESUMED,
>> +
>> + /* We have been asked to resume this thread, but haven't sent a vCont action
>> + for it yet. We'll need to consider it next time commit_resume is
>> + called. */
>> + PENDING_VCONT_RESUME,
>> +
>> + /* We have been asked to resume this thread, and we have sent a vCont action
>> + for it. */
>> + VCONT_RESUMED,
>> +};
>> +
>> +/* Information about a thread's pending vCont-resume. Used when a thread is in
>> + the remote_resume_state::PENDING_VCONT_RESUME state. remote_target::resume
>> + stores this information which is them picked up by
>> + remote_target::commit_resume to know which is the propert action for this
>
> Typo 'propert' ?
Fixed to "proper", thanks.
Simon
More information about the Gdb-patches
mailing list