From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 102798 invoked by alias); 19 Jul 2016 20:31:30 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 102754 invoked by uid 440); 19 Jul 2016 20:31:29 -0000 Date: Tue, 19 Jul 2016 20:31:00 -0000 Message-ID: <20160719203129.102717.qmail@sourceware.org> From: scox@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] scox/globalstate: Support successive notifications. X-Git-Refname: refs/heads/scox/globalstate X-Git-Reftype: branch X-Git-Oldrev: d7a6805f1d4956568ca5f2fb995bb84d522f97ba X-Git-Newrev: 4739424d4a0d9ee8505b47434df6565c5271c353 X-SW-Source: 2016-q3/txt/msg00001.txt.bz2 List-Id: The branch, scox/globalstate has been updated via 4739424d4a0d9ee8505b47434df6565c5271c353 (commit) from d7a6805f1d4956568ca5f2fb995bb84d522f97ba (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 4739424d4a0d9ee8505b47434df6565c5271c353 Author: Stan Cox Date: Tue Jul 19 16:30:09 2016 -0400 Support successive notifications. * server.c (get_packet_type): Add Hg,m,M,g,G (is_waiter): New. (setup_multiplexing): Send shadow client notification when vStopped received. (notify_clients): Add have_first_notify to indicate if this is an initial notification. Handle first and successive notify case. (handle_monitor_command): Display thread info for client state * server.h (new_general_thread): Intended for synchronizing multiple client threads. (in_buffer): Renamed notify_buffer. * gdb.server/multi-client.exp (testpath5): Added multi-threads.c test. ----------------------------------------------------------------------- Summary of changes: gdb/gdbserver/ChangeLog | 13 ++ gdb/gdbserver/notif.c | 3 +- gdb/gdbserver/server.c | 209 +++++++++++++++++-------- gdb/gdbserver/server.h | 9 +- gdb/testsuite/ChangeLog | 4 + gdb/testsuite/gdb.server/multi-client.exp | 235 ++++++++++++++++++++++------- 6 files changed, 349 insertions(+), 124 deletions(-) First 500 lines of diff: diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 231b91e..1f4425d 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,16 @@ +2016-07-19 Stan Cox + + * server.c (get_packet_type): Add Hg,m,M,g,G + (is_waiter): New. + (setup_multiplexing): Send shadow client notification when + vStopped received. + (notify_clients): Add have_first_notify to indicate if this is an + initial notification. Handle first and successive notify case. + (handle_monitor_command): Display thread info for client state + * server.h (new_general_thread): Intended for synchronizing + multiple client threads. + (in_buffer): Renamed notify_buffer. + 2016-06-08 Stan Cox * server.c (add_client_by_pid) Check all/non stop mode equivalence. diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c index 98e1b4d..8a7900b 100644 --- a/gdb/gdbserver/notif.c +++ b/gdb/gdbserver/notif.c @@ -67,6 +67,7 @@ notif_write_event (struct notif_server *notif, char *own_buf) = QUEUE_peek (notif_event_p, notif->queue); notif->write (event, own_buf); + notify_clients (own_buf, 0); } else write_ok (own_buf); @@ -150,7 +151,7 @@ notif_push (struct notif_server *np, struct notif_event *new_event) p += strlen (p); np->write (new_event, p); - if (notify_clients (buf)) + if (notify_clients (buf, 1)) putpkt_notif (buf); } } diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index b0206c6..1d5f326 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -85,11 +85,11 @@ static struct client_states client_states; static void handle_status (char *); -enum pending_types {none_pending, pending_waitee, pending_cont_waiter, pending_step_waiter, pending_stop}; -char *pending_types_str[] = {"not-waiting","waitee","waiter","step-waiter","stop", "notifier"}; +enum pending_types {none_pending, pending_waitee, pending_cont_waiter, pending_step_waiter}; +char *pending_types_str[] = {"not-waiting","waitee","waiter","step-waiter"}; enum nonstop_pending_types {no_notifier_pending, pending_notifier, pending_notified}; char *nonstop_pending_types_str[] = {"", "notifier", "notified"}; -char *packet_types_str[] = {"other", "vContc", "vConts","vContt","vRun", "vAttach"}; +char *packet_types_str[] = {"other", "vContc", "vConts","vContt","vRun", "vAttach", "Hg", "g_or_m", "vStopped"}; char *waitkind_str[] = {"exited", "stopped", "signalled", "loaded", "forked", "vforked", "execed", "vfork-done", "syscall-entry", "syscall-exit", "spurious", "ignore", "no-history", "not-resumed", "thread-created", "thread-exited", ""}; @@ -153,7 +153,7 @@ set_client_state (gdb_fildes_t fd) cs->packet_type = other_packet; cs->last_packet_type = other_packet; cs->pending = none_pending; - cs->in_buffer_ = NULL; + cs->notify_buffer_ = NULL; cs->own_buffer_ = xmalloc (PBUFSIZ + 1); cs->client_breakpoints = NULL; client_states.current_cs = cs; @@ -260,8 +260,8 @@ static void free_client_state (client_state *cs) if (csi == NULL) XDELETE (cs->ss); - if (cs->in_buffer_) - xfree (cs->in_buffer_); + if (cs->notify_buffer_) + xfree (cs->notify_buffer_); xfree (cs->own_buffer_); XDELETE (cs); } @@ -329,7 +329,7 @@ add_client_by_pid (int pid) { if (cs != matched_cs && matched_cs->ss->general_thread_.pid == pid) { - // Do clients all/non stop modes match? + /* Do clients all/non stop modes match? */ if (cs->non_stop_ ^ matched_cs->non_stop_) return -1; /* reuse the matched server state */ @@ -429,8 +429,8 @@ get_packet_type (client_state *cs) { char own_packet; - if (in_buffer) - own_packet = in_buffer[0]; + if (own_buffer) + own_packet = own_buffer[0]; else return other_packet; /* We have already categorized the packet type */ @@ -441,22 +441,44 @@ get_packet_type (client_state *cs) switch (own_packet) { case 'v': - if ((strncmp (in_buffer, "vCont;c", 7) == 0)) + if ((strncmp (own_buffer, "vCont;c", 7) == 0)) return vContc; - else if ((strncmp (in_buffer, "vCont;r", 7) == 0) - || (strncmp (in_buffer, "vCont;s", 7) == 0)) + else if ((strncmp (own_buffer, "vCont;r", 7) == 0) + || (strncmp (own_buffer, "vCont;s", 7) == 0)) return vConts; - else if ((strncmp (in_buffer, "vCont;t", 7) == 0)) + else if ((strncmp (own_buffer, "vCont;t", 7) == 0)) return vContt; - else if (strncmp (in_buffer, "vRun", 4) == 0) + else if (strncmp (own_buffer, "vRun", 4) == 0) return vRun; - else if (strncmp (in_buffer, "vAttach", 4) == 0) + else if (strncmp (own_buffer, "vAttach", 4) == 0) return vAttach; - default: - return other_packet; + else if (strncmp (own_buffer, "vStopped", 4) == 0) + return vStopped; + break; + case 'H': + if (own_buffer[1] == 'g') + { + client_states.current_cs->new_general_thread = read_ptid (&own_buffer[2], NULL); + return Hg; + } + case 'm': + case 'M': + case 'g': + case 'G': + return g_or_m; }; + return other_packet; +} + +static int is_waiter (client_state *cs) +{ + return ((cs->packet_type == vContc + || cs->packet_type == vConts) + && (cs->pending == pending_cont_waiter + || cs->pending == pending_step_waiter)); } + static int queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg); /* Belatedly reply to client CS, which is waiting on a packet reply. */ @@ -537,7 +559,7 @@ resolve_waiter (client_state *cs, client_state *waitee_cs) find_inferior (&all_threads, queue_stop_reply_callback, NULL); notif_write_event (¬if_stop, notif_buf); out_buf = alloca (strlen (notif_buf) + 8); - // TODO Use Defined notif constant + /* TODO Use Defined notif constant */ strcpy (out_buf, "Stop:"); strcat (out_buf, notif_buf); if (debug_threads) @@ -550,7 +572,6 @@ resolve_waiter (client_state *cs, client_state *waitee_cs) } case vRun: { - /* reply to vRun with an OK */ strcpy (own_buffer, "OK"); putpkt (own_buffer); break; @@ -564,18 +585,18 @@ resolve_waiter (client_state *cs, client_state *waitee_cs) static void -analyze_group (client_state *current_cs, int *have_nonwaiter) +analyze_group (client_state *current_cs, int *have_waitee) { client_state *csi; - *have_nonwaiter = 0; + *have_waitee = 0; for (csi = client_states.first->next; csi != NULL; csi = csi->next) { if (attached_to_same_proc (current_cs, csi)) { if (csi->pending == pending_waitee || csi->pending == none_pending) - *have_nonwaiter += 1; + *have_waitee += 1; } } } @@ -613,6 +634,17 @@ setup_multiplexing (client_state *current_cs) if (current_cs->packet_type == vContc || current_cs->packet_type == vConts) current_cs->nonstop_pending = none_pending; + if (current_cs->packet_type == vStopped && notify_buffer) + { + char okay_buf[4]; + write_ok (okay_buf); + putpkt (okay_buf); + putpkt_notif (notify_buffer); + xfree (notify_buffer); + notify_buffer = 0; + return 0; + } + for (same_pid_cs = client_states.first; same_pid_cs != NULL; same_pid_cs = same_pid_cs->next) @@ -623,6 +655,17 @@ setup_multiplexing (client_state *current_cs) if (non_stop && (same_pid_cs->catch_syscalls)) continue; + /* TODO Protect against a shadow client changing the current thread. + This attempted to do that but was invasive. + So is intercepting Hg packets */ + if (0 && current_cs->packet_type == g_or_m) + if (!ptid_equal (same_pid_cs->new_general_thread, current_cs->new_general_thread)) + { + sprintf (own_buffer, "E00"); + putpkt (own_buffer); + return 0; + } + switch (same_pid_cs->pending) { case /* same_pid_cs->pending */ none_pending: @@ -671,11 +714,11 @@ setup_multiplexing (client_state *current_cs) /* Current client is continuing and found another waiter client */ case /* current_cs->packet_type */ vContc: { - int have_nonwaiter; - analyze_group (current_cs, &have_nonwaiter); + int have_waitee; + analyze_group (current_cs, &have_waitee); dump_client_state (__FUNCTION__, "waitee/waiter switch"); /* Don't want to deadlock on everyone waiting */ - if (current_cs->pending == pending_waitee && have_nonwaiter) + if (current_cs->pending == pending_waitee && have_waitee) current_cs->pending = pending_cont_waiter; } break; @@ -715,7 +758,6 @@ setup_multiplexing (client_state *current_cs) { case pending_cont_waiter: case pending_step_waiter: - case pending_stop: switch (current_cs->last_packet_type) { case vRun: @@ -740,8 +782,10 @@ setup_multiplexing (client_state *current_cs) } +/* Send a notification to a shadow client. */ + int -notify_clients (char *buffer) +notify_clients (char *buffer, int have_first_notify) { client_state *same_pid_cs = NULL; int save_client_fd = client_states.current_fd; @@ -749,7 +793,6 @@ notify_clients (char *buffer) char *okay_buf = alloca (4); int have_syscall = 0; - debug_printf ("%s DBG %s %s\n", __FUNCTION__, target_waitstatus_to_string (&last_status), own_buffer); dump_client_state (__FUNCTION__, ""); write_ok (okay_buf); @@ -758,7 +801,7 @@ notify_clients (char *buffer) same_pid_cs != NULL; same_pid_cs = same_pid_cs->next) { - /* Insure another client is attached to the cs process */ + /* Is this a client attached to the same process? */ if (! attached_to_same_proc (client_states.current_cs, same_pid_cs)) continue; @@ -775,7 +818,8 @@ notify_clients (char *buffer) set_client_state (save_client_fd); return 1; case TARGET_WAITKIND_STOPPED: - if (same_pid_cs->pending == pending_cont_waiter && same_pid_cs->packet_type == vContc) + if ((same_pid_cs->pending == pending_cont_waiter + && same_pid_cs->packet_type == vContc)) { CORE_ADDR point_addr; struct regcache *regcache = same_pid_cs->ss->current_thread_->regcache_data; @@ -783,9 +827,12 @@ notify_clients (char *buffer) if (has_client_breakpoint_at (point_addr)) same_pid_cs->nonstop_pending = pending_notifier; } - + /* Have more than 1 notify so also send to shadow client */ + if (save_client_cs->packet_type == vStopped) + same_pid_cs->nonstop_pending = pending_notifier; + default: - /* A syscall client only gets a syscall packet */ + /* Only syscall clients need to see a syscall packet */ if (save_client_cs->catch_syscalls) { set_client_state (same_pid_cs->file_desc); @@ -793,19 +840,38 @@ notify_clients (char *buffer) } } - // syscall continue was erroneously caught by by a non syscall client + /* syscall continue was erroneously caught by by a non syscall client */ if (save_client_cs->packet_type == other_packet - && same_pid_cs->catch_syscalls) + && same_pid_cs->catch_syscalls) return 0; + /* client wants the notification */ if (same_pid_cs->nonstop_pending == pending_notifier) { /* Also send the notification to the attached client */ set_client_state (same_pid_cs->file_desc); - putpkt (okay_buf); if (debug_threads) debug_printf ("%s:%d Notifying fd=%d\n", __FUNCTION__, __LINE__, same_pid_cs->file_desc); - putpkt_notif (buffer); + /* This is the first notification */ + if (have_first_notify + && (is_waiter (same_pid_cs) + || (save_client_cs->packet_type != vStopped + && same_pid_cs->nonstop_pending == pending_notifier))) + { + putpkt (okay_buf); + putpkt_notif (buffer); + } + else /* This is another notification in the group */ + { + if (same_pid_cs->packet_type == vStopped) + putpkt (buffer); + else + { + /* send notify after we receive vStopped */ + same_pid_cs->notify_buffer_ = xmalloc (strlen (buffer) + 1); + memcpy (same_pid_cs->notify_buffer_, buffer, strlen (buffer) + 1); + } + } set_client_state (save_client_fd); same_pid_cs->pending = none_pending; same_pid_cs->nonstop_pending = pending_notified; @@ -813,8 +879,6 @@ notify_clients (char *buffer) } if (have_syscall && !save_client_cs->catch_syscalls) return 0; - else if (save_client_cs->nonstop_pending == pending_notified) - return 0; else return 1; } @@ -852,6 +916,7 @@ do_multiplexing (client_state *current_cs) switch (current_cs->packet_type) { case other_packet: + case Hg: break; case vContt: if (current_cs->last_packet_type == vAttach) @@ -2099,25 +2164,49 @@ handle_monitor_command (char *mon, char *own_buf) else if (strcmp (mon, "client status") == 0) { client_state *csidx; - char *result = NULL; + char *result = ""; + char *old_result = NULL; for (csidx = client_states.first; csidx != NULL; csidx = csidx->next) - if (csidx->pending) - { - if (result) - asprintf (&result, "%sFile descriptor %d, pid %d, is %s with a current %s request\n", result, csidx->file_desc, ptid_get_pid (csidx->ss->general_thread_), pending_types_str[csidx->pending], packet_types_str[csidx->packet_type]); - else - asprintf (&result, "File descriptor %d, pid %d, is %s with a current %s request\n", csidx->file_desc, ptid_get_pid (csidx->ss->general_thread_), pending_types_str[csidx->pending], packet_types_str[csidx->packet_type]); - } - if (result) - monitor_output (result); + { + if (csidx->file_desc > 0) + { + old_result = result; + asprintf (&result, "%s fd %d %s %s is %s", result, + csidx->file_desc, target_pid_to_str (csidx->new_general_thread), + last_status.kind != TARGET_WAITKIND_IGNORE ? waitkind_str[last_status.kind] : "", + pending_types_str[csidx->pending]); + strlen (old_result) ? free (old_result) : 0; + old_result = result; + if (csidx->packet_type) + asprintf (&result, "%s with a current %s request\n", result, + packet_types_str[csidx->packet_type]); + else + asprintf (&result, "%s\n", result); + strlen (old_result) ? free (old_result) : 0; + } + } + if (strlen (result) > 0) + { + monitor_output (result); + free (result); + } } else if (strcmp (mon, "client sync") == 0) { client_state *csidx; for (csidx = client_states.first; csidx != NULL; csidx = csidx->next) - if (csidx->pending == pending_cont_waiter - || csidx->pending == pending_waitee) - csidx->pending = none_pending; + { + if (csidx->pending) + { + if (csidx->pending == pending_cont_waiter) + { + if (non_stop) + csidx->packet_type = vContt; + resolve_waiter (csidx, NULL); + } + csidx->pending = none_pending; + } + } } else if (strcmp (mon, "help") == 0) monitor_show_help (); @@ -2440,7 +2529,7 @@ handle_qxfer_threads_worker (struct inferior_list_entry *inf, void *arg) char core_s[21]; const char *name = target_thread_name (ptid); - // TODO an attached client does not know about multiple inferiors + /* TODO an attached client does not know about multiple inferiors */ if (ptid_get_pid (inf->id) != ptid_get_pid (general_thread) && attach_count > 0) return; @@ -4840,19 +4929,6 @@ process_serial_event (void) else return -1; } - else - { - if (in_buffer) - { - xfree (in_buffer); - in_buffer = 0; - } - if (packet_length > 0) - { - in_buffer = xmalloc (packet_length); - memcpy (in_buffer, own_buffer, packet_length); - } - } response_needed = 1; @@ -5398,7 +5474,8 @@ handle_target_event (int err, gdb_client_data client_data) { for (csi = client_states.first; csi != NULL; csi = csi->next) { - if (attached_to_same_proc (save_csi, csi)) + if (attached_to_same_proc (save_csi, csi) + && csi->catch_syscalls) { save_csi = client_states.current_cs; csi->nonstop_pending = pending_notifier; diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index c54476e..fe3d1cb 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -84,7 +84,7 @@ typedef int gdb_fildes_t; /* Functions from server.c. */ extern int handle_serial_event (int err, gdb_client_data client_data); extern int handle_target_event (int err, gdb_client_data client_data); -extern int notify_clients (char *buffer); +extern int notify_clients (char *buffer, int first); /* Get rid of the currently pending stop replies that match PTID. */ extern void discard_queued_stop_replies (ptid_t ptid); @@ -163,7 +163,7 @@ struct client_breakpoint struct client_breakpoint *next; }; -enum packet_types { other_packet, vContc, vConts, vContt, vRun, vAttach }; +enum packet_types { other_packet, vContc, vConts, vContt, vRun, vAttach, Hg, g_or_m, vStopped }; typedef enum packet_types packet_types; enum exit_types { no_exit, have_exit, sent_exit }; @@ -180,6 +180,7 @@ struct client_state int nonstop_pending; int catch_syscalls; ptid_t last_cont_ptid; + ptid_t new_general_thread; struct target_waitstatus last_cont_waitstatus; /* From server.c */ @@ -226,7 +227,7 @@ struct client_state int pass_signals_[GDB_SIGNAL_LAST]; hooks/post-receive -- Repository for Project Archer.