X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Flinux-nat.c;h=e7e001bc4d5d445a0dbc545f2d83ea5b6da2d9e2;hb=080017175b5248f1e5b0d48a55a06634244db459;hp=48ea1bc46c81b40c72f83eb5109f4f66e6f2222b;hpb=268a4a75bdc5271819e657da07b868c8bddc500f;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 48ea1bc46c..e7e001bc4d 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -1105,25 +1105,6 @@ status_to_str (int status) return buf; } -/* Initialize the list of LWPs. Note that this module, contrary to - what GDB's generic threads layer does for its thread list, - re-initializes the LWP lists whenever we mourn or detach (which - doesn't involve mourning) the inferior. */ - -static void -init_lwp_list (void) -{ - struct lwp_info *lp, *lpnext; - - for (lp = lwp_list; lp; lp = lpnext) - { - lpnext = lp->next; - xfree (lp); - } - - lwp_list = NULL; -} - /* Remove all LWPs belong to PID from the lwp list. */ static void @@ -1184,6 +1165,7 @@ add_lwp (ptid_t ptid) lp->waitstatus.kind = TARGET_WAITKIND_IGNORE; lp->ptid = ptid; + lp->core = -1; lp->next = lwp_list; lwp_list = lp; @@ -1239,33 +1221,6 @@ find_lwp_pid (ptid_t ptid) return NULL; } -/* Returns true if PTID matches filter FILTER. FILTER can be the wild - card MINUS_ONE_PTID (all ptid match it); can be a ptid representing - a process (ptid_is_pid returns true), in which case, all lwps of - that give process match, lwps of other process do not; or, it can - represent a specific thread, in which case, only that thread will - match true. PTID must represent an LWP, it can never be a wild - card. */ - -static int -ptid_match (ptid_t ptid, ptid_t filter) -{ - /* Since both parameters have the same type, prevent easy mistakes - from happening. */ - gdb_assert (!ptid_equal (ptid, minus_one_ptid) - && !ptid_equal (ptid, null_ptid)); - - if (ptid_equal (filter, minus_one_ptid)) - return 1; - if (ptid_is_pid (filter) - && ptid_get_pid (ptid) == ptid_get_pid (filter)) - return 1; - else if (ptid_equal (ptid, filter)) - return 1; - - return 0; -} - /* Call CALLBACK with its second argument set to DATA for every LWP in the list. If CALLBACK returns 1 for a particular LWP, return a pointer to the structure describing that LWP immediately. @@ -1828,10 +1783,11 @@ linux_nat_detach (struct target_ops *ops, char *args, int from_tty) pass it along with PTRACE_DETACH. */ args = alloca (8); sprintf (args, "%d", (int) WSTOPSIG (status)); - fprintf_unfiltered (gdb_stdlog, - "LND: Sending signal %s to %s\n", - args, - target_pid_to_str (main_lwp->ptid)); + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "LND: Sending signal %s to %s\n", + args, + target_pid_to_str (main_lwp->ptid)); } delete_lwp (main_lwp->ptid); @@ -1930,14 +1886,8 @@ linux_nat_resume (struct target_ops *ops, resume_many = (ptid_equal (minus_one_ptid, ptid) || ptid_is_pid (ptid)); - if (!non_stop) - { - /* Mark the lwps we're resuming as resumed. */ - iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL); - iterate_over_lwps (ptid, resume_set_callback, NULL); - } - else - iterate_over_lwps (minus_one_ptid, resume_set_callback, NULL); + /* Mark the lwps we're resuming as resumed. */ + iterate_over_lwps (ptid, resume_set_callback, NULL); /* See if it's the current inferior that should be handled specially. */ @@ -3280,8 +3230,20 @@ retry: lp = NULL; status = 0; - /* Make sure there is at least one LWP that has been resumed. */ - gdb_assert (iterate_over_lwps (ptid, resumed_callback, NULL)); + /* Make sure that of those LWPs we want to get an event from, there + is at least one LWP that has been resumed. If there's none, just + bail out. The core may just be flushing asynchronously all + events. */ + if (iterate_over_lwps (ptid, resumed_callback, NULL) == NULL) + { + ourstatus->kind = TARGET_WAITKIND_IGNORE; + + if (debug_linux_nat_async) + fprintf_unfiltered (gdb_stdlog, "LLW: exit (no resumed LWP)\n"); + + restore_child_signals_mask (&prev_mask); + return minus_one_ptid; + } /* First check if there is a LWP with a wait status pending. */ if (pid == -1) @@ -3412,6 +3374,8 @@ retry: && ptid_is_pid (ptid) && ptid_get_pid (lp->ptid) != ptid_get_pid (ptid)) { + gdb_assert (lp->resumed); + if (debug_linux_nat) fprintf (stderr, "LWP %ld got an event %06x, leaving pending.\n", ptid_get_lwp (lp->ptid), status); @@ -3420,12 +3384,30 @@ retry: { if (WSTOPSIG (lp->status) != SIGSTOP) { - stop_callback (lp, NULL); - - /* Resume in order to collect the sigstop. */ - ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0); - - stop_wait_callback (lp, NULL); + /* Cancel breakpoint hits. The breakpoint may + be removed before we fetch events from this + process to report to the core. It is best + not to assume the moribund breakpoints + heuristic always handles these cases --- it + could be too many events go through to the + core before this one is handled. All-stop + always cancels breakpoint hits in all + threads. */ + if (non_stop + && lp->waitstatus.kind == TARGET_WAITKIND_IGNORE + && WSTOPSIG (lp->status) == SIGTRAP + && cancel_breakpoint (lp)) + { + /* Throw away the SIGTRAP. */ + lp->status = 0; + + if (debug_linux_nat) + fprintf (stderr, + "LLW: LWP %ld hit a breakpoint while waiting " + "for another process; cancelled it\n", + ptid_get_lwp (lp->ptid)); + } + lp->stopped = 1; } else { @@ -3615,12 +3597,19 @@ retry: starvation. */ if (pid == -1) select_event_lwp (ptid, &lp, &status); - } - /* Now that we've selected our final event LWP, cancel any - breakpoints in other LWPs that have hit a GDB breakpoint. See - the comment in cancel_breakpoints_callback to find out why. */ - iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp); + /* Now that we've selected our final event LWP, cancel any + breakpoints in other LWPs that have hit a GDB breakpoint. + See the comment in cancel_breakpoints_callback to find out + why. */ + iterate_over_lwps (minus_one_ptid, cancel_breakpoints_callback, lp); + + /* In all-stop, from the core's perspective, all LWPs are now + stopped until a new resume action is sent over. */ + iterate_over_lwps (minus_one_ptid, resume_clear_callback, NULL); + } + else + lp->resumed = 0; if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP) { @@ -3642,9 +3631,51 @@ retry: fprintf_unfiltered (gdb_stdlog, "LLW: exit\n"); restore_child_signals_mask (&prev_mask); + lp->core = linux_nat_core_of_thread_1 (lp->ptid); return lp->ptid; } +/* Resume LWPs that are currently stopped without any pending status + to report, but are resumed from the core's perspective. */ + +static int +resume_stopped_resumed_lwps (struct lwp_info *lp, void *data) +{ + ptid_t *wait_ptid_p = data; + + if (lp->stopped + && lp->resumed + && lp->status == 0 + && lp->waitstatus.kind == TARGET_WAITKIND_IGNORE) + { + gdb_assert (is_executing (lp->ptid)); + + /* Don't bother if there's a breakpoint at PC that we'd hit + immediately, and we're not waiting for this LWP. */ + if (!ptid_match (lp->ptid, *wait_ptid_p)) + { + struct regcache *regcache = get_thread_regcache (lp->ptid); + CORE_ADDR pc = regcache_read_pc (regcache); + + if (breakpoint_inserted_here_p (get_regcache_aspace (regcache), pc)) + return 0; + } + + if (debug_linux_nat) + fprintf_unfiltered (gdb_stdlog, + "RSRL: resuming stopped-resumed LWP %s\n", + target_pid_to_str (lp->ptid)); + + linux_ops->to_resume (linux_ops, pid_to_ptid (GET_LWP (lp->ptid)), + lp->step, TARGET_SIGNAL_0); + lp->stopped = 0; + memset (&lp->siginfo, 0, sizeof (lp->siginfo)); + lp->stopped_by_watchpoint = 0; + } + + return 0; +} + static ptid_t linux_nat_wait (struct target_ops *ops, ptid_t ptid, struct target_waitstatus *ourstatus, @@ -3659,6 +3690,16 @@ linux_nat_wait (struct target_ops *ops, if (target_can_async_p ()) async_file_flush (); + /* Resume LWPs that are currently stopped without any pending status + to report, but are resumed from the core's perspective. LWPs get + in this state if we find them stopping at a time we're not + interested in reporting the event (target_wait on a + specific_process, for example, see linux_nat_wait_1), and + meanwhile the event became uninteresting. Don't bother resuming + LWPs we're not going to wait for if they'd stop immediately. */ + if (non_stop) + iterate_over_lwps (minus_one_ptid, resume_stopped_resumed_lwps, &ptid); + event_ptid = linux_nat_wait_1 (ops, ptid, ourstatus, target_options); /* If we requested any event, and something came out, assume there @@ -4045,8 +4086,8 @@ linux_nat_find_memory_regions (int (*func) (CORE_ADDR, if (info_verbose) { fprintf_filtered (gdb_stdout, - "Save segment, %lld bytes at %s (%c%c%c)", - size, paddress (target_gdbarch, addr), + "Save segment, %s bytes at %s (%c%c%c)", + plongest (size), paddress (target_gdbarch, addr), read ? 'r' : ' ', write ? 'w' : ' ', exec ? 'x' : ' '); if (filename[0]) @@ -5007,7 +5048,7 @@ linux_xfer_partial (struct target_ops *ops, enum target_object object, LONGEST xfer; if (object == TARGET_OBJECT_AUXV) - return procfs_xfer_auxv (ops, object, annex, readbuf, writebuf, + return memory_xfer_auxv (ops, object, annex, readbuf, writebuf, offset, len); if (object == TARGET_OBJECT_OSDATA) @@ -5423,6 +5464,75 @@ linux_nat_thread_address_space (struct target_ops *t, ptid_t ptid) return inf->aspace; } +int +linux_nat_core_of_thread_1 (ptid_t ptid) +{ + struct cleanup *back_to; + char *filename; + FILE *f; + char *content = NULL; + char *p; + char *ts = 0; + int content_read = 0; + int i; + int core; + + filename = xstrprintf ("/proc/%d/task/%ld/stat", + GET_PID (ptid), GET_LWP (ptid)); + back_to = make_cleanup (xfree, filename); + + f = fopen (filename, "r"); + if (!f) + { + do_cleanups (back_to); + return -1; + } + + make_cleanup_fclose (f); + + for (;;) + { + int n; + content = xrealloc (content, content_read + 1024); + n = fread (content + content_read, 1, 1024, f); + content_read += n; + if (n < 1024) + { + content[content_read] = '\0'; + break; + } + } + + make_cleanup (xfree, content); + + p = strchr (content, '('); + p = strchr (p, ')') + 2; /* skip ")" and a whitespace. */ + + /* If the first field after program name has index 0, then core number is + the field with index 36. There's no constant for that anywhere. */ + p = strtok_r (p, " ", &ts); + for (i = 0; i != 36; ++i) + p = strtok_r (NULL, " ", &ts); + + if (sscanf (p, "%d", &core) == 0) + core = -1; + + do_cleanups (back_to); + + return core; +} + +/* Return the cached value of the processor core for thread PTID. */ + +int +linux_nat_core_of_thread (struct target_ops *ops, ptid_t ptid) +{ + struct lwp_info *info = find_lwp_pid (ptid); + if (info) + return info->core; + return -1; +} + void linux_nat_add_target (struct target_ops *t) { @@ -5463,6 +5573,8 @@ linux_nat_add_target (struct target_ops *t) t->to_supports_multi_process = linux_nat_supports_multi_process; + t->to_core_of_thread = linux_nat_core_of_thread; + /* We don't change the stratum; this target will sit at process_stratum and thread_db will set at thread_stratum. This is a little strange, since this is a multi-threaded-capable