From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 24282 invoked by alias); 14 Aug 2008 20:40:56 -0000 Received: (qmail 24274 invoked by uid 22791); 14 Aug 2008 20:40:55 -0000 X-Spam-Check-By: sourceware.org Received: from mtagate4.de.ibm.com (HELO mtagate4.de.ibm.com) (195.212.29.153) by sourceware.org (qpsmtpd/0.31) with ESMTP; Thu, 14 Aug 2008 20:40:12 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate4.de.ibm.com (8.13.8/8.13.8) with ESMTP id m7EKe0iQ210040 for ; Thu, 14 Aug 2008 20:40:00 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v9.0) with ESMTP id m7EKe0ld897162 for ; Thu, 14 Aug 2008 22:40:00 +0200 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m7EKdxTr021352 for ; Thu, 14 Aug 2008 22:40:00 +0200 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id m7EKdxmf021349 for ; Thu, 14 Aug 2008 22:39:59 +0200 Message-Id: <200808142039.m7EKdxmf021349@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Thu, 14 Aug 2008 22:39:59 +0200 Subject: [rfc] Preferred thread event reporting: Linux native target To: gdb-patches@sourceware.org Date: Thu, 14 Aug 2008 20:40:00 -0000 From: "Ulrich Weigand" X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-08/txt/msg00386.txt.bz2 Hello, this is another patch we've been using internally for a while. The problem addressed by this patch is related to the way the Linux native target handled simultaneous events in multi-threaded programs. After the OS has signalled an event in some thread, GDB will stop all other threads (unless in non-stop mode). During this process, some other thread might *also* signal an event, so once everything is stopped, there might be multiple threads with pending events. However, the Linux native target has to select just one of them to report up to the infrun logic. It currently makes that decision randomly. This may be unexpected to a user who is currently working on one specific thread (say, single-stepping). If the single-step event in the thread the user is working on arrives at the same time as some other event in some other thread, it would be nice if that single-step event were reported first, so as to not interrupt the user's work flow. And indeed, the Linux native target does contain special code that prefers reporting an event in a thread that is currently single-stepped, bypassing the randomization logic that would otherwise be used. *However*, this unfortunately works only on platforms that use *hardware* single-stepping, because the native target is not even aware that anything special is going on when the target uses software single-stepping. It seems to me that this implementation detail should not determine user-visible behaviour in the way described above. Therefore, I'd suggest to try to *always* prefer reporting events in the thread the user currently "cares about" -- this is actually simply the currently selected thread (i.e. the current value of inferior_ptid). The patch below implements this by adding a new member "preferred" to "struct lwp_info", setting it according to the value of inferior_ptid in linux_nat_resume, and using it (instead of the single-step flag) to decide whether to prefer reporting events in this thread. Tested on powerpc-linux and powerpc64-linux. Any comments on this approach welcome ... Am I missing some reason why this might not be a good idea? Bye, Ulrich ChangeLog: * linux-nat.h (struct lwp_info): New member "preferred". * linux-nat.c (resume_callback): Reset lp->preferred. (linux_nat_resume): Set lp->preferred. (select_singlestep_lwp_callback): Rename to ... (select_preferred_lwp_callback): ... this. Check for lp->preferred instead of lp->step. (select_event_lwp): Update call to select_singlestep_lwp_callback. diff -urNp gdb-orig/gdb/linux-nat.c gdb-head/gdb/linux-nat.c --- gdb-orig/gdb/linux-nat.c 2008-08-08 20:14:08.000000000 +0200 +++ gdb-head/gdb/linux-nat.c 2008-08-14 19:28:07.334541534 +0200 @@ -1600,6 +1600,7 @@ resume_callback (struct lwp_info *lp, vo "RC: PTRACE_CONT %s, 0, 0 (resume sibling)\n", target_pid_to_str (lp->ptid)); lp->stopped = 0; + lp->preferred = 0; lp->step = 0; memset (&lp->siginfo, 0, sizeof (lp->siginfo)); } @@ -1671,6 +1672,9 @@ linux_nat_resume (ptid_t ptid, int step, /* Convert to something the lower layer understands. */ ptid = pid_to_ptid (GET_LWP (lp->ptid)); + /* Mark this thread as the preferred thread. */ + lp->preferred = 1; + /* Remember if we're stepping. */ lp->step = step; @@ -2293,12 +2297,12 @@ count_events_callback (struct lwp_info * return 0; } -/* Select the LWP (if any) that is currently being single-stepped. */ +/* Select the LWP the user is currently interested in. */ static int -select_singlestep_lwp_callback (struct lwp_info *lp, void *data) +select_preferred_lwp_callback (struct lwp_info *lp, void *data) { - if (lp->step && lp->status != 0) + if (lp->preferred && lp->status != 0) return 1; else return 0; @@ -2396,8 +2400,8 @@ select_event_lwp (struct lwp_info **orig /* Record the wait status for the original LWP. */ (*orig_lp)->status = *status; - /* Give preference to any LWP that is being single-stepped. */ - event_lp = iterate_over_lwps (select_singlestep_lwp_callback, NULL); + /* Give preference to the LWP the user is currently interested in. */ + event_lp = iterate_over_lwps (select_preferred_lwp_callback, NULL); if (event_lp != NULL) { if (debug_linux_nat) @@ -2407,8 +2411,8 @@ select_event_lwp (struct lwp_info **orig } else { - /* No single-stepping LWP. Select one at random, out of those - which have had SIGTRAP events. */ + /* No preferred LWP. Select one at random, out of those which + have had SIGTRAP events. */ /* First see how many SIGTRAP events we have. */ iterate_over_lwps (count_events_callback, &num_events); diff -urNp gdb-orig/gdb/linux-nat.h gdb-head/gdb/linux-nat.h --- gdb-orig/gdb/linux-nat.h 2008-08-05 22:16:25.000000000 +0200 +++ gdb-head/gdb/linux-nat.h 2008-08-14 19:20:07.523558223 +0200 @@ -65,6 +65,9 @@ struct lwp_info /* Non-zero if we expect a duplicated SIGINT. */ int ignore_sigint; + /* Non-zero if this is the thread preferred for event reporting. */ + int preferred; + /* If WAITSTATUS->KIND != TARGET_WAITKIND_SPURIOUS, the waitstatus for this LWP's last event. This may correspond to STATUS above, or to a local variable in lin_lwp_wait. */ -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE Ulrich.Weigand@de.ibm.com