[patch, libfortran] Fix PR 123446, broken bootstrap

Thomas Koenig <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
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.
p3.diff (text/x-patch, 4.5 KB)
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;
 		}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.