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