This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: generic `struct serial' interface pipe for remote non-stop


On Friday 17 October 2008 11:21:27, Eli Zaretskii wrote:
> > From: Pedro Alves <pedro@codesourcery.com>

> Forgive me, especially if I talk out of ignorance or misunderstanding,
> but isn't this a horrible design?  We need to communicate to the event
> loop that some event happened, and we do that by opening a pipe
> between one part of GDB and another, and talk to ourselves via that
> pipe?
> 
> Can't we instead register with the event loop some callback that would
> tell the loop that an event arrived?  Heck, even raise-ing a signal
> would be better.
> 

Believe me or not, I had just changed to using pipes very
recently ...  I was using the asynchronous signal handling mechanism
already in place, until I found out that it wasn't sufficient
for my purposes, so I thought that reusing pipes was the most
expedite way to solve this issue.  I was also avoiding touching
the event loop design, which is heavilly file descriptor based.
Read through event-loop.c.

> > For go32/djgpp or for unix hosts that don't have socketpair, I
> > just bail out with ENOSYS.
> 
> Does that mean that some feature that could have worked for DJGPP with
> a different design, will now be broken by design?  If so, I'd like us
> to look for alternatives.
> 

I can't honestly, seriously believe that anyone would be so masochist
enough as to be doing non-stop cross-debugging from DJGPP.  And, it's
not like you couldn't implement in-process pipes on DJGPP, and
implement a gdb_select on DJGPP too.  We do this for Windows.

That being said, I took a step back, and relooked at the problems I was
having with async signals handlers, which is a mechanism to register a 
callback function in the event-loop.  Notice that the currently event
loop design is heavilly based on waitable file descriptors, with async
signal handlers being a secondary input event source.

So I came up with the attached patch to adjust it to my needs.

The biggest problem the attached patch solves is:

 - Since async signal handlers are always checked before polling the
   file descriptors, I can easily starve the file descriptor based
   sources.  E.g., if I place several threads displace stepping a
   breakpoint, forcing continuous remote traffic, the CLI becomes very,
   very unresponsive, unusable really.  This is because stdin itself
   is registered as a monitored (via select/poll) file descriptor.

 To solve this, I adjusted the event loop to give equal priority to
 all event-sources (timers, async signal handlers, monitored file
 descriptors).  The async signal handling was changed to instead
 of immediatelly calling the associated callback, it installs an
 event in the "ready" queue, just like the file-descriptor and
 timer based sources.  I then make sure that I poll each of the
 possible event sources once (select/poll with timeout 0 too).  If
 if no event is found ready, then, we go blocking waiting for one
 in select/poll.

I can sucessfully debug a non-stop linux gdbserver from both
a linux host and a Windows (mingw32) host with this.

The remote.c changes below apply on top of the non-stop support
patch I sent yesterday, and it's what I used to test, shown here
so you could see what was required that change, in case you're
curious about it.

Do you think it is a better alternative?  I can't think of a reason
this wouldn't work on DJGPP.

-- 
Pedro Alves
2008-10-17  Pedro Alves  <pedro@codesourcery.com>

	* event-loop.c (event_data): New.
	(event_handler_func): Take an event_data instead of an integer.
	(struct gdb_event): Replace the integer file descriptor by a
	generic event_data.
	(async_handler_ready): Delete.
	(create_event): New.
	(create_file_event): Use it.
	(process_event): Don't check async signal handlers here.  Adjust.
	(gdb_do_one_event): Poll from the event sources in round-robin
	fashion across calls.  Be sure to consult all sources before
	blocking.
	(handle_file_event): Take an event_data instead of an integer.
	Adjust.
	(gdb_wait_for_event): Add `block' argument.  Handle it.
	(mark_async_signal_handler): Adjust.
	(struct signal_handler_data): New.
	(invoke_async_signal_handler): Rename to ...
	(check_async_signal_handlers): ... this.  Enqueue an event instead
	of calling the callback here.
	(check_async_ready): Delete.
	(handle_timer_event): Adjust.

