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; }
