https://gcc.gnu.org/g:d5964a270de33349ff137b1835046e65ec81fa1e

commit r16-6586-gd5964a270de33349ff137b1835046e65ec81fa1e
Author: Thomas Koenig <[email protected]>
Date:   Thu Jan 8 21:35:27 2026 +0100

    Fix compile failure on systems not supporting gthreads.
    
    I just realized that it is possible to run a check by #undef - ing
     __GTHREADS_CXX0X in async.h.  Doing so promptly found another syntax
     error, which this version of the patch fixes.
    
    PR libfortran/123446
    PR libfortran/119136
    
    libgfortran/ChangeLog:
    
            * io/async.h: DEBUG_ASYNC needs gtreads support.
            (LOCK_UNIT): Only lock when there is pthreads support and it is 
active.
            Otherwise, just set unit->self to 1.
            (UNLOCK_UNIT): Only unlock when there is pthreads support and it is 
active.
            Otherwise, just set unit->self to 0.
            (TRYLOCK_UNIT): Only try locking when thee is pthreads support and 
it is
            active.  Otherwise, return unit->self.
            (OWN_THREAD_ID): New macro.
            * io/io.h: gfc_unit's self is an int when there is no gthreads 
support.
            * io/unit.c (check_for_recursive): Check for equality of unit which
            locked to OWN_THREAD_ID.

Diff:
---
 libgfortran/io/async.h | 72 ++++++++++++++++++++++++++++++++++++++++++++------
 libgfortran/io/io.h    |  2 ++
 libgfortran/io/unit.c  |  7 ++---
 3 files changed, 70 insertions(+), 11 deletions(-)

diff --git a/libgfortran/io/async.h b/libgfortran/io/async.h
index fcd0dd2bb528..c4451f28f318 100644
--- a/libgfortran/io/async.h
+++ b/libgfortran/io/async.h
@@ -29,6 +29,9 @@
    __gthread_cond_t and __gthread_equal / __gthread_self.  Check
    this.  */
 
+/* #undef __GTHREADS_CXX0X - uncomment for checking non-threading
+   systems.  */
+
 #if defined(__GTHREAD_HAS_COND) && defined(__GTHREADS_CXX0X)
 #define ASYNC_IO 1
 #else
@@ -42,6 +45,9 @@
 #undef DEBUG_ASYNC
 
 #ifdef DEBUG_ASYNC
+#ifndef __GTHREADS_CXX0X
+#error "gthreads support required for DEBUG_ASYNC"
+#endif
 
 /* Define this if you want to use ANSI color escape sequences in your
    debugging output.  */
@@ -369,25 +375,56 @@
 
 #define DEBUG_LINE(...) __VA_ARGS__
 
-#else
+#else  /* DEBUG_ASYNC */
+
 #define DEBUG_PRINTF(...) {}
 #define CHECK_LOCK(au, mutex, status) {}
 #define NOTE(str, ...) {}
 #define DEBUG_LINE(...)
 #define T_ERROR(func, ...) func(__VA_ARGS__)
 #define LOCK(mutex) INTERN_LOCK (mutex)
-#define LOCK_UNIT(unit) do {                               \
-    if (__gthread_active_p ()) {                           \
-      LOCK (&(unit)->lock); (unit)->self = __gthread_self ();  \
-    }                                                          \
+
+#ifdef __GTHREADS_CXX0X
+
+/* When pthreads are not active, we do not touch the lock for locking /
+   unlocking; the only use for this is checking for recursion.  */
+
+#define LOCK_UNIT(unit) do {                                   \
+  if (__gthread_active_p ()) {                                 \
+    LOCK (&(unit)->lock); (unit)->self = __gthread_self ();    \
+  } else {                                                     \
+    (unit)->self = 1;                                          \
+  }                                                            \
   } while(0)
+#else
+
+#define LOCK_UNIT(unit) do { \
+    (unit)->self = 1;       \
+  } while(0)
+
+#endif
+
 #define UNLOCK(mutex) INTERN_UNLOCK (mutex)