---
 gdb/event-loop.c |  261 ++++++++++++++++++++++++++++++++++---------------------
 gdb/remote.c     |  132 +++++++--------------------
 2 files changed, 201 insertions(+), 192 deletions(-)

Index: src/gdb/event-loop.c
===================================================================
--- src.orig/gdb/event-loop.c	2008-10-17 19:11:14.000000000 +0100
+++ src/gdb/event-loop.c	2008-10-17 20:14:41.000000000 +0100
@@ -38,25 +38,40 @@
 #include "gdb_assert.h"
 #include "gdb_select.h"
 
+/* Data point to pass to the event handler.  */
+typedef union event_data
+{
+  void *ptr;
+  int integer;
+} event_data;
+
 typedef struct gdb_event gdb_event;
-typedef void (event_handler_func) (int);
+typedef void (event_handler_func) (event_data);
 
 /* Event for the GDB event system.  Events are queued by calling
    async_queue_event and serviced later on by gdb_do_one_event. An
    event can be, for instance, a file descriptor becoming ready to be
-   read. Servicing an event simply means that the procedure PROC will
+   read.  Servicing an event simply means that the procedure PROC will
    be called.  We have 2 queues, one for file handlers that we listen
    to in the event loop, and one for the file handlers+events that are
-   ready. The procedure PROC associated with each event is always the
-   same (handle_file_event).  Its duty is to invoke the handler
-   associated with the file descriptor whose state change generated
-   the event, plus doing other cleanups and such. */
+   ready. The procedure PROC associated with each event is dependant
+   of the event source.  In the case of monitored file descriptors, it
+   is always the same (handle_file_event).  Its duty is to invoke the
+   handler associated with the file descriptor whose state change
+   generated the event, plus doing other cleanups and such.  In the
+   case of async signal handlers, it is
+   invoke_async_signal_handler.  */
 
 struct gdb_event
   {
-    event_handler_func *proc;	/* Procedure to call to service this event. */
-    int fd;			/* File descriptor that is ready. */
-    struct gdb_event *next_event;	/* Next in list of events or NULL. */
+    /* Procedure to call to service this event.  */
+    event_handler_func *proc;
+
+    /* Data to pass to the event handler.  */
+    event_data data;
+
+    /* Next in list of events or NULL.  */
+    struct gdb_event *next_event;
   };
 
 /* Information about each file descriptor we register with the event
@@ -207,21 +222,13 @@ static struct
   }
 sighandler_list;
 
-/* Are any of the handlers ready?  Check this variable using
-   check_async_ready. This is used by process_event, to determine
-   whether or not to invoke the invoke_async_signal_handler
-   function. */
-static int async_handler_ready = 0;
-
 static void create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data);
-static void invoke_async_signal_handler (void);
-static void handle_file_event (int event_file_desc);
-static int gdb_wait_for_event (void);
-static int check_async_ready (void);
+static void check_async_signal_handlers ();
+static void handle_file_event (event_data data);
+static int gdb_wait_for_event (int);
 static void async_queue_event (gdb_event * event_ptr, queue_position position);
 static gdb_event *create_file_event (int fd);
 static int process_event (void);
-static void handle_timer_event (int dummy);
 static void poll_timers (void);
 
 
@@ -260,6 +267,22 @@ async_queue_event (gdb_event * event_ptr
     }
 }
 
