(struct target_ops): Add a `n' argument to the `resume' callback.
* server.c (start_inferior): Adjust.
(handle_v_cont, myresume): Adjust.
* linux-low.c (check_removed_breakpoint): Adjust to resume
interface change, and to removed leave_stopped field.
(resume_ptr): Delete.
(struct thread_resume_array): New.
(linux_set_resume_request): Add new `arg' parameter. Adjust to
resume interface change.
(linux_continue_one_thread, linux_queue_one_thread)
(resume_status_pending_p): Check if the resume field is NULL
instead of checking the leave_stopped member.
(linux_resume): Adjust to the target resume interface change.
* spu-low.c (spu_resume): Adjust to the target resume interface
change.
* win32-low.c (win32_detach, win32_resume): Ditto.
+2009-04-01 Pedro Alves <pedro@codesourcery.com>
+
+ * target.h (struct thread_resume): Delete leave_stopped member.
+ (struct target_ops): Add a `n' argument to the `resume' callback.
+ * server.c (start_inferior): Adjust.
+ (handle_v_cont, myresume): Adjust.
+ * linux-low.c (check_removed_breakpoint): Adjust to resume
+ interface change, and to removed leave_stopped field.
+ (resume_ptr): Delete.
+ (struct thread_resume_array): New.
+ (linux_set_resume_request): Add new `arg' parameter. Adjust to
+ resume interface change.
+ (linux_continue_one_thread, linux_queue_one_thread)
+ (resume_status_pending_p): Check if the resume field is NULL
+ instead of checking the leave_stopped member.
+ (linux_resume): Adjust to the target resume interface change.
+ * spu-low.c (spu_resume): Adjust to the target resume interface
+ change.
+ * win32-low.c (win32_detach, win32_resume): Ditto.
+
2009-04-01 Pedro Alves <pedro@codesourcery.com>
* linux-low.c (linux_wait_for_event): Don't clear the `stepping'
static void linux_resume_one_lwp (struct inferior_list_entry *entry,
int step, int signal, siginfo_t *info);
-static void linux_resume (struct thread_resume *resume_info);
+static void linux_resume (struct thread_resume *resume_info, size_t n);
static void stop_all_lwps (void);
static int linux_wait_for_event (struct thread_info *child);
static int check_removed_breakpoint (struct lwp_info *event_child);
{
struct thread_resume resume_info;
resume_info.thread = -1;
- resume_info.step = resume_info.sig = resume_info.leave_stopped = 0;
- linux_resume (&resume_info);
+ resume_info.step = resume_info.sig = 0;
+ linux_resume (&resume_info, 1);
}
}
}
}
-static struct thread_resume *resume_ptr;
+struct thread_resume_array
+{
+ struct thread_resume *resume;
+ size_t n;
+};
/* This function is called once per thread. We look up the thread
in RESUME_PTR, and mark the thread with a pointer to the appropriate
This algorithm is O(threads * resume elements), but resume elements
is small (and will remain small at least until GDB supports thread
suspension). */
-static void
-linux_set_resume_request (struct inferior_list_entry *entry)
+static int
+linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
{
struct lwp_info *lwp;
struct thread_info *thread;
int ndx;
+ struct thread_resume_array *r;
thread = (struct thread_info *) entry;
lwp = get_thread_lwp (thread);
+ r = arg;
- ndx = 0;
- while (resume_ptr[ndx].thread != -1 && resume_ptr[ndx].thread != entry->id)
- ndx++;
+ for (ndx = 0; ndx < r->n; ndx++)
+ if (r->resume[ndx].thread == -1 || r->resume[ndx].thread == entry->id)
+ {
+ lwp->resume = &r->resume[ndx];
+ return 0;
+ }
+
+ /* No resume action for this thread. */
+ lwp->resume = NULL;
- lwp->resume = &resume_ptr[ndx];
+ return 0;
}
/* This function is called once per thread. We check the thread's resume
thread = (struct thread_info *) entry;
lwp = get_thread_lwp (thread);
- if (lwp->resume->leave_stopped)
+ if (lwp->resume == NULL)
return;
if (lwp->resume->thread == -1
thread = (struct thread_info *) entry;
lwp = get_thread_lwp (thread);
- if (lwp->resume->leave_stopped)
+ if (lwp->resume == NULL)
return;
/* If we have a new signal, enqueue the signal. */
/* Processes which will not be resumed are not interesting, because
we might not wait for them next time through linux_wait. */
- if (lwp->resume->leave_stopped)
+ if (lwp->resume == NULL)
return 0;
/* If this thread has a removed breakpoint, we won't have any
}
static void
-linux_resume (struct thread_resume *resume_info)
+linux_resume (struct thread_resume *resume_info, size_t n)
{
int pending_flag;
+ struct thread_resume_array array = { resume_info, n };
- /* Yes, the use of a global here is rather ugly. */
- resume_ptr = resume_info;
-
- for_each_inferior (&all_threads, linux_set_resume_request);
+ find_inferior (&all_threads, linux_set_resume_request, &array);
/* If there is a thread which would otherwise be resumed, which
has a pending status, then don't resume any threads - we can just
resume_info.thread = -1;
resume_info.step = 0;
resume_info.sig = 0;
- resume_info.leave_stopped = 0;
sig = mywait (statusptr, 0);
if (*statusptr != 'T')
do
{
- (*the_target->resume) (&resume_info);
+ (*the_target->resume) (&resume_info, 1);
sig = mywait (statusptr, 0);
if (*statusptr != 'T')
{
char *p, *q;
int n = 0, i = 0;
- struct thread_resume *resume_info, default_action;
+ struct thread_resume *resume_info;
+ struct thread_resume default_action = {0};
/* Count the number of semicolons in the packet. There should be one
for every action. */
p++;
p = strchr (p, ';');
}
- /* Allocate room for one extra action, for the default remain-stopped
- behavior; if no default action is in the list, we'll need the extra
- slot. */
- resume_info = malloc ((n + 1) * sizeof (resume_info[0]));
+
+ resume_info = malloc (n * sizeof (resume_info[0]));
if (resume_info == NULL)
goto err;
- default_action.thread = -1;
- default_action.leave_stopped = 1;
- default_action.step = 0;
- default_action.sig = 0;
-
p = &own_buf[5];
- i = 0;
while (*p)
{
p++;
- resume_info[i].leave_stopped = 0;
-
if (p[0] == 's' || p[0] == 'S')
resume_info[i].step = 1;
else if (p[0] == 'c' || p[0] == 'C')
}
}
- resume_info[i] = default_action;
+ if (i < n)
+ resume_info[i] = default_action;
/* Still used in occasional places in the backend. */
if (n == 1 && resume_info[0].thread != -1)
set_desired_inferior (0);
enable_async_io ();
- (*the_target->resume) (resume_info);
+ (*the_target->resume) (resume_info, n);
free (resume_info);
struct thread_resume resume_info[2];
int n = 0;
int sig = *signalp;
+ int valid_cont_thread;
set_desired_inferior (0);
- if (step || sig || (cont_thread != 0 && cont_thread != -1))
+ valid_cont_thread = (cont_thread != 0 && cont_thread != -1);
+
+ if (step || sig || valid_cont_thread)
{
resume_info[0].thread
= ((struct inferior_list_entry *) current_inferior)->id;
resume_info[0].step = step;
resume_info[0].sig = sig;
- resume_info[0].leave_stopped = 0;
n++;
}
- resume_info[n].thread = -1;
- resume_info[n].step = 0;
- resume_info[n].sig = 0;
- resume_info[n].leave_stopped = (cont_thread != 0 && cont_thread != -1);
+
+ if (!valid_cont_thread)
+ {
+ resume_info[n].thread = -1;
+ resume_info[n].step = 0;
+ resume_info[n].sig = 0;
+ n++;
+ }
enable_async_io ();
- (*the_target->resume) (resume_info);
+ (*the_target->resume) (resume_info, n);
*signalp = mywait (statusp, 1);
prepare_resume_reply (own_buf, *statusp, *signalp);
disable_async_io ();
/* Resume process. */
static void
-spu_resume (struct thread_resume *resume_info)
+spu_resume (struct thread_resume *resume_info, size_t n)
{
- while (resume_info->thread != -1
- && resume_info->thread != current_tid)
- resume_info++;
+ size_t i;
- if (resume_info->leave_stopped)
+ for (i = 0; i < n; i++)
+ if (resume_info[i].thread == -1
+ || resume_info[i].thread == current_tid)
+ break;
+
+ if (i == n)
return;
/* We don't support hardware single-stepping right now, assume
GDB knows to use software single-stepping. */
- if (resume_info->step)
+ if (resume_info[i].step)
fprintf (stderr, "Hardware single-step not supported.\n");
regcache_invalidate ();
errno = 0;
- ptrace (PTRACE_CONT, current_tid, 0, resume_info->sig);
+ ptrace (PTRACE_CONT, current_tid, 0, resume_info[i].sig);
if (errno)
perror_with_name ("ptrace");
}
#ifndef TARGET_H
#define TARGET_H
-/* This structure describes how to resume a particular thread (or
- all threads) based on the client's request. If thread is -1, then
- this entry applies to all threads. These are generally passed around
- as an array, and terminated by a thread == -1 entry. */
+/* This structure describes how to resume a particular thread (or all
+ threads) based on the client's request. If thread is -1, then this
+ entry applies to all threads. These are passed around as an
+ array. */
struct thread_resume
{
unsigned long thread;
- /* If non-zero, leave this thread stopped. */
- int leave_stopped;
-
/* If non-zero, we want to single-step. */
int step;
/* Resume the inferior process. */
- void (*resume) (struct thread_resume *resume_info);
+ void (*resume) (struct thread_resume *resume_info, size_t n);
/* Wait for the inferior process to change state.
typedef BOOL WINAPI (*winapi_DebugBreakProcess) (HANDLE);
typedef BOOL WINAPI (*winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
-static void win32_resume (struct thread_resume *resume_info);
+static void win32_resume (struct thread_resume *resume_info, size_t n);
/* Get the thread ID from the current selected inferior (the current
thread). */
resume.thread = -1;
resume.step = 0;
resume.sig = 0;
- resume.leave_stopped = 0;
- win32_resume (&resume);
+ win32_resume (&resume, 1);
}
if (!DebugActiveProcessStop (current_process_id))
/* Resume the inferior process. RESUME_INFO describes how we want
to resume. */
static void
-win32_resume (struct thread_resume *resume_info)
+win32_resume (struct thread_resume *resume_info, size_t n)
{
DWORD tid;
enum target_signal sig;
/* This handles the very limited set of resume packets that GDB can
currently produce. */
- if (resume_info[0].thread == -1)
+ if (n == 1 && resume_info[0].thread == -1)
tid = -1;
- else if (resume_info[1].thread == -1 && !resume_info[1].leave_stopped)
+ else if (n > 1)
tid = -1;
else
/* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make