* 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.
This commit is contained in:
Pedro Alves 2009-04-01 22:29:33 +00:00
parent c35fafde7c
commit 2bd7c093f6
6 changed files with 89 additions and 63 deletions

View File

@ -1,3 +1,23 @@
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> 2009-04-01 Pedro Alves <pedro@codesourcery.com>
* linux-low.c (linux_wait_for_event): Don't clear the `stepping' * linux-low.c (linux_wait_for_event): Don't clear the `stepping'

View File

@ -116,7 +116,7 @@ static int new_inferior;
static void linux_resume_one_lwp (struct inferior_list_entry *entry, static void linux_resume_one_lwp (struct inferior_list_entry *entry,
int step, int signal, siginfo_t *info); 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 void stop_all_lwps (void);
static int linux_wait_for_event (struct thread_info *child); static int linux_wait_for_event (struct thread_info *child);
static int check_removed_breakpoint (struct lwp_info *event_child); static int check_removed_breakpoint (struct lwp_info *event_child);
@ -952,8 +952,8 @@ linux_wait (char *status)
{ {
struct thread_resume resume_info; struct thread_resume resume_info;
resume_info.thread = -1; resume_info.thread = -1;
resume_info.step = resume_info.sig = resume_info.leave_stopped = 0; resume_info.step = resume_info.sig = 0;
linux_resume (&resume_info); linux_resume (&resume_info, 1);
} }
} }
@ -1247,7 +1247,11 @@ linux_resume_one_lwp (struct inferior_list_entry *entry,
} }
} }
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 /* 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 in RESUME_PTR, and mark the thread with a pointer to the appropriate
@ -1256,21 +1260,29 @@ static struct thread_resume *resume_ptr;
This algorithm is O(threads * resume elements), but resume elements This algorithm is O(threads * resume elements), but resume elements
is small (and will remain small at least until GDB supports thread is small (and will remain small at least until GDB supports thread
suspension). */ suspension). */
static void static int
linux_set_resume_request (struct inferior_list_entry *entry) linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
{ {
struct lwp_info *lwp; struct lwp_info *lwp;
struct thread_info *thread; struct thread_info *thread;
int ndx; int ndx;
struct thread_resume_array *r;
thread = (struct thread_info *) entry; thread = (struct thread_info *) entry;
lwp = get_thread_lwp (thread); lwp = get_thread_lwp (thread);
r = arg;
ndx = 0; for (ndx = 0; ndx < r->n; ndx++)
while (resume_ptr[ndx].thread != -1 && resume_ptr[ndx].thread != entry->id) if (r->resume[ndx].thread == -1 || r->resume[ndx].thread == entry->id)
ndx++; {
lwp->resume = &r->resume[ndx];
return 0;
}
lwp->resume = &resume_ptr[ndx]; /* No resume action for this thread. */
lwp->resume = NULL;
return 0;
} }
/* This function is called once per thread. We check the thread's resume /* This function is called once per thread. We check the thread's resume
@ -1289,7 +1301,7 @@ linux_continue_one_thread (struct inferior_list_entry *entry)
thread = (struct thread_info *) entry; thread = (struct thread_info *) entry;
lwp = get_thread_lwp (thread); lwp = get_thread_lwp (thread);
if (lwp->resume->leave_stopped) if (lwp->resume == NULL)
return; return;
if (lwp->resume->thread == -1 if (lwp->resume->thread == -1
@ -1320,7 +1332,7 @@ linux_queue_one_thread (struct inferior_list_entry *entry)
thread = (struct thread_info *) entry; thread = (struct thread_info *) entry;
lwp = get_thread_lwp (thread); lwp = get_thread_lwp (thread);
if (lwp->resume->leave_stopped) if (lwp->resume == NULL)
return; return;
/* If we have a new signal, enqueue the signal. */ /* If we have a new signal, enqueue the signal. */
@ -1354,7 +1366,7 @@ resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
/* Processes which will not be resumed are not interesting, because /* Processes which will not be resumed are not interesting, because
we might not wait for them next time through linux_wait. */ we might not wait for them next time through linux_wait. */
if (lwp->resume->leave_stopped) if (lwp->resume == NULL)
return 0; return 0;
/* If this thread has a removed breakpoint, we won't have any /* If this thread has a removed breakpoint, we won't have any
@ -1375,14 +1387,12 @@ resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
} }
static void static void
linux_resume (struct thread_resume *resume_info) linux_resume (struct thread_resume *resume_info, size_t n)
{ {
int pending_flag; int pending_flag;
struct thread_resume_array array = { resume_info, n };
/* Yes, the use of a global here is rather ugly. */ find_inferior (&all_threads, linux_set_resume_request, &array);
resume_ptr = resume_info;
for_each_inferior (&all_threads, linux_set_resume_request);
/* If there is a thread which would otherwise be resumed, which /* If there is a thread which would otherwise be resumed, which
has a pending status, then don't resume any threads - we can just has a pending status, then don't resume any threads - we can just

View File

@ -146,7 +146,6 @@ start_inferior (char **argv, char *statusptr)
resume_info.thread = -1; resume_info.thread = -1;
resume_info.step = 0; resume_info.step = 0;
resume_info.sig = 0; resume_info.sig = 0;
resume_info.leave_stopped = 0;
sig = mywait (statusptr, 0); sig = mywait (statusptr, 0);
if (*statusptr != 'T') if (*statusptr != 'T')
@ -154,7 +153,7 @@ start_inferior (char **argv, char *statusptr)
do do
{ {
(*the_target->resume) (&resume_info); (*the_target->resume) (&resume_info, 1);
sig = mywait (statusptr, 0); sig = mywait (statusptr, 0);
if (*statusptr != 'T') if (*statusptr != 'T')
@ -1056,7 +1055,8 @@ handle_v_cont (char *own_buf, char *status, int *signal)
{ {
char *p, *q; char *p, *q;
int n = 0, i = 0; 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 /* Count the number of semicolons in the packet. There should be one
for every action. */ for every action. */
@ -1067,26 +1067,16 @@ handle_v_cont (char *own_buf, char *status, int *signal)
p++; p++;
p = strchr (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 resume_info = malloc (n * sizeof (resume_info[0]));
slot. */
resume_info = malloc ((n + 1) * sizeof (resume_info[0]));
if (resume_info == NULL) if (resume_info == NULL)
goto err; goto err;
default_action.thread = -1;
default_action.leave_stopped = 1;
default_action.step = 0;
default_action.sig = 0;
p = &own_buf[5]; p = &own_buf[5];
i = 0;
while (*p) while (*p)
{ {
p++; p++;
resume_info[i].leave_stopped = 0;
if (p[0] == 's' || p[0] == 'S') if (p[0] == 's' || p[0] == 'S')
resume_info[i].step = 1; resume_info[i].step = 1;
else if (p[0] == 'c' || p[0] == 'C') else if (p[0] == 'c' || p[0] == 'C')
@ -1141,7 +1131,8 @@ handle_v_cont (char *own_buf, char *status, int *signal)
} }
} }
resume_info[i] = default_action; if (i < n)
resume_info[i] = default_action;
/* Still used in occasional places in the backend. */ /* Still used in occasional places in the backend. */
if (n == 1 && resume_info[0].thread != -1) if (n == 1 && resume_info[0].thread != -1)
@ -1151,7 +1142,7 @@ handle_v_cont (char *own_buf, char *status, int *signal)
set_desired_inferior (0); set_desired_inferior (0);
enable_async_io (); enable_async_io ();
(*the_target->resume) (resume_info); (*the_target->resume) (resume_info, n);
free (resume_info); free (resume_info);
@ -1333,25 +1324,31 @@ myresume (char *own_buf, int step, int *signalp, char *statusp)
struct thread_resume resume_info[2]; struct thread_resume resume_info[2];
int n = 0; int n = 0;
int sig = *signalp; int sig = *signalp;
int valid_cont_thread;
set_desired_inferior (0); 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 resume_info[0].thread
= ((struct inferior_list_entry *) current_inferior)->id; = ((struct inferior_list_entry *) current_inferior)->id;
resume_info[0].step = step; resume_info[0].step = step;
resume_info[0].sig = sig; resume_info[0].sig = sig;
resume_info[0].leave_stopped = 0;
n++; n++;
} }
resume_info[n].thread = -1;
resume_info[n].step = 0; if (!valid_cont_thread)
resume_info[n].sig = 0; {
resume_info[n].leave_stopped = (cont_thread != 0 && cont_thread != -1); resume_info[n].thread = -1;
resume_info[n].step = 0;
resume_info[n].sig = 0;
n++;
}
enable_async_io (); enable_async_io ();
(*the_target->resume) (resume_info); (*the_target->resume) (resume_info, n);
*signalp = mywait (statusp, 1); *signalp = mywait (statusp, 1);
prepare_resume_reply (own_buf, *statusp, *signalp); prepare_resume_reply (own_buf, *statusp, *signalp);
disable_async_io (); disable_async_io ();

