wingo pushed a commit to branch wip-whippet
in repository guile.

commit 9e26907885ee824575075adf53566626bedfb667
Author: Andy Wingo <wi...@pobox.com>
AuthorDate: Tue Jul 15 10:59:08 2025 +0200

    Move private fports things to fports-internal.h
    
    * libguile/fports-internal.h: New file.
    * libguile/Makefile.am: Add new file.
    * libguile/filesys.c:
    * libguile/fports.c:
    * libguile/fports.h:
    * libguile/init.c:
    * libguile/ioext.c:
    * libguile/posix.c:
    * libguile/socket.c: Adapt.
---
 libguile/Makefile.am       |  1 +
 libguile/filesys.c         |  2 +-
 libguile/fports-internal.h | 78 ++++++++++++++++++++++++++++++++++++++++++++++
 libguile/fports.c          | 53 +++++++++++++++++++++++--------
 libguile/fports.h          | 28 ++---------------
 libguile/init.c            |  2 +-
 libguile/ioext.c           |  2 +-
 libguile/posix.c           |  2 +-
 libguile/socket.c          |  2 +-
 9 files changed, 126 insertions(+), 44 deletions(-)

diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index b7c97ec76..208fecde2 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -522,6 +522,7 @@ noinst_HEADERS = atomic.h                                   
\
                 dynstack.h                                     \
                  filesys-internal.h                            \
                  fluids-internal.h                             \
+                 fports-internal.h                             \
                  frames-internal.h                             \
                  gc-inline.h                                   \
                  gc-internal.h                                 \
diff --git a/libguile/filesys.c b/libguile/filesys.c
index 441708290..131439131 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -78,7 +78,7 @@
 #include "dynwind.h"
 #include "fdes-finalizers.h"
 #include "feature.h"
-#include "fports.h"
+#include "fports-internal.h"
 #include "gsubr.h"
 #include "iselect.h"
 #include "keywords.h"
diff --git a/libguile/fports-internal.h b/libguile/fports-internal.h
new file mode 100644
index 000000000..7576aca6e
--- /dev/null
+++ b/libguile/fports-internal.h
@@ -0,0 +1,78 @@
+#ifndef SCM_FPORTS_INTERNAL_H
+#define SCM_FPORTS_INTERNAL_H
+
+/* Copyright 1995-2001,2006,2008-2009,2011-2012,2017-2019,2025
+     Free Software Foundation, Inc.
+
+   This file is part of Guile.
+
+   Guile is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   Guile is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
+   License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with Guile.  If not, see
+   <https://www.gnu.org/licenses/>.  */
+
+
+
+#include "libguile/atomics-internal.h"
+#include "libguile/fports.h"
+
+
+
+enum scm_fport_option
+  {
+    /* FD's that aren't created by Guile probably need to be checked for
+       validity.  We also check that the open mode is valid.  */
+    SCM_FPORT_OPTION_VERIFY = 1U<<0,
+    /* We know some ports aren't seekable and can elide a syscall in
+       that case.  */
+    SCM_FPORT_OPTION_NOT_SEEKABLE = 1U<<1,
+    /* If reading or writing on this fd returns -1, then we set this
+       flag to record that it's nonblocking and we can avoid leaving GC
+       around those syscalls.  Similarly we can set this flag in
+       response to an explicit request that the port be nonblocking.  */
+    SCM_FPORT_OPTION_NONBLOCKING = 1U<<2
+  };
+
+static inline int
+scm_fport_has_option (scm_t_fport *fp, enum scm_fport_option opt)
+{
+  return (scm_atomic_ref_bits (&fp->options) & opt) != 0;
+}
+
+static inline void
+scm_fport_set_option (scm_t_fport *fp, enum scm_fport_option opt)
+{
+  scm_atomic_set_flags (&fp->options, opt);
+}
+
+static inline int
+scm_fport_is_nonblocking (scm_t_fport *fp)
+{
+  return scm_fport_has_option (fp, SCM_FPORT_OPTION_NONBLOCKING);
+}
+
+static inline void
+scm_fport_set_nonblocking (scm_t_fport *fp)
+{
+  scm_fport_set_option (fp, SCM_FPORT_OPTION_NONBLOCKING);
+}
+
+SCM_INTERNAL int scm_i_mode_to_open_flags (SCM mode, int *is_binary,
+                                           const char *FUNC_NAME);
+SCM_INTERNAL void scm_init_fports_keywords (void);
+SCM_INTERNAL void scm_init_fports (void);
+
+SCM_INTERNAL int scm_i_fdes_is_valid (int fdes, long mode_bits);
+SCM_INTERNAL SCM scm_i_fdes_to_port (int fdes, long mode_bits, SCM name,
+                                     unsigned options);
+
+#endif  /* SCM_FPORTS_INTERNAL_H */
diff --git a/libguile/fports.c b/libguile/fports.c
index b51f3b219..d95b5a62f 100644
--- a/libguile/fports.c
+++ b/libguile/fports.c
@@ -51,6 +51,7 @@
 #include "filesys-internal.h"
 #include "fluids.h"
 #include "gc.h"
