Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: kurku <sandovin@mail.ru>
To: gdb-patches@sourceware.org
Cc: kurku <sandovin@mail.ru>
Subject: [RFC][PATCH 1/2][PR cli/34409] gdb: event-loop: Rework poll's version of round robin
Date: Wed, 22 Jul 2026 10:21:36 +0300	[thread overview]
Message-ID: <20260722072137.1397888-2-sandovin@mail.ru> (raw)
In-Reply-To: <20260722072137.1397888-1-sandovin@mail.ru>

GDB had 2 implementations for round robin over file descriptors.

version for poll
version for select

poll version uses:
 - std::vector index in gdb_notifier
 - linked list from gdb_notifier
it does:
 - circular scan over std::vector to find a slot
   with revents filled in by the kernel
 - additional linear scan of the linked list to find
   the matched file_handler with the same fd

select version uses:
 - linked list in gdb_notifier
it does:
 - circular scan of the linked list
   to find the node which has events

I can't find no clear reason to distinguish the two, or make the shape
of the code to be so vastly different. In both cases we do circular
linear scan over something and if flag of the fired event has been set -
we stop the scan and handle the event.

The only difference is the source of events. One comes directly from the
linked list. The other is from poll_fds std::vector.

Thus I propose to unify the shape of code paths. And unification would
be made on select's version because it already does the tracking of
events for select, we just need to extend it so that now revents issued
by poll api are accessible through the linked list.

( the real use case to do this change
  is due to many readline macros hazards
  I was trying to fix: gdb/34409 )
---
 gdbsupport/event-loop.cc | 72 ++++++++++++++++++++++------------------
 1 file changed, 39 insertions(+), 33 deletions(-)

diff --git a/gdbsupport/event-loop.cc b/gdbsupport/event-loop.cc
index c6e1b5b4634..deca3d86e5d 100644
--- a/gdbsupport/event-loop.cc
+++ b/gdbsupport/event-loop.cc
@@ -77,6 +77,11 @@ struct file_handler
 
   /* Next registered file descriptor.  */
   struct file_handler *next_file;
+
+#ifdef HAVE_POLL
+  /* Reverse index from linked list into vector poll_fds vector */
+  int poll_fds_index;
+#endif
 };
 
 #ifdef HAVE_POLL
@@ -104,7 +109,7 @@ static struct
     /* Ptr to head of file handler list.  */
     file_handler *first_file_handler;
 
-    /* Next file handler to handle, for the select variant.  To level
+    /* Next file handler to handle.  To level
        the fairness across event sources, we serve file handlers in a
        round-robin-like fashion.  The number and order of the polled
        file handlers may change between invocations, but this is good
@@ -115,13 +120,6 @@ static struct
     /* Descriptors to poll.  */
     std::vector<struct pollfd> poll_fds;
 
-    /* Next file descriptor to handle, for the poll variant.  To level
-       the fairness across event sources, we poll the file descriptors
-       in a round-robin-like fashion.  The number and order of the
-       polled file descriptors may change between invocations, but
-       this is good enough.  */
-    int next_poll_fds_index;
-
     /* Timeout in milliseconds for calls to poll().  */
     int poll_timeout;
 #endif
@@ -335,6 +333,7 @@ create_file_handler (int fd, int mask, handler_func * proc,
 #ifdef HAVE_POLL
       if (use_poll)
 	{
+	  file_ptr->poll_fds_index = gdb_notifier.num_fds;
 	  gdb_notifier.num_fds++;
 	  struct pollfd new_fd;
 	  new_fd.fd = fd;
@@ -420,13 +419,30 @@ delete_file_handler (int fd)
 #ifdef HAVE_POLL
   if (use_poll)
     {
-      auto iter = std::remove_if (gdb_notifier.poll_fds.begin (),
-				  gdb_notifier.poll_fds.end (),
-				  [=] (const pollfd &item)
-				  {
-				    return item.fd == fd;
-				  });
-      gdb_notifier.poll_fds.erase (iter, gdb_notifier.poll_fds.end());
+      /* Swap last with the provided file_ptr in poll_fds vector
+	 then do repair of a reverse index */
+
+      int i = file_ptr->poll_fds_index;
+      int j = gdb_notifier.num_fds - 1;
+
+      file_handler *i_ptr = file_ptr;
+      file_handler *j_ptr;
+
+      for (j_ptr = gdb_notifier.first_file_handler;
+	   j_ptr != NULL;
+	   j_ptr = j_ptr->next_file)
+	{
+	  if (j_ptr->poll_fds_index == j)
+	    break;
+	}
+
+      gdb_assert (i_ptr != NULL);
+      gdb_assert (j_ptr != NULL);
+
+      std::swap(gdb_notifier.poll_fds[i], gdb_notifier.poll_fds[j]);
+      std::swap(j_ptr->poll_fds_index, i_ptr->poll_fds_index);
+
+      gdb_notifier.poll_fds.pop_back();
       gdb_notifier.num_fds--;
     }
   else
@@ -645,30 +661,20 @@ gdb_wait_for_event (int block)
 #ifdef HAVE_POLL
   if (use_poll)
     {
-      int i;
-      int mask;
+      int mask = 0;
 
-      while (1)
+      do
 	{
-	  if (gdb_notifier.next_poll_fds_index >= gdb_notifier.num_fds)
-	    gdb_notifier.next_poll_fds_index = 0;
-	  i = gdb_notifier.next_poll_fds_index++;
+	  file_ptr = get_next_file_handler_to_handle_and_advance ();
 
-	  gdb_assert (i < gdb_notifier.num_fds);
-	  if (gdb_notifier.poll_fds[i].revents)
-	    break;
-	}
+	  int i = file_ptr->poll_fds_index;
+	  short revents = gdb_notifier.poll_fds[i].revents;
 
-      for (file_ptr = gdb_notifier.first_file_handler;
-	   file_ptr != NULL;
-	   file_ptr = file_ptr->next_file)
-	{
-	  if (file_ptr->fd == gdb_notifier.poll_fds[i].fd)
-	    break;
+	  if (revents)
+	    mask |= revents;
 	}
-      gdb_assert (file_ptr != NULL);
+      while (mask == 0);
 
-      mask = gdb_notifier.poll_fds[i].revents;
       handle_file_event (file_ptr, mask);
       return 1;
     }
-- 
2.43.0


  reply	other threads:[~2026-07-22  7:22 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-22  7:21 [RFC][PATCH 0/2][PR cli/34409] Fix SIGTTIN due to readline macroinput kurku
2026-07-22  7:21 ` kurku [this message]
2026-07-22  7:21 ` [RFC][PATCH 2/2][PR cli/34409] gdb: Fix readline macros hazards kurku

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260722072137.1397888-2-sandovin@mail.ru \
    --to=sandovin@mail.ru \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox