]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sched: don't keep prepared fd_set
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 22 Jun 2016 12:21:33 +0000 (14:21 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 23 Jun 2016 09:34:00 +0000 (11:34 +0200)
Instead of copying a prepared fd_set to the fd_set used by select(),
fill it from scratch according to the array of file handlers before each
select() call. This should make the code simpler and save some memory
when other events are supported.

sched.c

diff --git a/sched.c b/sched.c
index 5879d10008a1ddc7d9f7b73854bee2503eb93c37..c4afe788121a0bcd6e9b8e574ea49a451e592a07 100644 (file)
--- a/sched.c
+++ b/sched.c
@@ -44,17 +44,6 @@ static int initialised = 0;
 
 /* ================================================== */
 
-/* Variables to handle the capability to dispatch on particular file
-   handles becoming readable */
-
-/* Each bit set in this fd set corresponds to a read descriptor that
-   we are watching and with which we have a handler associated in the
-   file_handlers array */
-static fd_set read_fds;
-
-/* This is the number of bits that we have set in read_fds */
-static unsigned int n_read_fds;
-
 /* One more than the highest file descriptor that is registered */
 static unsigned int one_highest_fd;
 
@@ -67,6 +56,7 @@ static unsigned int one_highest_fd;
 typedef struct {
   SCH_FileHandler       handler;
   SCH_ArbitraryArgument arg;
+  int                   events;
 } FileHandlerEntry;
 
 static ARR_Instance file_handlers;
@@ -132,9 +122,6 @@ handle_slew(struct timeval *raw,
 void
 SCH_Initialise(void)
 {
-  FD_ZERO(&read_fds);
-  n_read_fds = 0;
-
   file_handlers = ARR_CreateInstance(sizeof (FileHandlerEntry));
 
   n_timer_queue_entries = 0;
@@ -178,26 +165,27 @@ SCH_AddFileHandler
   if (fd >= FD_SETSIZE)
     LOG_FATAL(LOGF_Scheduler, "Too many file descriptors");
 
+  /* Resize the array if the descriptor is highest so far */
+  while (ARR_GetSize(file_handlers) <= fd) {
+    ptr = ARR_GetNewElement(file_handlers);
+    ptr->handler = NULL;
+    ptr->arg = NULL;
+    ptr->events = 0;
+  }
+
+  ptr = ARR_GetElement(file_handlers, fd);
+
   /* Don't want to allow the same fd to register a handler more than
      once without deleting a previous association - this suggests
      a bug somewhere else in the program. */
-  if (FD_ISSET(fd, &read_fds))
-    assert(0);
-
-  ++n_read_fds;
-  
-  if (ARR_GetSize(file_handlers) < fd + 1)
-    ARR_SetSize(file_handlers, fd + 1);
+  assert(!ptr->handler);
 
-  ptr = (FileHandlerEntry *)ARR_GetElement(file_handlers, fd);
   ptr->handler = handler;
   ptr->arg = arg;
+  ptr->events = events;
 
-  FD_SET(fd, &read_fds);
-
-  if ((fd + 1) > one_highest_fd) {
+  if (one_highest_fd < fd + 1)
     one_highest_fd = fd + 1;
-  }
 }
 
 
@@ -206,29 +194,26 @@ SCH_AddFileHandler
 void
 SCH_RemoveFileHandler(int fd)
 {
-  int fds_left, fd_to_check;
+  FileHandlerEntry *ptr;
 
   assert(initialised);
 
-  /* Check that a handler was registered for the fd in question */
-  if (!FD_ISSET(fd, &read_fds))
-    assert(0);
+  ptr = ARR_GetElement(file_handlers, fd);
 
-  --n_read_fds;
+  /* Check that a handler was registered for the fd in question */
+  assert(ptr->handler);
 
-  FD_CLR(fd, &read_fds);
+  ptr->handler = NULL;
+  ptr->arg = NULL;
+  ptr->events = 0;
 
   /* Find new highest file descriptor */
-  fds_left = n_read_fds;
-  fd_to_check = 0;
-  while (fds_left > 0) {
-    if (FD_ISSET(fd_to_check, &read_fds)) {
-      --fds_left;
-    }
-    ++fd_to_check;
+  while (one_highest_fd > 0) {
+    ptr = ARR_GetElement(file_handlers, one_highest_fd - 1);
+    if (ptr->handler)
+      break;
+    one_highest_fd--;
   }
-
-  one_highest_fd = fd_to_check;
 }
 
 /* ================================================== */
@@ -595,6 +580,38 @@ handle_slew(struct timeval *raw,
 
 /* ================================================== */
 
+static void
+fill_fd_sets(fd_set **read_fds)
+{
+  FileHandlerEntry *handlers;
+  fd_set *rd;
+  int i, n, events;
+
+  n = ARR_GetSize(file_handlers);
+  handlers = ARR_GetElements(file_handlers);
+  rd = NULL;
+
+  for (i = 0; i < n; i++) {
+    events = handlers[i].events;
+
+    if (!events)
+      continue;
+
+    if (events & SCH_FILE_INPUT) {
+      if (!rd) {
+        rd = *read_fds;
+        FD_ZERO(rd);
+      }
+      FD_SET(i, rd);
+    }
+  }
+
+  if (!rd)
+    *read_fds = NULL;
+}
+
+/* ================================================== */
+
 #define JUMP_DETECT_THRESHOLD 10
 
 static int
@@ -650,7 +667,7 @@ check_current_time(struct timeval *prev_raw, struct timeval *raw, int timeout,
 void
 SCH_MainLoop(void)
 {
-  fd_set rd;
+  fd_set read_fds, *p_read_fds;
   int status, errsv;
   struct timeval tv, saved_tv, *ptv;
   struct timeval now, saved_now, cooked;
@@ -681,16 +698,15 @@ SCH_MainLoop(void)
       saved_tv.tv_sec = 0;
     }
 
+    p_read_fds = &read_fds;
+    fill_fd_sets(&p_read_fds);
+
     /* if there are no file descriptors being waited on and no
        timeout set, this is clearly ridiculous, so stop the run */
-    if (!ptv && !n_read_fds) {
+    if (!ptv && !p_read_fds)
       LOG_FATAL(LOGF_Scheduler, "Nothing to do");
-    }
-
-    /* Copy current set of read file descriptors */
-    memcpy((void *) &rd, (void *) &read_fds, sizeof(fd_set));
 
-    status = select(one_highest_fd, &rd, NULL, NULL, ptv);
+    status = select(one_highest_fd, p_read_fds, NULL, NULL, ptv);
     errsv = errno;
 
     LCL_ReadRawTime(&now);
@@ -713,7 +729,7 @@ SCH_MainLoop(void)
     } else if (status > 0) {
       /* A file descriptor is ready to read */
 
-      dispatch_filehandlers(status, &rd);
+      dispatch_filehandlers(status, &read_fds);
 
     } else {
       /* No descriptors readable, timeout must have elapsed.