+/* Create a generic event, to be enqueued in the event queue for
+   processing.  PROC is the procedure associated to the event.  DATA
+   is passed to PROC uppon PROC invocation.  */
+
+static gdb_event *
+create_event (event_handler_func proc, event_data data)
+{
+  gdb_event *event;
+
+  event = xmalloc (sizeof (*event));
+  event->proc = proc;
+  event->data = data;
+
+  return event;
+}
+
 /* Create a file event, to be enqueued in the event queue for
    processing. The procedure associated to this event is always
    handle_file_event, which will in turn invoke the one that was
@@ -267,12 +290,10 @@ async_queue_event (gdb_event * event_ptr
 static gdb_event *
 create_file_event (int fd)
 {
-  gdb_event *file_event_ptr;
+  event_data data;
 
-  file_event_ptr = (gdb_event *) xmalloc (sizeof (gdb_event));
-  file_event_ptr->proc = handle_file_event;
-  file_event_ptr->fd = fd;
-  return (file_event_ptr);
+  data.integer = fd;
+  return create_event (handle_file_event, data);
 }
 
 /* Process one event.
@@ -289,17 +310,7 @@ process_event (void)
 {
   gdb_event *event_ptr, *prev_ptr;
   event_handler_func *proc;
-  int fd;
-
-  /* First let's see if there are any asynchronous event handlers that
-     are ready. These would be the result of invoking any of the
-     signal handlers. */
-
-  if (check_async_ready ())
-    {
-      invoke_async_signal_handler ();
-      return 1;
-    }
+  event_data data;
 
   /* Look in the event queue to find an event that is ready
      to be processed. */
@@ -310,7 +321,7 @@ process_event (void)
       /* Call the handler for the event. */
 
       proc = event_ptr->proc;
-      fd = event_ptr->fd;
+      data = event_ptr->data;
 
       /* Let's get rid of the event from the event queue.  We need to
          do this now because while processing the event, the proc
@@ -338,7 +349,7 @@ process_event (void)
       xfree (event_ptr);
 
       /* Now call the procedure associated with the event. */
-      (*proc) (fd);
+      (*proc) (data);
       return 1;
     }
 
@@ -355,33 +366,61 @@ process_event (void)
 int
 gdb_do_one_event (void *data)
 {
-  /* Any events already waiting in the queue? */
+  static int event_source_head = 0;
+  static const int number_of_sources = 3;
+  int current = 0;
+
+  /* Any events already waiting in the queue?  */
   if (process_event ())
+    return 1;
+
+  /* To level the fairness across event sources, we poll them in a
+     round-robin fashion.  */
+  for (current = 0; current < number_of_sources; current++)
     {
-      return 1;
+      switch (event_source_head)
+	{
+	case 0:
+	  /* Are any timers that are ready? If so, put an event on the
+	     queue. */
+	  poll_timers ();
+	  break;
+	case 1:
+	  /* Are there events already waiting to be collected on the
+	     monitored file descriptors?  */
+	  gdb_wait_for_event (0);
+	  break;
+	case 2:
+	  /* Are there any asynchronous event handlers ready?  These
+	     would be the result of invoking any of the signal
+	     handlers.  */
+	  check_async_signal_handlers ();
+	  break;
+	}
+
+      event_source_head++;
+      if (event_source_head == number_of_sources)
+	event_source_head = 0;
     }
 
-  /* Are any timers that are ready? If so, put an event on the queue. */
-  poll_timers ();
+  /* Handle any new events collected.  */
+  if (process_event ())
+    return 1;
 
-  /* Wait for a new event.  If gdb_wait_for_event returns -1,
-     we should get out because this means that there are no
-     event sources left. This will make the event loop stop,
-     and the application exit. */
+  /* Block waiting for a new event.  If gdb_wait_for_event returns -1,
+     we should get out because this means that there are no event
+     sources left.  This will make the event loop stop, and the
+     application exit.  */
 
-  if (gdb_wait_for_event () < 0)
-    {
-      return -1;
-    }
+  if (gdb_wait_for_event (1) < 0)
+    return -1;
 
-  /* Handle any new events occurred while waiting. */
+  /* Handle any new events occurred while waiting.  */
   if (process_event ())
-    {
-      return 1;
-    }
+    return 1;
 
-  /* If gdb_wait_for_event has returned 1, it means that one
-     event has been handled. We break out of the loop. */
+  /* If gdb_wait_for_event has returned 1, it means that one event has
+     been handled.  We break out of the loop.  */
   return 1;
 }
 