+#include "gc-internal.h"
 #include "gsubr.h"
 #include "hashtab.h"
 #include "keywords.h"
@@ -70,7 +71,7 @@
 #include "variable.h"
 #include "version.h"
 
-#include "fports.h"
+#include "fports-internal.h"
 
 
 #if SIZEOF_OFF_T == SIZEOF_INT
@@ -621,20 +622,33 @@ static size_t
 fport_read (SCM port, SCM dst, size_t start, size_t count)
 {
   scm_t_fport *fp = SCM_FSTREAM (port);
+  scm_thread *thr = SCM_I_CURRENT_THREAD;
   signed char *ptr = SCM_BYTEVECTOR_CONTENTS (dst) + start;
-  ssize_t ret;
+  int blocking = !scm_fport_is_nonblocking (fp);
 
  retry:
-  ret = read (fp->fdes, ptr, count);
+  if (blocking)
+    gc_deactivate (thr->mutator);
+  ssize_t ret = read (fp->fdes, ptr, count);
+  int saved_errno = errno;
+  if (blocking)
+    gc_reactivate (thr->mutator);
+
   if (ret < 0)
     {
-      if (errno == EINTR)
+      if (saved_errno == EINTR)
         {
           scm_async_tick ();
           goto retry;
         }
-      if (errno == EWOULDBLOCK || errno == EAGAIN)
-        return -1;
+      if (saved_errno == EWOULDBLOCK || saved_errno == EAGAIN)
+        {
+          if (blocking)
+            /* We just found out the FD was actually nonblocking.  */
+            scm_fport_set_nonblocking (fp);
+          return -1;
+        }
+      errno = saved_errno;
       scm_syserror ("fport_read");
     }
   return ret;
@@ -643,21 +657,34 @@ fport_read (SCM port, SCM dst, size_t start, size_t count)
 static size_t
 fport_write (SCM port, SCM src, size_t start, size_t count)
 {
-  int fd = SCM_FPORT_FDES (port);
+  scm_t_fport *fp = SCM_FSTREAM (port);
+  scm_thread *thr = SCM_I_CURRENT_THREAD;
   signed char *ptr = SCM_BYTEVECTOR_CONTENTS (src) + start;
-  ssize_t ret;
+  int blocking = !scm_fport_is_nonblocking (fp);
 
  retry:
-  ret = write (fd, ptr, count);
+  if (blocking)
+    gc_deactivate (thr->mutator);
+  ssize_t ret = write (fp->fdes, ptr, count);
+  int saved_errno = errno;
+  if (blocking)
+    gc_reactivate (thr->mutator);
+
   if (ret < 0)
     {
-      if (errno == EINTR)
+      if (saved_errno == EINTR)
         {
           scm_async_tick ();
           goto retry;
         }
-      if (errno == EWOULDBLOCK || errno == EAGAIN)
-        return -1;
+      if (saved_errno == EWOULDBLOCK || saved_errno == EAGAIN)
+        {
+          if (blocking)
+            /* We just found out the FD was actually nonblocking.  */
+            scm_fport_set_nonblocking (fp);
+          return -1;
+        }
+      errno = saved_errno;
       scm_syserror ("fport_write");
     }
 
@@ -711,7 +738,7 @@ fport_random_access_p (SCM port)
 {
   scm_t_fport *fp = SCM_FSTREAM (port);
 
-  if (fp->options & SCM_FPORT_OPTION_NOT_SEEKABLE)
+  if (scm_fport_has_option (fp, SCM_FPORT_OPTION_NOT_SEEKABLE))
     return 0;
 
   if (lseek (fp->fdes, 0, SEEK_CUR) == -1)
diff --git a/libguile/fports.h b/libguile/fports.h
index 3a895775f..7c2629e05 100644
--- a/libguile/fports.h
+++ b/libguile/fports.h
@@ -1,7 +1,7 @@
 #ifndef SCM_FPORTS_H
 #define SCM_FPORTS_H
 
-/* Copyright 1995-2001,2006,2008-2009,2011-2012,2017-2019
+/* Copyright 1995-2001,2006,2008-2009,2011-2012,2017-2019,2025
      Free Software Foundation, Inc.
 
    This file is part of Guile.
@@ -34,7 +34,7 @@ typedef struct scm_t_fport {
   /* Revealed count; 0 indicates not revealed, > 1 revealed.  */
   unsigned int revealed;
   /* Set of scm_fport_option flags.  */
-  unsigned options;
+  scm_t_bits options;
 } scm_t_fport;
 
 SCM_API scm_t_port_type *scm_file_port_type;
@@ -55,8 +55,6 @@ SCM_API scm_t_port_type *scm_file_port_type;
 
 
 SCM_API void scm_evict_ports (int fd);
-SCM_INTERNAL int scm_i_mode_to_open_flags (SCM mode, int *is_binary,
-                                           const char *FUNC_NAME);
 SCM_API SCM scm_open_file_with_encoding (SCM filename, SCM modes,
                                          SCM guess_encoding, SCM encoding);
 SCM_API SCM scm_open_file (SCM filename, SCM modes);
@@ -70,26 +68,4 @@ SCM_API SCM scm_port_revealed (SCM port);
 SCM_API SCM scm_set_port_revealed_x (SCM port, SCM rcount);
 SCM_API SCM scm_adjust_port_revealed_x (SCM port, SCM addend);
 
-
-SCM_INTERNAL void scm_init_fports_keywords (void);
-SCM_INTERNAL void scm_init_fports (void);
-
-/* internal functions */
-
-#ifdef BUILDING_LIBGUILE
-enum scm_fport_option
-  {
-    /* FD's that aren't created by Guile probably need to be checked for
-       validity.  We also check that the open mode is valid.  */
-    SCM_FPORT_OPTION_VERIFY = 1U<<0,
-    /* We know some ports aren't seekable and can elide a syscall in
-       that case.  */
-    SCM_FPORT_OPTION_NOT_SEEKABLE = 1U<<1
-  };
-SCM_INTERNAL int scm_i_fdes_is_valid (int fdes, long mode_bits);
-SCM_INTERNAL SCM scm_i_fdes_to_port (int fdes, long mode_bits, SCM name,
-                                     unsigned options);
-
-#endif /* BUILDING_LIBGUILE */
-
 #endif  /* SCM_FPORTS_H */
diff --git a/libguile/init.c b/libguile/init.c
index dc1769af5..f5d500afc 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -72,7 +72,7 @@
 #include "fluids-internal.h"
 #include "foreign-object.h"
 #include "foreign.h"
-#include "fports.h"
+#include "fports-internal.h"
 #include "frames-internal.h"
 #include "gc.h"
 #include "gc-internal.h"
diff --git a/libguile/ioext.c b/libguile/ioext.c
index e5553575e..9ba8a0693 100644
--- a/libguile/ioext.c
+++ b/libguile/ioext.c
@@ -38,7 +38,7 @@
 #include "extensions.h"
 #include "fdes-finalizers.h"
 #include "feature.h"
-#include "fports.h"
+#include "fports-internal.h"
 #include "gsubr.h"
 #include "hashtab.h"
 #include "numbers.h"
diff --git a/libguile/posix.c b/libguile/posix.c
index 39efe213f..f51cae6f6 100644
--- a/libguile/posix.c
+++ b/libguile/posix.c
@@ -62,7 +62,7 @@
 #include "extensions.h"
 #include "feature.h"
 #include "finalizers.h"
-#include "fports.h"
+#include "fports-internal.h"
 #include "gettext.h"
 #include "gsubr.h"
 #include "keywords.h"
diff --git a/libguile/socket.c b/libguile/socket.c
index 0ba1058e6..9571a334c 100644
--- a/libguile/socket.c
+++ b/libguile/socket.c
@@ -61,7 +61,7 @@
 #include "bytevectors.h"
 #include "dynwind.h"
 #include "feature.h"
-#include "fports.h"
+#include "fports-internal.h"
 #include "gsubr.h"
 #include "list.h"
 #include "modules.h"

Reply via email to