View File

@ -345,24 +345,27 @@ spu_thread_alive (unsigned long tid)
/* Resume process. */ /* Resume process. */
static void static void
spu_resume (struct thread_resume *resume_info) spu_resume (struct thread_resume *resume_info, size_t n)
{ {
while (resume_info->thread != -1 size_t i;
&& resume_info->thread != current_tid)
resume_info++;
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; return;
/* We don't support hardware single-stepping right now, assume /* We don't support hardware single-stepping right now, assume
GDB knows to use software single-stepping. */ GDB knows to use software single-stepping. */
if (resume_info->step) if (resume_info[i].step)
fprintf (stderr, "Hardware single-step not supported.\n"); fprintf (stderr, "Hardware single-step not supported.\n");
regcache_invalidate (); regcache_invalidate ();
errno = 0; errno = 0;
ptrace (PTRACE_CONT, current_tid, 0, resume_info->sig); ptrace (PTRACE_CONT, current_tid, 0, resume_info[i].sig);
if (errno) if (errno)
perror_with_name ("ptrace"); perror_with_name ("ptrace");
} }

View File

@ -22,18 +22,15 @@
#ifndef TARGET_H #ifndef TARGET_H
#define TARGET_H #define TARGET_H
/* This structure describes how to resume a particular thread (or /* This structure describes how to resume a particular thread (or all
all threads) based on the client's request. If thread is -1, then threads) based on the client's request. If thread is -1, then this
this entry applies to all threads. These are generally passed around entry applies to all threads. These are passed around as an
as an array, and terminated by a thread == -1 entry. */ array. */
struct thread_resume struct thread_resume
{ {
unsigned long thread; unsigned long thread;
/* If non-zero, leave this thread stopped. */
int leave_stopped;
/* If non-zero, we want to single-step. */ /* If non-zero, we want to single-step. */
int step; int step;
@ -83,7 +80,7 @@ struct target_ops
/* Resume the inferior process. */ /* 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. /* Wait for the inferior process to change state.

View File

@ -90,7 +90,7 @@ typedef BOOL WINAPI (*winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
typedef BOOL WINAPI (*winapi_DebugBreakProcess) (HANDLE); typedef BOOL WINAPI (*winapi_DebugBreakProcess) (HANDLE);
typedef BOOL WINAPI (*winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD); 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 /* Get the thread ID from the current selected inferior (the current
thread). */ thread). */
@ -726,8 +726,7 @@ win32_detach (void)
resume.thread = -1; resume.thread = -1;
resume.step = 0; resume.step = 0;
resume.sig = 0; resume.sig = 0;
resume.leave_stopped = 0; win32_resume (&resume, 1);
win32_resume (&resume);
} }
if (!DebugActiveProcessStop (current_process_id)) if (!DebugActiveProcessStop (current_process_id))
@ -771,7 +770,7 @@ win32_thread_alive (unsigned long tid)
/* Resume the inferior process. RESUME_INFO describes how we want /* Resume the inferior process. RESUME_INFO describes how we want
to resume. */ to resume. */
static void static void
win32_resume (struct thread_resume *resume_info) win32_resume (struct thread_resume *resume_info, size_t n)
{ {
DWORD tid; DWORD tid;
enum target_signal sig; enum target_signal sig;
@ -782,9 +781,9 @@ win32_resume (struct thread_resume *resume_info)
/* This handles the very limited set of resume packets that GDB can /* This handles the very limited set of resume packets that GDB can
currently produce. */ currently produce. */
if (resume_info[0].thread == -1) if (n == 1 && resume_info[0].thread == -1)
tid = -1; tid = -1;
else if (resume_info[1].thread == -1 && !resume_info[1].leave_stopped) else if (n > 1)
tid = -1; tid = -1;
else else
/* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make /* Yes, we're ignoring resume_info[0].thread. It'd be tricky to make