+
+#ifdef __GTHREADS_CXX0X
+
 #define UNLOCK_UNIT(unit) do {                                         \
     if (__gthread_active_p ()) {                                       \
       (unit)->self = 0 ; UNLOCK(&(unit)->lock);                                
\
+    } else {                                                           \
+      (unit)->self = 0;                                                        
\
     }                                                                  \
+} while(0)
+#else
+#define UNLOCK_UNIT(unit) do {                 \
+    (unit)->self = 0;                          \
   } while(0)
+
+#endif
+
 #define TRYLOCK(mutex) (__gthread_mutex_trylock (mutex))
+
+#ifdef __GTHREADS_CXX0X
 #define TRYLOCK_UNIT(unit) ({                                  \
       int res;                                                 \
       if (__gthread_active_p ()) {                             \
@@ -395,10 +432,20 @@
        if (!res)                                               \
          (unit)->self = __gthread_self ();                     \
       }                                                                \
-      else                                                     \
-       res = 0;                                                \
+      else {                                                   \
+       res = (unit)->self;                                     \
+       (unit)->self = 1;                                       \
+      }                                                                \
       res;                                                     \
     })
+#else
+#define TRYLOCK_UNIT(unit) ({ \
+      int res = (unit)->self; \
+      (unit)->self = 1;              \
+      res;                   \
+    })
+#endif
+
 #ifdef __GTHREAD_RWLOCK_INIT
 #define RDLOCK(rwlock) INTERN_RDLOCK (rwlock)
 #define WRLOCK(rwlock) INTERN_WRLOCK (rwlock)
@@ -504,6 +551,15 @@ DEBUG_LINE (extern __gthread_rwlock_t debug_queue_rwlock;)
 extern __thread gfc_unit *thread_unit;
 #endif
 
+/* When threading is not active, or there is no thread system, we fake the ID
+   to be 1.  */
+
+#ifdef __GTHREADS_CXX0X
+#define OWN_THREAD_ID (__gthread_active_p () ? __gthread_self () : 1)
+#else
+#define OWN_THREAD_ID 1
+#endif
+
 enum aio_do {
   AIO_INVALID = 0,
   AIO_DATA_TRANSFER_INIT,
@@ -583,7 +639,7 @@ bool async_wait_id (st_parameter_common *, async_unit *, 
int);
 internal_proto (async_wait_id);
 
 bool collect_async_errors (st_parameter_common *, async_unit *);
-internal_proto (collect_async_errors); 
+internal_proto (collect_async_errors);
 
 void async_close (async_unit *);
 internal_proto (async_close);
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 1d33624b7d80..ebb225296681 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -730,6 +730,8 @@ typedef struct gfc_unit
   GFC_IO_INT size_used;
 #ifdef __GTHREADS_CXX0X
   __gthread_t self;
+#else
+  int self;
 #endif
 }
 gfc_unit;
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index 9474e9bb8f87..fac24db014dc 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -348,6 +348,7 @@ get_gfc_unit_from_unit_root (int n)
 /* Recursive I/O is not allowed. Check to see if the UNIT exists and if
    so, check if the UNIT is locked already.  This check does not apply
    to DTIO.  */
+
 void
 check_for_recursive (st_parameter_dt *dtp)
 {
@@ -367,9 +368,9 @@ check_for_recursive (st_parameter_dt *dtp)
                  /* The lock failed.  This unit is locked either our own
                     thread, which is illegal recursive I/O, or somebody by
                     else, in which case we are doing OpenMP or similar; this
-                    is harmless and permitted.  */
-                 __gthread_t locker = __atomic_load_n (&p->self, 
__ATOMIC_RELAXED);
-                 if (locker == __gthread_self ())
+                    is harmless and permitted.  When threading is not active, 
or
+                    there is no thread system, we fake the ID to be 1.  */
+                 if (__atomic_load_n (&p->self, __ATOMIC_RELAXED) == 
OWN_THREAD_ID)
                    generate_error (&dtp->common, LIBERROR_RECURSIVE_IO, NULL);
                  return;
                }

Reply via email to