From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27721 invoked by alias); 18 Mar 2008 21:16:35 -0000 Received: (qmail 27547 invoked by uid 22791); 18 Mar 2008 21:16:33 -0000 X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 18 Mar 2008 21:16:04 +0000 Received: (qmail 23889 invoked from network); 18 Mar 2008 21:16:02 -0000 Received: from unknown (HELO localhost) (vladimir@127.0.0.2) by mail.codesourcery.com with ESMTPA; 18 Mar 2008 21:16:02 -0000 From: Vladimir Prus To: gdb@sources.redhat.com Subject: MI non-stop mode spec Date: Wed, 19 Mar 2008 02:49:00 -0000 User-Agent: KMail/1.9.6 (enterprise 0.20070907.709405) MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200803190016.02072.vladimir@codesourcery.com> Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2008-03/txt/msg00148.txt.bz2 Making good used of GDB in async mode, and especially in async non-stop mode demands some changes in MI -- both general clarifications, and actual work to allow most MI commands while the target is running and define their behaviour. I propose the changes as below. Please view this document as spec of how MI should ideally operate. In the cases where MI currently operates differently, there may be various transition plans, including deciding that current frontends won't be affected by change anyway, allowing earlier behaviour with a big warning in MI docs, or bumping MI version and implementing new behaviour only for MI3. This spec does not deal with such compatibility issues -- only with ideal MI behaviour. MI command details ================== Legend: (*) Changes from current MI behaviour. (**) Changes from original non-stop mode proposal in http://sourceware.org/ml/gdb/2007-11/msg00198.html -> Todo items General clarifications ---------------------- When operating in MI mode, gdb prints a prompt if and only if it is ready to immediately read and process the next command. Of course, a frontend can send a command without waiting for the prompt, and it will be eventually processed. However, if gdb has not printed a prompt after the previous command yet, it means that it might take a lot time until the next command will be executed. The frontend may use the lack of prompt to disable some commands, or to show "waiting for previous command to finish" indicator. (*) Current MI syntax says that any result record must be followed by a prompt. For sync targets, this is wrong -- when gdb prints ^running and resumes the target, it does not check for input, so (gdb) is misleading. When the target stops, the *stopped message, followed by the prompt is printed -- and it's at this point that gdb starts to accept the input again. So, I propose to remove the prompt right after ^running for the sync targets. Each MI command results in either ^done, ^error, ^connected or ^running response. The ^connected response is basically identical to ^done, and the naming is different for historic reasons. All of those except for ^running are immediately followed by prompt. The ^running response means that the target has started running. Further events from the target will be reported using async notifications. The async notifications are for various interesting events that cannot generally be reported as result of a command. For example, =thread-created is emitted whenever a new thread appears, and *stopped is emitted whenever target stops for any reason (generally, a stop in the target is not 100% related to the execution command we were last doing, for example -exec-next can cause a breakpoint to be hit in unrelated thread). Because async notifications are not related to any given command, they don't, generally speaking, include the token of any previous MI command. (*) Currently, the *stopped output does include the token of the last command. However, it's implemented in limited way -- if we allow any command except for -exec-interrupt in async mode, the token printed for *stopped will be wrong. In non-stop mode, associating *stopped with a command is just impossible. Presently, MI spec says a command can output ^running just once. However, it the presense of breakpoint commands, it's quite possible that we resume one thread, hit a breakpoint, and breakpoint commands resume all threads, or some other thread. To handle this case we need a new async output for this case: *running,thread-id="xxx" which is emitted whenever a previously stopped thread is resumed. In case all threads are resumed, "xxx" will be "all". Async/non-stop mode notes ------------------------- The async mode basically means that gdb can process commands even while the target is running. This mode is enabled whenever the target is async-capable. In async mode, there are two further distinctions: - Should we allow an exec command while some other exec command is already in progress? - Should we stop all threads whenever an event is detected in one thread? Those issues seem independent initially, so we might try to allow two -exec-next at one time, and then stop all threads when any -exec-next is finished. However, that will require user to explicitly resume the -exec-next that is not yet finished, which does not seem very helpful -- it's not much better than sending two -exec-next sequentally. Therefore, for now we shall have only two modes: - "all-stop", when all threads are stopped if any thread stops, and when only one exec command is allowed to be active at any given time, - "non-stop", where individual threads are stopped, and several exec commands can be active. Except for what is said above "all-stop" and "non-stop" async modes are identical. Generally, most MI commands are allowed while a target is running, with the following exceptions: - An execution command that logically applies to a single thread cannot be used if the thread is already running. Global -exec-continue is OK, and will resume all threads that are not presently running. In all-stop mode an execution command cannot be started if any thread is running. - Many commands in current MI operate on current thread. In non-stop mode, this creates a potential for race condition -- between the frontend sending a command to gdb and gdb reading that command, gdb can detect a breakpoint and change the current thread. Furthermore, in case when a frontend sends a series of commands and gdb detects a thread stop in between, it's plain impossible to figure if the second command should be executed in the originally current thread, or in the thread were stop was detected. For that reason, in non-stop mode all MI commands that require a thread will require the frontend to specify the thread explicitly. Note: stateless protocol will not only be more robust in non-stop mode, but actually simplify frontends. Say, in CDT there are several places were we switch a thread, do some operation, and then switch back to the original thread. Say, Thread.getStackFrameCount or Target.evaluateExpressionToString. - Some data access commands are also implicitly using a specific thread -- because they are using registers, or variables in specific thread/frame, or because they have to call a function in the inferior. Such data access commands are not allowed when the necessary thread is running. Wholesale update operations like -var-update will plain ignore variable objects that need now-running threads. - The commands that grab global state of the target are allowed when some threads are running. It should be understood that the result may be inaccurate -- in particular, the memory content can change while we read it, and the list of threads might not be updated until some event from the target arrives. In addition, some targets might not even allow reading memory while all threads are running -- so memory access commands on such targets will require that at least one thread is stopped. To simplify things, if GDB is started in MI mode, no CLI command is allowed while the target is running, and -interpreter-exec is not allowed either. Note: in cases when to implement a command, GDB requires that at least one (or all) threads are stopped, and the command is issued when this condition is not met, we have two choices -- issue an error, or briefly stop the target, perform the operation, and resume. Clearly, doing that in GDB (or even in the target) will be less intrusive then doing that in frontend. However, it might be still too intrusive. For now, we'll just emit error, should a real need arise, we can always implement automatic interruption of the target. MI commands changes ------------------- (**) There are two new options that a number of MI commands may take: --thread option specifies the id of the thread the command should operate on. --global specifies that the command should operate on no thread, but on global data. This option is necessary to distinguish the case where the frontend has forgot to specify --thread, assuming that the current thread will be used, from the case when frontend explicitly wants to execute a command in global scope. This clarify of intention is particularly important when the "current thread" is running. - Break commands. All breakpoints commands are allowed at any time and the changes are applied to the program immediately. The output of -break-list and -break-info in general should be considered invalid as soon as a stop in any thread is reported. The break commands generally don't care about current thread and frame. If -break-insert command specifies only line number, then it implicitly depends on the filename of the current thread/frame. In non-stop mode, the frontend is required to specify thread and frame explicitly. - Program context commands. Those are not allowed after the program has started execution. - Thread commands. The -thread-info command should be implemented (a patch is already posted). (**) The -thread-list-all-threads is not necessary with the current behaviour of -thread-info. (**) The -thread-select command is only allowed on the that that is currently stopped. This command should not generally be used in non-stop mode. - Program execution. The -exec-next, -exec-step, -exec-finish, -exec-until, -exec-return, -exec-step-instruction and -exec-next-instruction command require --thread parameter. Also, those commands resume strictly the thread that is being stepped, equivalent to "scheduler-locking on". The -exec-continue command with the --thread parameter will resume just one thread, whereas -exec-continue without a --thread parameter will resume all threads that are not presently running. - Stack commands. All are allowed. All require a thread parameter in non-stop mode. - Variable objects. The -var-create command requires either the --thread or --global option. If --thread is specified, then the referred thread must be stopped. With --global, varobj's expression is evaluated in the global scope. If a variable object makes use of any local variable, the object becomes bound to the thread where it was created. An attempt to manipulate an individual variable obect when the thread it is bound to is not stopped results in an error. As a special exception, -var-update will ignore any variable object whose bound thread is not stopped. A variable object's expression might involve a function call. If a variable object is not bound to any thread, the function call will be executed in any currently stopped thread. Note: this does allow creating a global varobj while all threads are running. If the target does not allow accessing memory when all threads are running, such a varobj will only get any value at a later time. -> Should @ varobjs be bound to only thread, or to nothing at all. - Data manipulation. All commands are supported, except for data-list-changed-registers, which is presently thread-unaware and seems inferior to using variable objects anyway. The -data-evaluate-expression and -data-list-register-values requires that either the --thread or the --global option be provided. - Symbol query commands. All are supported. - File commands. The -file-exec-and-symbols and -file-exec-file cannot be used when any thread is running. The -file-list-shared-libraries can be used while inferior is running, but the results might be invalidated immediately. Same for -file-list-symbol-files. Others can be used without limitations. On some targets it might not be possible to get the list of shared libraries from the target while it is running. In such cases, GDB will report an error. - Target manipulation. The -target-disconnect can be used while threads are running. Other (currently implemented) commands can only be used before we have an executable. - File transfer. Can be always used. - Misc. Case-by-case, nothing interesting.