static void complete_ongoing_step_over (void);
static int linux_low_ptrace_options (int attached);
static int check_ptrace_stopped_lwp_gone (struct lwp_info *lp);
-static int proceed_one_lwp (struct inferior_list_entry *entry, void *except);
+static int proceed_one_lwp (thread_info *thread, void *except);
/* When the event-loop is doing a step-over, this points at the thread
being stepped. */
debug_printf ("deleting %ld\n", lwpid_of (thr));
remove_thread (thr);
- free (lwp->arch_private);
+
+ if (the_low_target.delete_thread != NULL)
+ the_low_target.delete_thread (lwp->arch_private);
+ else
+ gdb_assert (lwp->arch_private == NULL);
+
free (lwp);
}
new_lwp->status_pending = status;
}
+ thread_db_notice_clone (event_thr, ptid);
+
/* Don't report the event. */
return 1;
}
else if (event == PTRACE_EVENT_EXEC && report_exec_events)
{
struct process_info *proc;
- VEC (int) *syscalls_to_catch;
+ std::vector<int> syscalls_to_catch;
ptid_t event_ptid;
pid_t event_pid;
/* Save the syscall list from the execing process. */
proc = get_thread_process (event_thr);
- syscalls_to_catch = proc->syscalls_to_catch;
- proc->syscalls_to_catch = NULL;
+ syscalls_to_catch = std::move (proc->syscalls_to_catch);
/* Delete the execing process and all its threads. */
linux_mourn (proc);
/* Restore the list to catch. Don't rely on the client, which is free
to avoid sending a new list when the architecture doesn't change.
Also, for ANY_SYSCALL, the architecture doesn't really matter. */
- proc->syscalls_to_catch = syscalls_to_catch;
+ proc->syscalls_to_catch = std::move (syscalls_to_catch);
/* Report the event. */
*orig_event_lwp = event_lwp;
struct lwp_info *new_lwp;
int pid;
ptid_t ptid;
- struct cleanup *restore_personality
- = maybe_disable_address_space_randomization (disable_randomization);
- std::string str_program_args = stringify_argv (program_args);
- pid = fork_inferior (program,
- str_program_args.c_str (),
- get_environ ()->envp (), linux_ptrace_fun,
- NULL, NULL, NULL, NULL);
+ {
+ maybe_disable_address_space_randomization restore_personality
+ (disable_randomization);
+ std::string str_program_args = stringify_argv (program_args);
- do_cleanups (restore_personality);
+ pid = fork_inferior (program,
+ str_program_args.c_str (),
+ get_environ ()->envp (), linux_ptrace_fun,
+ NULL, NULL, NULL, NULL);
+ }
linux_add_process (pid, 0);
};
static int
-second_thread_of_pid_p (struct inferior_list_entry *entry, void *args)
+second_thread_of_pid_p (thread_info *thread, void *args)
{
struct counter *counter = (struct counter *) args;
- if (ptid_get_pid (entry->id) == counter->pid)
+ if (thread->id.pid () == counter->pid)
{
if (++counter->count > 1)
return 1;
perror_with_name ("kill_wait_lwp");
}
-/* Callback for `find_inferior'. Kills an lwp of a given process,
+/* Callback for `for_each_thread'. Kills an lwp of a given process,
except the leader. */
-static int
-kill_one_lwp_callback (struct inferior_list_entry *entry, void *args)
+static void
+kill_one_lwp_callback (thread_info *thread, int pid)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
- int pid = * (int *) args;
-
- if (ptid_get_pid (entry->id) != pid)
- return 0;
/* We avoid killing the first thread here, because of a Linux kernel (at
least 2.6.0-test7 through 2.6.8-rc4) bug; if we kill the parent before
{
if (debug_threads)
debug_printf ("lkop: is last of process %s\n",
- target_pid_to_str (entry->id));
- return 0;
+ target_pid_to_str (thread->id));
+ return;
}
kill_wait_lwp (lwp);
- return 0;
}
static int
first, as PTRACE_KILL will not work otherwise. */
stop_all_lwps (0, NULL);
- find_inferior (&all_threads, kill_one_lwp_callback , &pid);
+ for_each_thread (pid, [&] (thread_info *thread)
+ {
+ kill_one_lwp_callback (thread, pid);
+ });
/* See the comment in linux_kill_one_lwp. We did not kill the first
thread in the list, so do so now. */
given process. */
static int
-linux_detach_lwp_callback (struct inferior_list_entry *entry, void *args)
+linux_detach_lwp_callback (thread_info *thread, void *args)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
int pid = *(int *) args;
int lwpid = lwpid_of (thread);
/* Skip other processes. */
- if (ptid_get_pid (entry->id) != pid)
+ if (thread->id.pid () != pid)
return 0;
/* We don't actually detach from the thread group leader just yet.
If the thread group exits, we must reap the zombie clone lwps
before we're able to reap the leader. */
- if (ptid_get_pid (entry->id) == lwpid)
+ if (thread->id.pid () == lwpid)
return 0;
linux_detach_one_lwp (lwp);
/* Remove all LWPs that belong to process PROC from the lwp list. */
static int
-delete_lwp_callback (struct inferior_list_entry *entry, void *proc)
+delete_lwp_callback (thread_info *thread, void *proc)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
struct process_info *process = (struct process_info *) proc;
/* Freeing all private data. */
priv = process->priv;
- free (priv->arch_private);
+ if (the_low_target.delete_process != NULL)
+ the_low_target.delete_process (priv->arch_private);
+ else
+ gdb_assert (priv->arch_private == NULL);
free (priv);
process->priv = NULL;
/* Return 1 if this lwp has an interesting status pending. */
static int
-status_pending_p_callback (struct inferior_list_entry *entry, void *arg)
+status_pending_p_callback (thread_info *thread, void *arg)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lp = get_thread_lwp (thread);
ptid_t ptid = * (ptid_t *) arg;
}
static int
-same_lwp (struct inferior_list_entry *entry, void *data)
+same_lwp (thread_info *thread, void *data)
{
ptid_t ptid = *(ptid_t *) data;
int lwp;
else
lwp = ptid_get_pid (ptid);
- if (ptid_get_lwp (entry->id) == lwp)
+ if (thread->id.lwp () == lwp)
return 1;
return 0;
struct lwp_info *
find_lwp_pid (ptid_t ptid)
{
- struct inferior_list_entry *thread
- = find_inferior (&all_threads, same_lwp, &ptid);
+ thread_info *thread = find_inferior (&all_threads, same_lwp, &ptid);
if (thread == NULL)
return NULL;
- return get_thread_lwp ((struct thread_info *) thread);
+ return get_thread_lwp (thread);
}
/* Return the number of known LWPs in the tgid given by PID. */
static int
num_lwps (int pid)
{
- struct inferior_list_entry *inf, *tmp;
int count = 0;
- ALL_INFERIORS (&all_threads, inf, tmp)
+ for_each_thread (pid, [&] (thread_info *thread)
{
- if (ptid_get_pid (inf->id) == pid)
- count++;
- }
+ count++;
+ });
return count;
}
-/* The arguments passed to iterate_over_lwps. */
-
-struct iterate_over_lwps_args
-{
- /* The FILTER argument passed to iterate_over_lwps. */
- ptid_t filter;
-
- /* The CALLBACK argument passed to iterate_over_lwps. */
- iterate_over_lwps_ftype *callback;
-
- /* The DATA argument passed to iterate_over_lwps. */
- void *data;
-};
-
-/* Callback for find_inferior used by iterate_over_lwps to filter
- calls to the callback supplied to that function. Returning a
- nonzero value causes find_inferiors to stop iterating and return
- the current inferior_list_entry. Returning zero indicates that
- find_inferiors should continue iterating. */
-
-static int
-iterate_over_lwps_filter (struct inferior_list_entry *entry, void *args_p)
-{
- struct iterate_over_lwps_args *args
- = (struct iterate_over_lwps_args *) args_p;
-
- if (ptid_match (entry->id, args->filter))
- {
- struct thread_info *thr = (struct thread_info *) entry;
- struct lwp_info *lwp = get_thread_lwp (thr);
-
- return (*args->callback) (lwp, args->data);
- }
-
- return 0;
-}
-
/* See nat/linux-nat.h. */
struct lwp_info *
iterate_over_lwps_ftype callback,
void *data)
{
- struct iterate_over_lwps_args args = {filter, callback, data};
- struct inferior_list_entry *entry;
+ thread_info *thread = find_thread (filter, [&] (thread_info *thread)
+ {
+ lwp_info *lwp = get_thread_lwp (thread);
+
+ return callback (lwp, data);
+ });
- entry = find_inferior (&all_threads, iterate_over_lwps_filter, &args);
- if (entry == NULL)
+ if (thread == NULL)
return NULL;
- return get_thread_lwp ((struct thread_info *) entry);
+ return get_thread_lwp (thread);
}
/* Detect zombie thread group leaders, and "exit" them. We can't reap
static void
check_zombie_leaders (void)
{
- struct process_info *proc, *tmp;
-
- ALL_PROCESSES (proc, tmp)
- {
- pid_t leader_pid = pid_of (proc);
- struct lwp_info *leader_lp;
+ for_each_process ([] (process_info *proc) {
+ pid_t leader_pid = pid_of (proc);
+ struct lwp_info *leader_lp;
- leader_lp = find_lwp_pid (pid_to_ptid (leader_pid));
+ leader_lp = find_lwp_pid (pid_to_ptid (leader_pid));
- if (debug_threads)
- debug_printf ("leader_pid=%d, leader_lp!=NULL=%d, "
- "num_lwps=%d, zombie=%d\n",
- leader_pid, leader_lp!= NULL, num_lwps (leader_pid),
- linux_proc_pid_is_zombie (leader_pid));
-
- if (leader_lp != NULL && !leader_lp->stopped
- /* Check if there are other threads in the group, as we may
- have raced with the inferior simply exiting. */
- && !last_thread_of_process_p (leader_pid)
- && linux_proc_pid_is_zombie (leader_pid))
- {
- /* A leader zombie can mean one of two things:
-
- - It exited, and there's an exit status pending
- available, or only the leader exited (not the whole
- program). In the latter case, we can't waitpid the
- leader's exit status until all other threads are gone.
-
- - There are 3 or more threads in the group, and a thread
- other than the leader exec'd. On an exec, the Linux
- kernel destroys all other threads (except the execing
- one) in the thread group, and resets the execing thread's
- tid to the tgid. No exit notification is sent for the
- execing thread -- from the ptracer's perspective, it
- appears as though the execing thread just vanishes.
- Until we reap all other threads except the leader and the
- execing thread, the leader will be zombie, and the
- execing thread will be in `D (disc sleep)'. As soon as
- all other threads are reaped, the execing thread changes
- it's tid to the tgid, and the previous (zombie) leader
- vanishes, giving place to the "new" leader. We could try
- distinguishing the exit and exec cases, by waiting once
- more, and seeing if something comes out, but it doesn't
- sound useful. The previous leader _does_ go away, and
- we'll re-add the new one once we see the exec event
- (which is just the same as what would happen if the
- previous leader did exit voluntarily before some other
- thread execs). */
+ if (debug_threads)
+ debug_printf ("leader_pid=%d, leader_lp!=NULL=%d, "
+ "num_lwps=%d, zombie=%d\n",
+ leader_pid, leader_lp!= NULL, num_lwps (leader_pid),
+ linux_proc_pid_is_zombie (leader_pid));
- if (debug_threads)
- debug_printf ("CZL: Thread group leader %d zombie "
- "(it exited, or another thread execd).\n",
- leader_pid);
-
- delete_lwp (leader_lp);
- }
- }
+ if (leader_lp != NULL && !leader_lp->stopped
+ /* Check if there are other threads in the group, as we may
+ have raced with the inferior simply exiting. */
+ && !last_thread_of_process_p (leader_pid)
+ && linux_proc_pid_is_zombie (leader_pid))
+ {
+ /* A leader zombie can mean one of two things:
+
+ - It exited, and there's an exit status pending
+ available, or only the leader exited (not the whole
+ program). In the latter case, we can't waitpid the
+ leader's exit status until all other threads are gone.
+
+ - There are 3 or more threads in the group, and a thread
+ other than the leader exec'd. On an exec, the Linux
+ kernel destroys all other threads (except the execing
+ one) in the thread group, and resets the execing thread's
+ tid to the tgid. No exit notification is sent for the
+ execing thread -- from the ptracer's perspective, it
+ appears as though the execing thread just vanishes.
+ Until we reap all other threads except the leader and the
+ execing thread, the leader will be zombie, and the
+ execing thread will be in `D (disc sleep)'. As soon as
+ all other threads are reaped, the execing thread changes
+ it's tid to the tgid, and the previous (zombie) leader
+ vanishes, giving place to the "new" leader. We could try
+ distinguishing the exit and exec cases, by waiting once
+ more, and seeing if something comes out, but it doesn't
+ sound useful. The previous leader _does_ go away, and
+ we'll re-add the new one once we see the exec event
+ (which is just the same as what would happen if the
+ previous leader did exit voluntarily before some other
+ thread execs). */
+
+ if (debug_threads)
+ debug_printf ("CZL: Thread group leader %d zombie "
+ "(it exited, or another thread execd).\n",
+ leader_pid);
+
+ delete_lwp (leader_lp);
+ }
+ });
}
/* Callback for `find_inferior'. Returns the first LWP that is not
stopped. ARG is a PTID filter. */
static int
-not_stopped_callback (struct inferior_list_entry *entry, void *arg)
+not_stopped_callback (thread_info *thread, void *arg)
{
- struct thread_info *thr = (struct thread_info *) entry;
struct lwp_info *lwp;
ptid_t filter = *(ptid_t *) arg;
- if (!ptid_match (ptid_of (thr), filter))
+ if (!ptid_match (ptid_of (thread), filter))
return 0;
- lwp = get_thread_lwp (thr);
+ lwp = get_thread_lwp (thread);
if (!lwp->stopped)
return 1;
to report, but are resumed from the core's perspective. */
static void
-resume_stopped_resumed_lwps (struct inferior_list_entry *entry)
+resume_stopped_resumed_lwps (thread_info *thread)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lp = get_thread_lwp (thread);
if (lp->stopped
/* Count the LWP's that have had events. */
static int
-count_events_callback (struct inferior_list_entry *entry, void *data)
+count_events_callback (thread_info *thread, void *data)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lp = get_thread_lwp (thread);
int *count = (int *) data;
/* Select the LWP (if any) that is currently being single-stepped. */
static int
-select_singlestep_lwp_callback (struct inferior_list_entry *entry, void *data)
+select_singlestep_lwp_callback (thread_info *thread, void *data)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lp = get_thread_lwp (thread);
if (thread->last_status.kind == TARGET_WAITKIND_IGNORE
/* Select the Nth LWP that has had an event. */
static int
-select_event_lwp_callback (struct inferior_list_entry *entry, void *data)
+select_event_lwp_callback (thread_info *thread, void *data)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lp = get_thread_lwp (thread);
int *selector = (int *) data;
}
}
-/* Decrement the suspend count of an LWP. */
-
-static int
-unsuspend_one_lwp (struct inferior_list_entry *entry, void *except)
-{
- struct thread_info *thread = (struct thread_info *) entry;
- struct lwp_info *lwp = get_thread_lwp (thread);
-
- /* Ignore EXCEPT. */
- if (lwp == except)
- return 0;
-
- lwp_suspended_decr (lwp);
- return 0;
-}
-
/* Decrement the suspend count of all LWPs, except EXCEPT, if non
NULL. */
static void
unsuspend_all_lwps (struct lwp_info *except)
{
- find_inferior (&all_threads, unsuspend_one_lwp, except);
+ for_each_thread ([&] (thread_info *thread)
+ {
+ lwp_info *lwp = get_thread_lwp (thread);
+
+ if (lwp != except)
+ lwp_suspended_decr (lwp);
+ });
}
-static void move_out_of_jump_pad_callback (struct inferior_list_entry *entry);
-static int stuck_in_jump_pad_callback (struct inferior_list_entry *entry,
- void *data);
-static int lwp_running (struct inferior_list_entry *entry, void *data);
+static void move_out_of_jump_pad_callback (thread_info *thread);
+static bool stuck_in_jump_pad_callback (thread_info *thread);
+static int lwp_running (thread_info *thread, void *data);
static ptid_t linux_wait_1 (ptid_t ptid,
struct target_waitstatus *ourstatus,
int target_options);
static void
linux_stabilize_threads (void)
{
- struct thread_info *saved_thread;
- struct thread_info *thread_stuck;
+ thread_info *thread_stuck = find_thread (stuck_in_jump_pad_callback);
- thread_stuck
- = (struct thread_info *) find_inferior (&all_threads,
- stuck_in_jump_pad_callback,
- NULL);
if (thread_stuck != NULL)
{
if (debug_threads)
return;
}
- saved_thread = current_thread;
+ thread_info *saved_thread = current_thread;
stabilizing_threads = 1;
if (debug_threads)
{
- thread_stuck
- = (struct thread_info *) find_inferior (&all_threads,
- stuck_in_jump_pad_callback,
- NULL);
+ thread_stuck = find_thread (stuck_in_jump_pad_callback);
+
if (thread_stuck != NULL)
debug_printf ("couldn't stabilize, LWP %ld got stuck in jump pad\n",
lwpid_of (thread_stuck));
struct thread_info *thread = get_lwp_thread (event_child);
struct process_info *proc = get_thread_process (thread);
- return !VEC_empty (int, proc->syscalls_to_catch);
+ return !proc->syscalls_to_catch.empty ();
}
/* Returns 1 if GDB is interested in the event_child syscall.
static int
gdb_catch_this_syscall_p (struct lwp_info *event_child)
{
- int i, iter;
int sysno;
struct thread_info *thread = get_lwp_thread (event_child);
struct process_info *proc = get_thread_process (thread);
- if (VEC_empty (int, proc->syscalls_to_catch))
+ if (proc->syscalls_to_catch.empty ())
return 0;
- if (VEC_index (int, proc->syscalls_to_catch, 0) == ANY_SYSCALL)
+ if (proc->syscalls_to_catch[0] == ANY_SYSCALL)
return 1;
get_syscall_trapinfo (event_child, &sysno);
- for (i = 0;
- VEC_iterate (int, proc->syscalls_to_catch, i, iter);
- i++)
+
+ for (int iter : proc->syscalls_to_catch)
if (iter == sysno)
return 1;
{
/* In all-stop, a stop reply cancels all previous resume
requests. Delete all single-step breakpoints. */
- struct inferior_list_entry *inf, *tmp;
- ALL_INFERIORS (&all_threads, inf, tmp)
- {
- struct thread_info *thread = (struct thread_info *) inf;
+ find_thread ([&] (thread_info *thread) {
+ if (has_single_step_breakpoints (thread))
+ {
+ remove_single_step_breakpoints_p = 1;
+ return true;
+ }
- if (has_single_step_breakpoints (thread))
- {
- remove_single_step_breakpoints_p = 1;
- break;
- }
- }
+ return false;
+ });
}
if (remove_single_step_breakpoints_p)
}
else
{
- struct inferior_list_entry *inf, *tmp;
-
- ALL_INFERIORS (&all_threads, inf, tmp)
- {
- struct thread_info *thread = (struct thread_info *) inf;
-
- if (has_single_step_breakpoints (thread))
- delete_single_step_breakpoints (thread);
- }
+ for_each_thread ([] (thread_info *thread){
+ if (has_single_step_breakpoints (thread))
+ delete_single_step_breakpoints (thread);
+ });
}
unstop_all_lwps (0, event_child);
}
static int
-send_sigstop_callback (struct inferior_list_entry *entry, void *except)
+send_sigstop_callback (thread_info *thread, void *except)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
/* Ignore EXCEPT. */
/* Increment the suspend count of an LWP, and stop it, if not stopped
yet. */
static int
-suspend_and_send_sigstop_callback (struct inferior_list_entry *entry,
- void *except)
+suspend_and_send_sigstop_callback (thread_info *thread, void *except)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
/* Ignore EXCEPT. */
lwp_suspended_inc (lwp);
- return send_sigstop_callback (entry, except);
+ return send_sigstop_callback (thread, except);
}
static void
saved_thread = current_thread;
if (saved_thread != NULL)
- saved_tid = saved_thread->entry.id;
+ saved_tid = saved_thread->id;
else
saved_tid = null_ptid; /* avoid bogus unused warning */
}
}
-/* Returns true if LWP ENTRY is stopped in a jump pad, and we can't
+/* Returns true if THREAD is stopped in a jump pad, and we can't
move it out, because we need to report the stop event to GDB. For
example, if the user puts a breakpoint in the jump pad, it's
because she wants to debug it. */
-static int
-stuck_in_jump_pad_callback (struct inferior_list_entry *entry, void *data)
+static bool
+stuck_in_jump_pad_callback (thread_info *thread)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
if (lwp->suspended != 0)
}
static void
-move_out_of_jump_pad_callback (struct inferior_list_entry *entry)
+move_out_of_jump_pad_callback (thread_info *thread)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct thread_info *saved_thread;
struct lwp_info *lwp = get_thread_lwp (thread);
int *wstat;
}
static int
-lwp_running (struct inferior_list_entry *entry, void *data)
+lwp_running (thread_info *thread, void *data)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
if (lwp_is_marked_dead (lwp))
END_CATCH
}
-struct thread_resume_array
-{
- struct thread_resume *resume;
- size_t n;
-};
-
-/* This function is called once per thread via find_inferior.
- ARG is a pointer to a thread_resume_array struct.
- We look up the thread specified by ENTRY in ARG, and mark the thread
- with a pointer to the appropriate resume request.
+/* This function is called once per thread via for_each_thread.
+ We look up which resume request applies to THREAD and mark it with a
+ pointer to the appropriate resume request.
This algorithm is O(threads * resume elements), but resume elements
is small (and will remain small at least until GDB supports thread
suspension). */
-static int
-linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
+static void
+linux_set_resume_request (thread_info *thread, thread_resume *resume, size_t n)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
- int ndx;
- struct thread_resume_array *r;
- r = (struct thread_resume_array *) arg;
-
- for (ndx = 0; ndx < r->n; ndx++)
+ for (int ndx = 0; ndx < n; ndx++)
{
- ptid_t ptid = r->resume[ndx].thread;
+ ptid_t ptid = resume[ndx].thread;
if (ptid_equal (ptid, minus_one_ptid)
- || ptid_equal (ptid, entry->id)
+ || ptid == thread->id
/* Handle both 'pPID' and 'pPID.-1' as meaning 'all threads
of PID'. */
|| (ptid_get_pid (ptid) == pid_of (thread)
&& (ptid_is_pid (ptid)
|| ptid_get_lwp (ptid) == -1)))
{
- if (r->resume[ndx].kind == resume_stop
+ if (resume[ndx].kind == resume_stop
&& thread->last_resume_kind == resume_stop)
{
if (debug_threads)
/* Ignore (wildcard) resume requests for already-resumed
threads. */
- if (r->resume[ndx].kind != resume_stop
+ if (resume[ndx].kind != resume_stop
&& thread->last_resume_kind != resume_stop)
{
if (debug_threads)
reported to GDBserver core, but GDB has not pulled the
event out of the vStopped queue yet, likewise, ignore the
(wildcard) resume request. */
- if (in_queued_stop_replies (entry->id))
+ if (in_queued_stop_replies (thread->id))
{
if (debug_threads)
debug_printf ("not resuming LWP %ld: has queued stop reply\n",
continue;
}
- lwp->resume = &r->resume[ndx];
+ lwp->resume = &resume[ndx];
thread->last_resume_kind = lwp->resume->kind;
lwp->step_range_start = lwp->resume->step_range_start;
lwpid_of (thread));
}
- return 0;
+ return;
}
}
/* No resume action for this thread. */
lwp->resume = NULL;
-
- return 0;
}
/* find_inferior callback for linux_resume.
Set *FLAG_P if this lwp has an interesting status pending. */
-static int
-resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
+static bool
+resume_status_pending_p (thread_info *thread)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
/* LWPs which will not be resumed are not interesting, because
we might not wait for them next time through linux_wait. */
if (lwp->resume == NULL)
- return 0;
-
- if (thread_still_has_status_pending_p (thread))
- * (int *) flag_p = 1;
+ return false;
- return 0;
+ return thread_still_has_status_pending_p (thread);
}
/* Return 1 if this lwp that GDB wants running is stopped at an
required STOP_PC adjustment has already been propagated to the
inferior's regcache. */
-static int
-need_step_over_p (struct inferior_list_entry *entry, void *dummy)
+static bool
+need_step_over_p (thread_info *thread)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
struct thread_info *saved_thread;
CORE_ADDR pc;
/* GDBserver is skipping the extra traps from the wrapper program,
don't have to do step over. */
if (proc->tdesc == NULL)
- return 0;
+ return false;
/* LWPs which will not be resumed are not interesting, because we
might not wait for them next time through linux_wait. */
if (debug_threads)
debug_printf ("Need step over [LWP %ld]? Ignoring, not stopped\n",
lwpid_of (thread));
- return 0;
+ return false;
}
if (thread->last_resume_kind == resume_stop)
debug_printf ("Need step over [LWP %ld]? Ignoring, should remain"
" stopped\n",
lwpid_of (thread));
- return 0;
+ return false;
}
gdb_assert (lwp->suspended >= 0);
if (debug_threads)
debug_printf ("Need step over [LWP %ld]? Ignoring, suspended\n",
lwpid_of (thread));
- return 0;
+ return false;
}
if (lwp->status_pending_p)
debug_printf ("Need step over [LWP %ld]? Ignoring, has pending"
" status.\n",
lwpid_of (thread));
- return 0;
+ return false;
}
/* Note: PC, not STOP_PC. Either GDB has adjusted the PC already,
"Old stop_pc was 0x%s, PC is now 0x%s\n",
lwpid_of (thread),
paddress (lwp->stop_pc), paddress (pc));
- return 0;
+ return false;
}
/* On software single step target, resume the inferior with signal
" signals.\n",
lwpid_of (thread));
- return 0;
+ return false;
}
saved_thread = current_thread;
lwpid_of (thread), paddress (pc));
current_thread = saved_thread;
- return 0;
+ return false;
}
else
{
that find_inferior stops looking. */
current_thread = saved_thread;
- return 1;
+ return true;
}
}
" at 0x%s\n",
lwpid_of (thread), paddress (pc));
- return 0;
+ return false;
}
/* Start a step-over operation on LWP. When LWP stopped at a
linux_resume_one_lwp (lwp, step, 0, NULL);
/* Require next event from this LWP. */
- step_over_bkpt = thread->entry.id;
+ step_over_bkpt = thread->id;
return 1;
}
they should be re-issued if necessary. */
static int
-linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
+linux_resume_one_thread (thread_info *thread, void *arg)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
int leave_all_stopped = * (int *) arg;
int leave_pending;
if (debug_threads)
debug_printf ("resuming LWP %ld\n", lwpid_of (thread));
- proceed_one_lwp (entry, NULL);
+ proceed_one_lwp (thread, NULL);
}
else
{
static void
linux_resume (struct thread_resume *resume_info, size_t n)
{
- struct thread_resume_array array = { resume_info, n };
struct thread_info *need_step_over = NULL;
- int any_pending;
int leave_all_stopped;
if (debug_threads)
debug_printf ("linux_resume:\n");
}
- find_inferior (&all_threads, linux_set_resume_request, &array);
+ for_each_thread ([&] (thread_info *thread)
+ {
+ linux_set_resume_request (thread, resume_info, n);
+ });
/* If there is a thread which would otherwise be resumed, which has
a pending status, then don't resume any threads - we can just
would otherwise be sent. In non-stop mode, we'll apply this
logic to each thread individually. We consume all pending events
before considering to start a step-over (in all-stop). */
- any_pending = 0;
+ bool any_pending = false;
if (!non_stop)
- find_inferior (&all_threads, resume_status_pending_p, &any_pending);
+ any_pending = find_thread (resume_status_pending_p) != NULL;
/* If there is a thread which would otherwise be resumed, which is
stopped at a breakpoint that needs stepping over, then don't
to queue any signals that would otherwise be delivered or
queued. */
if (!any_pending && supports_breakpoints ())
- need_step_over
- = (struct thread_info *) find_inferior (&all_threads,
- need_step_over_p, NULL);
+ need_step_over = find_thread (need_step_over_p);
leave_all_stopped = (need_step_over != NULL || any_pending);
on that particular thread, and leave all others stopped. */
static int
-proceed_one_lwp (struct inferior_list_entry *entry, void *except)
+proceed_one_lwp (thread_info *thread, void *except)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
int step;
}
static int
-unsuspend_and_proceed_one_lwp (struct inferior_list_entry *entry, void *except)
+unsuspend_and_proceed_one_lwp (thread_info *thread, void *except)
{
- struct thread_info *thread = (struct thread_info *) entry;
struct lwp_info *lwp = get_thread_lwp (thread);
if (lwp == except)
lwp_suspended_decr (lwp);
- return proceed_one_lwp (entry, except);
+ return proceed_one_lwp (thread, except);
}
/* When we finish a step-over, set threads running again. If there's
if (supports_breakpoints ())
{
- need_step_over
- = (struct thread_info *) find_inferior (&all_threads,
- need_step_over_p, NULL);
+ need_step_over = find_thread (need_step_over_p);
if (need_step_over != NULL)
{
return linux_supports_traceexec ();
}
-/* Callback for 'find_inferior'. Set the (possibly changed) ptrace
- options for the specified lwp. */
-
-static int
-reset_lwp_ptrace_options_callback (struct inferior_list_entry *entry,
- void *args)
-{
- struct thread_info *thread = (struct thread_info *) entry;
- struct lwp_info *lwp = get_thread_lwp (thread);
-
- if (!lwp->stopped)
- {
- /* Stop the lwp so we can modify its ptrace options. */
- lwp->must_set_ptrace_flags = 1;
- linux_stop_lwp (lwp);
- }
- else
- {
- /* Already stopped; go ahead and set the ptrace options. */
- struct process_info *proc = find_process_pid (pid_of (thread));
- int options = linux_low_ptrace_options (proc->attached);
-
- linux_enable_event_reporting (lwpid_of (thread), options);
- lwp->must_set_ptrace_flags = 0;
- }
-
- return 0;
-}
-
/* Target hook for 'handle_new_gdb_connection'. Causes a reset of the
ptrace flags for all inferiors. This is in case the new GDB connection
doesn't support the same set of events that the previous one did. */
static void
linux_handle_new_gdb_connection (void)
{
- pid_t pid;
-
/* Request that all the lwps reset their ptrace options. */
- find_inferior (&all_threads, reset_lwp_ptrace_options_callback , &pid);
+ for_each_thread ([] (thread_info *thread)
+ {
+ struct lwp_info *lwp = get_thread_lwp (thread);
+
+ if (!lwp->stopped)
+ {
+ /* Stop the lwp so we can modify its ptrace options. */
+ lwp->must_set_ptrace_flags = 1;
+ linux_stop_lwp (lwp);
+ }
+ else
+ {
+ /* Already stopped; go ahead and set the ptrace options. */
+ struct process_info *proc = find_process_pid (pid_of (thread));
+ int options = linux_low_ptrace_options (proc->attached);
+
+ linux_enable_event_reporting (lwpid_of (thread), options);
+ lwp->must_set_ptrace_flags = 0;
+ }
+ });
}
static int
linux_supports_software_single_step,
linux_supports_catch_syscall,
linux_get_ipa_tdesc_idx,
+#if USE_THREAD_DB
+ thread_db_thread_handle,
+#else
+ NULL,
+#endif
};
#ifdef HAVE_LINUX_REGSETS