Hello world,

the attached patch hopefully fixes the bootstrap problem on
systems without threading support. I have tested it as far
as I could, but I could not find any way to test it. It looks
OK to me, but...

I also tested it on a system where there is no pthreads in
libc, that should hopefully also be fixed.

Anybody up for testing on one of the systems that I do not have
access to?  OK for trunk?

Best regards

        Thomas

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 --git a/libgfortran/io/async.h b/libgfortran/io/async.h
index 07f1557a98c..ece621f3cba 100644
--- a/libgfortran/io/async.h
+++ b/libgfortran/io/async.h
@@ -42,6 +42,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 +372,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 +429,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 +548,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 +636,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 e0025d08d87..029fb6b9414 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 6c8ee798b22..8cf85f6fb15 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