@@ -659,7 +698,7 @@ delete_file_handler (int fd)
    through event_ptr->proc.  EVENT_FILE_DESC is file descriptor of the
    event in the front of the event queue. */
 static void
-handle_file_event (int event_file_desc)
+handle_file_event (event_data data)
 {
   file_handler *file_ptr;
   int mask;
@@ -667,6 +706,7 @@ handle_file_event (int event_file_desc)
   int error_mask;
   int error_mask_returned;
 #endif
+  int event_file_desc = data.integer;
 
   /* Search the file handler list to find one that matches the fd in
      the event. */
@@ -735,15 +775,13 @@ handle_file_event (int event_file_desc)
     }
 }
 
-/* Called by gdb_do_one_event to wait for new events on the 
-   monitored file descriptors. Queue file events as they are 
-   detected by the poll. 
-   If there are no events, this function will block in the 
-   call to poll.
-   Return -1 if there are no files descriptors to monitor, 
-   otherwise return 0. */
+/* Called by gdb_do_one_event to wait for new events on the monitored
+   file descriptors.  Queue file events as they are detected by the
+   poll.  If BLOCK and if there are no events, this function will
+   block in the call to poll.  Return -1 if there are no files
+   descriptors to monitor, otherwise return 0. */
 static int
-gdb_wait_for_event (void)
+gdb_wait_for_event (int block)
 {
   file_handler *file_ptr;
   gdb_event *file_event_ptr;
@@ -760,13 +798,18 @@ gdb_wait_for_event (void)
   if (use_poll)
     {
 #ifdef HAVE_POLL
-      num_found =
-	poll (gdb_notifier.poll_fds,
-	      (unsigned long) gdb_notifier.num_fds,
-	      gdb_notifier.timeout_valid ? gdb_notifier.poll_timeout : -1);
+      int timeout;
+
+      if (block)
+	timeout = gdb_notifier.timeout_valid ? gdb_notifier.poll_timeout : -1;
+      else
+	timeout = 0;
+
+      num_found = poll (gdb_notifier.poll_fds,
+			(unsigned long) gdb_notifier.num_fds, timeout);
 
       /* Don't print anything if we get out of poll because of a
-         signal. */
+	 signal.  */
       if (num_found == -1 && errno != EINTR)
 	perror_with_name (("poll"));
 #else
@@ -776,6 +819,18 @@ gdb_wait_for_event (void)
     }
   else
     {
+      struct timeval select_timeout;
+
+      struct timeval *timeout_p;
+      if (block)
+	timeout_p = gdb_notifier.timeout_valid
+	  ? &gdb_notifier.select_timeout : NULL;
+      else
+	{
+	  memset (&select_timeout, 0, sizeof (select_timeout));
+	  timeout_p = &select_timeout;
+	}
+
       gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
       gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
       gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
@@ -783,8 +838,7 @@ gdb_wait_for_event (void)
 			      &gdb_notifier.ready_masks[0],
 			      &gdb_notifier.ready_masks[1],
 			      &gdb_notifier.ready_masks[2],
-			      gdb_notifier.timeout_valid
-			      ? &gdb_notifier.select_timeout : NULL);
+			      timeout_p);
 
       /* Clear the masks after an error from select. */
       if (num_found == -1)
@@ -792,7 +846,9 @@ gdb_wait_for_event (void)
 	  FD_ZERO (&gdb_notifier.ready_masks[0]);
 	  FD_ZERO (&gdb_notifier.ready_masks[1]);
 	  FD_ZERO (&gdb_notifier.ready_masks[2]);
-	  /* Dont print anything is we got a signal, let gdb handle it. */
+
+	  /* Dont print anything if we got a signal, let gdb handle
+	     it.  */
 	  if (errno != EINTR)
 	    perror_with_name (("select"));
 	}
@@ -912,20 +968,31 @@ void
 mark_async_signal_handler (async_signal_handler * async_handler_ptr)
 {
   ((async_signal_handler *) async_handler_ptr)->ready = 1;
-  async_handler_ready = 1;
 }
 
