MI threads behaviour

Vladimir Prus
2008-06-18T12:02:09Z

[-- Attachment #1: Type: text/plain, Size: 262 bytes --]

Here's the promised document about how I'd like threads to work in MI. It's not
fully implemented at this point, but I'd like to have some discussion before we
go on further. Anybody sees anything wrong or suboptimal about this proprosed
behaviour?

- Volodya

[-- Attachment #2: mi-threads.txt --]
[-- Type: text/plain, Size: 5110 bytes --]

Threads management in GDB
=========================

CLI interface
=============

In CLI mode, GDB maintains the current thread and current frame -- which
are specified by the user, with commands like 'thread', 'frame' and 'up/down'.
Most of the operation, such as printing variable values, work in context of
the current thread/frame. In all-stop mode, GDB will also implicitly switch
current thread/frame to the thread that has stopped. In non-stop mode, GDB
never automatically switches the thread.

It is possible that the current thread exits. In non-stop mode, GDB will
automatically reset the 'current thread' to an invalid value. Essentially
no commands are allowed after that, and user must switch to some still-alive
thread. In all-stop mode, GDB does not allow commands until it stops, and it does
not stop on thread exit. So, if a thread exits, GDB continues to execute the
program until an event in some other thread happens -- in which case it
switches to that other thread automatically. In
all-stop/sync/scheduler-locking-on mode the user will have to use Ctrl-C after
the current thread exits to stop some other thread.

MI interface
============

In MI mode, there are two current threads -- the current thread as shown in
UI, and the current thread from GDB point of view. The frontend should either
avoid relying on GDB current thread, or make sure to switch GDB current
thread as necessary. Also, we expect the frontend to notice when user requests
a change in current thread via a CLI command such as 'thread', or a
user-defined command, and update the UI current thread. There are two
possible approaches:

1. The recommended way is to use the --thread option for all MI
commands, and this makes the GDB current thread almost irrelevant.

GDB will have a new notification, =thread-selected, which is used to
report to the frontend that during processing of the last MI command,
GDB discovered user's request to change current thread to something.
Internally, this will be implemented by checking of the GDB current
thread has changed when we're done with processing MI command.
In all-stop mode, the notification will be emitted when any thread stops.

The CLI behaviour of setting GDB current thread to invalid value if the
current thread exits will be preserved, but is of limited value, since
the frontend does not depend on current thread directly, and will be notified
about thread exit anyway. Therefore, no notification will be emitted in
this case.

The notification will be emitted even if the thread user requested to be
selected is the same as currently selected thread. Imagine the frontend
has two windows open -- in one, UI has thread 1 selected, and in another,
UI has thread 2 selected. If user types "thread 2" in GDB console in the
first window, would expect the first window UI to switch to thread 2. So,
the notification should be emitted even if GDB current thread is 2,
already.

To summarize:
- With --thread option, frontend should not care at all about GDB's
current thread. There's no need to ever send -thread-select
- GDB will emit =thread-changed, and =frame-changes notification, which
should be interpred as saying "I think that user wants, via CLI,
to switch to this thread/frame"

2. The frontends not willing to upgrade to use the --thread option may use
-thread-select prior the sending the actual MI command, and optionally
-thread-select after the command.

In this case, the frontend should, in addition to maintaining current thread
as in UI, also remember which thread is current in GDB, and whenever sending
a command that should be executed in a thread different from the current GDB
thread, switch GDB to the desired thread. In particular, if sending several
commands at once, one of which can be CLI command, the frontend should be
prepared for the CLI command to change current thread. Frontend should never
ever send a command to GDB's pipe if it previously sent a CLI command and
haven't yet got its output back.

The =thread-selected notification, in this case, should be interpreted to
mean:
(1) User's request that the selected thread be changed, and
(2) Notification that GDB current thread has changed
The (2) trait does not matter if --thread is used, but in this case the
frontend need to use this information to figure if -thread-select should be
sent.

Note that conceptually, the --thread option is equivalent to -thread-select,
followed by the command, followed by -thread-select back to the original
thread (unless the command been executed changes thread itself), followed by
-stack-select-frame for old fram. The --thread option is allowed whenever
the -thread-select command is.

Threads and non-stop
====================

To simplify initial implementation, we allow *all* MI commands even if
inferiour is running. Furthermore, we don't care if the command tries to
work on a running thread. If the command requires that the thread be stopped,
it will error out, eventually. We don't try to pick a stopped thread and
execute the command there. For now, let's decide it's frontend problem.