-/* Call all the handlers that are ready. */
+struct signal_handler_data
+{
+  sig_handler_func* proc;
+  gdb_client_data client_data;
+};
+
 static void
-invoke_async_signal_handler (void)
+invoke_async_signal_handler (event_data data)
 {
-  async_signal_handler *async_handler_ptr;
+  struct signal_handler_data *hdata = data.ptr;
+  (*hdata->proc) (hdata->client_data);
 
-  if (async_handler_ready == 0)
-    return;
-  async_handler_ready = 0;
+  xfree (hdata);
+}
 
-  /* Invoke ready handlers. */
+/* Check if any signal handlers are ready.  */
+static void
+check_async_signal_handlers (void)
+{
+  async_signal_handler *async_handler_ptr;
+  struct signal_handler_data *hdata;
+  struct gdb_event *event_ptr;
+  event_data data;
 
   while (1)
     {
@@ -938,11 +1005,20 @@ invoke_async_signal_handler (void)
 	}
       if (async_handler_ptr == NULL)
 	break;
+
       async_handler_ptr->ready = 0;
-      (*async_handler_ptr->proc) (async_handler_ptr->client_data);
-    }
 
-  return;
+      hdata = xmalloc (sizeof (*hdata));
+
+      hdata->proc = async_handler_ptr->proc;
+      hdata->client_data = async_handler_ptr->client_data;
+
+      data.ptr = hdata;
+
+      event_ptr = create_event (invoke_async_signal_handler, data);
+      async_queue_event (event_ptr, TAIL);
+      break;
+    }
 }
 
 /* Delete an asynchronous handler (ASYNC_HANDLER_PTR). 
@@ -971,13 +1047,6 @@ delete_async_signal_handler (async_signa
   (*async_handler_ptr) = NULL;
 }
 
-/* Is it necessary to call invoke_async_signal_handler? */
-static int
-check_async_ready (void)
-{
-  return async_handler_ready;
-}
-
 /* Create a timer that will expire in MILLISECONDS from now. When the
    timer is ready, PROC will be executed. At creation, the timer is
    aded to the timers queue.  This queue is kept sorted in order of
@@ -1080,11 +1149,11 @@ delete_timer (int id)
 }
 
 /* When a timer event is put on the event queue, it will be handled by
-   this function.  Just call the assiciated procedure and delete the
-   timer event from the event queue. Repeat this for each timer that
-   has expired. */
+   this function.  Just call the associated procedure and delete the
+   timer event from the event queue.  Repeat this for each timer that
+   has expired.  */
 static void
-handle_timer_event (int dummy)
+handle_timer_event (event_data dummy)
 {
   struct timeval time_now;
   struct gdb_timer *timer_ptr, *saved_timer;
@@ -1150,7 +1219,7 @@ poll_timers (void)
 	{
 	  event_ptr = (gdb_event *) xmalloc (sizeof (gdb_event));
 	  event_ptr->proc = handle_timer_event;
-	  event_ptr->fd = timer_list.first_timer->timer_id;
+	  event_ptr->data.integer = timer_list.first_timer->timer_id;
 	  async_queue_event (event_ptr, TAIL);
 	}
 
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2008-10-17 20:14:40.000000000 +0100
+++ src/gdb/remote.c	2008-10-17 20:27:10.000000000 +0100
@@ -229,10 +229,8 @@ static void remote_get_pending_stop_repl
 static void discard_pending_stop_replies (int pid);
 static int peek_stop_reply (ptid_t ptid);
 
-static void remote_async_inferior_event_handler (struct serial *scb,
-						 void *context);
-static void remote_async_get_pending_events_handler (struct serial *scb,
-						     void *context);
+static void remote_async_inferior_event_handler (gdb_client_data);
+static void remote_async_get_pending_events_handler (gdb_client_data);
 
 /* The non-stop remote protocol provisions for one pending stop reply.
    This is where we keep it until it is acknowledged.  */
@@ -1101,77 +1099,17 @@ static struct async_signal_handler *sigi
 static struct async_signal_handler *sigint_remote_token;
 
 
-/* Pipes for use by the asynchronous event processing used in non-stop
-   mode.  */
-
-/* The read handle of this pipe is registered as the event source of
+/* Asynchronous signal handle registered as event loop source for
    when we have pending events ready to be passed to the core.  */
 
-static struct serial *remote_inferior_event_pipe[2];
-
-/* The read handle of this pipe is registered as the event source of
-   when the remote sent as a %Stop notification.  The registered
-   callback will do a vStopped sequence to pull the rest of the events
-   out of the remote side into our event queue.  */
-
-static struct serial *remote_get_pending_events_pipe[2];
+static struct async_signal_handler *remote_async_inferior_event_token;
 
-static void
-make_event_pipes (void)
-{
-  /* Create event pipes and register them in the event loop.  */
-  if (serial_pipe (remote_inferior_event_pipe) == -1
-      || serial_pipe (remote_get_pending_events_pipe) == -1)
-    perror_with_name (_("Creating the non-stop mode event files failed"));
+/* Asynchronous signal handle registered as event loop source for when
+   the remote sent us a %Stop notification.  The registered callback
+   will do a vStopped sequence to pull the rest of the events out of
+   the remote side into our event queue.  */
 
-  /* Register the read handles in the event loop.  */
-  serial_async (remote_inferior_event_pipe[0],
-		remote_async_inferior_event_handler, NULL);
-  serial_async (remote_get_pending_events_pipe[0],
-		remote_async_get_pending_events_handler, NULL);
-}
-
-/* Destroy a pipe previously created by MAKE_EVENT_PIPE and remove it
-   from the event loop.  */
-
-static void
-close_event_pipe (struct serial *mypipe[2])
-{
-  if (mypipe[0])
-    {
-      serial_close (mypipe[0]);
-      serial_close (mypipe[1]);
-      mypipe[0] = NULL;
-      mypipe[1] = NULL;
-    }
-}
-
-/* Flush the read end of the pipe.  */
-
-static void
-event_file_flush (struct serial *mypipe[2])
-{
-  int ch;
-
-  serial_flush_input (mypipe[0]);
-
-  do
-    {
-      ch = serial_readchar (mypipe[0], 0);
-    }
-  while (ch >= 0);
-}
-
-/* Put something in the pipe, so the event loop wakes up.  */
-
-static void
-event_file_mark (struct serial *mypipe[2])
-{
-  event_file_flush (mypipe);
-
-  if (serial_write (mypipe[1], "+", 1))
-    perror_with_name (_("event_file_mark: write failed"));
-}
+static struct async_signal_handler *remote_async_get_pending_events_token;
 
 
 static ptid_t magic_null_ptid;
@@ -2370,8 +2308,10 @@ remote_close (int quitting)
   /* We're no longer interested in any of these events.  */
   discard_pending_stop_replies (-1);
 
-  close_event_pipe (remote_inferior_event_pipe);
-  close_event_pipe (remote_get_pending_events_pipe);
+  if (remote_async_inferior_event_token)
+    delete_async_signal_handler (&remote_async_inferior_event_token);
+  if (remote_async_get_pending_events_token)
+    delete_async_signal_handler (&remote_async_get_pending_events_token);
 
   generic_mourn_inferior ();
 }
@@ -2620,9 +2560,6 @@ remote_start_remote (struct ui_out *uiou
       if (!rs->non_stop_aware)
 	error (_("Non-stop mode requested, but remote does not support non-stop"));
 
-      /* Make the event pipes and register them in the event loop.  */
-      make_event_pipes ();
-
       putpkt ("QNonStop:1");
       getpkt (&rs->buf, &rs->buf_size, 0);
 
@@ -3220,6 +3157,14 @@ remote_open_1 (char *name, int from_tty,
   /* Assume that the target is running, unless we learn otherwise.  */
   target_mark_running (target);
 
+  /* Register extra event sources in the event loop.  */
+  remote_async_inferior_event_token
+    = create_async_signal_handler (remote_async_inferior_event_handler,
+				   NULL);
+  remote_async_get_pending_events_token
+    = create_async_signal_handler (remote_async_get_pending_events_handler,
+				   NULL);
+
   /* Reset the target state; these things will be queried either by
      remote_query_supported or as they are needed.  */
   init_all_packet_configs ();
@@ -4174,7 +4119,7 @@ queued_stop_reply (ptid_t ptid)
 
   if (stop_reply_queue)
     /* There's still at least an event left.  */
-    event_file_mark (remote_inferior_event_pipe);
+    mark_async_signal_handler (remote_async_inferior_event_token);
 
   return it;
 }
@@ -4200,7 +4145,7 @@ push_stop_reply (struct stop_reply *new_
   else
     stop_reply_queue = new_event;
 
-  event_file_mark (remote_inferior_event_pipe);
+  mark_async_signal_handler (remote_async_inferior_event_token);
 }
 
 /* Returns true if we have a stop reply for PTID.  */
@@ -4433,21 +4378,21 @@ Packet: '%s'\n"),
    query.
 
    To solve this, whenever we parse a %Stop notification sucessfully,
-   we mark the REMOTE_GET_PENDING_EVENTS_PIPE, and carry on doing
+   we mark the REMOTE_ASYN_GET_PENDING_EVENTS_TOKEN, and carry on doing
    whatever we were doing:
 
     2.1) --> Hg 1
     2.2) <-- OK
     2.3) --> g
     2.4) <-- %Stop
-      <GDB writes to the REMOTE_GET_PENDING_EVENTS_PIPE>
+      <GDB marks the REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN>
     2.5) <-- (registers reply to step #2.3)
 
    Eventualy after step #2.5, we return to the event loop, which
-   selects/polls on the REMOTE_GET_PENDING_EVENTS_PIPE read end. Since
-   there's something there to read, GDB calls the pipe's associated
-   callback --- the function below.  At this point, we're always safe
-   to start a vStopped sequence. :
+   notices there's an event on the
+   REMOTE_ASYNC_GET_PENDING_EVENTS_TOKEN signal and calls the
+   associated callback --- the function below.  At this point, we're
+   always safe to start a vStopped sequence. :
 
     2.6) --> vStopped
     2.7) <-- T05 thread:2
@@ -4768,13 +4713,10 @@ remote_wait (ptid_t ptid, struct target_
 
   if (target_can_async_p ())
     {
-      /* If there are no events left in the queue, we can stop coming
-	 back.  If there's something else there, then please return
-	 here.  */
-      if (!stop_reply_queue)
-	event_file_flush (remote_inferior_event_pipe);
-      else
-	event_file_mark (remote_inferior_event_pipe);
+      /* If there are are events left in the queue tell the event loop
+	 to return here.  */
+      if (stop_reply_queue)
+	mark_async_signal_handler (remote_async_inferior_event_token);
     }
 
   return event_ptid;
@@ -5686,7 +5628,7 @@ handle_notification (char *buf, size_t l
 
 	  /* Notify the event loop there's a stop reply to acknowledge
 	     and that there may be more events to fetch.  */
-	  event_file_mark (remote_get_pending_events_pipe);
+	  mark_async_signal_handler (remote_async_get_pending_events_token);
 	}
     }
   else
@@ -8694,16 +8636,14 @@ remote_async_serial_handler (struct seri
 }
 
 static void
-remote_async_inferior_event_handler (struct serial *scb, void *context)
+remote_async_inferior_event_handler (gdb_client_data data)
 {
   inferior_event_handler (INF_REG_EVENT, NULL);
 }
 
 static void
-remote_async_get_pending_events_handler (struct serial *scb, void *context)
+remote_async_get_pending_events_handler (gdb_client_data data)
 {
-  event_file_flush (remote_get_pending_events_pipe);
-
   remote_get_pending_stop_replies ();
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]