summaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorThomas König <tkoenig@gcc.gnu.org>2020-02-13 22:22:04 +0100
committerThomas König <tkoenig@gcc.gnu.org>2020-02-22 12:31:18 +0100
commitc080a6fb6f0cf402affc287fc600c189980cfb2d (patch)
tree4ecdffcee6aef4297181fdea8a9fd504208c5a31 /libgfortran
parent3004aba7a0e041cafd2adf927e0b3a610b16e7c0 (diff)
downloadgcc-c080a6fb6f0cf402affc287fc600c189980cfb2d.tar.gz
Use au->lock exclusively for locking in async I/O.
2020-02-18 Thomas Koenig <tkoenig@gcc.gnu.org> Backport from trunk PR fortran/93599 * io/async.c (destroy_adv_cond): Do not destroy lock. (async_io): Make sure au->lock is locked for finishing of thread. Do not lock/unlock around signalling emptysignal. Unlock au->lock before return. (init_adv_cond): Do not initialize lock. (enqueue_transfer): Unlock after signal. (enqueue_done_id): Likewise. (enqueue_done): Likewise. (enqueue_close): Likewise. (enqueue_data_transfer): Likewise. (async_wait_id): Do not lock/unlock around signalling au->work. (async_wait): Unlock after signal. * io/async.h (SIGNAL): Add comment about needed au->lock. Remove locking/unlocking of advcond->lock. (WAIT_SIGNAL_MUTEX): Add comment. Remove locking/unlocking of advcond->lock. Unlock mutex only at the end. Loop on __ghread_cond_wait returning zero. (REVOKE_SIGNAL): Add comment. Remove locking/unlocking of advcond->lock. (struct adv_cond): Remove mutex from struct.
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog25
-rw-r--r--libgfortran/io/async.c23
-rw-r--r--libgfortran/io/async.h45
3 files changed, 56 insertions, 37 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 340396dea07..ce75fe80636 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,28 @@
+2020-02-22 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ Backport from trunk
+ PR fortran/93599
+ * io/async.c (destroy_adv_cond): Do not destroy lock.
+ (async_io): Make sure au->lock is locked for finishing of thread.
+ Do not lock/unlock around signalling emptysignal. Unlock au->lock
+ before return.
+ (init_adv_cond): Do not initialize lock.
+ (enqueue_transfer): Unlock after signal.
+ (enqueue_done_id): Likewise.
+ (enqueue_done): Likewise.
+ (enqueue_close): Likewise.
+ (enqueue_data_transfer): Likewise.
+ (async_wait_id): Do not lock/unlock around signalling au->work.
+ (async_wait): Unlock after signal.
+ * io/async.h (SIGNAL): Add comment about needed au->lock.
+ Remove locking/unlocking of advcond->lock.
+ (WAIT_SIGNAL_MUTEX): Add comment. Remove locking/unlocking of
+ advcond->lock. Unlock mutex only at the end. Loop on
+ __ghread_cond_wait returning zero.
+ (REVOKE_SIGNAL): Add comment. Remove locking/unlocking of
+ advcond->lock.
+ (struct adv_cond): Remove mutex from struct.
+
2020-01-21 Jerry DeLisle <jvdelisle@gcc.gnu.org>
Backport from mainline
diff --git a/libgfortran/io/async.c b/libgfortran/io/async.c
index e3d1d01122e..28b84f6613a 100644
--- a/libgfortran/io/async.c
+++ b/libgfortran/io/async.c
@@ -80,7 +80,6 @@ update_pdt (st_parameter_dt **old, st_parameter_dt *new) {
static void
destroy_adv_cond (struct adv_cond *ac)
{
- T_ERROR (__gthread_mutex_destroy, &ac->lock);
T_ERROR (__gthread_cond_destroy, &ac->signal);
}
@@ -156,6 +155,7 @@ async_io (void *arg)
case AIO_CLOSE:
NOTE ("Received AIO_CLOSE");
+ LOCK (&au->lock);
goto finish_thread;
default:
@@ -175,7 +175,6 @@ async_io (void *arg)
else if (ctq->type == AIO_CLOSE)
{
NOTE ("Received AIO_CLOSE during error condition");
- UNLOCK (&au->lock);
goto finish_thread;
}
}
@@ -189,9 +188,7 @@ async_io (void *arg)
au->tail = NULL;
au->head = NULL;
au->empty = 1;
- UNLOCK (&au->lock);
SIGNAL (&au->emptysignal);
- LOCK (&au->lock);
}
finish_thread:
au->tail = NULL;
@@ -199,6 +196,7 @@ async_io (void *arg)
au->empty = 1;
SIGNAL (&au->emptysignal);
free (ctq);
+ UNLOCK (&au->lock);
return NULL;
}
@@ -223,7 +221,6 @@ static void
init_adv_cond (struct adv_cond *ac)
{
ac->pending = 0;
- __GTHREAD_MUTEX_INIT_FUNCTION (&ac->lock);
__GTHREAD_COND_INIT_FUNCTION (&ac->signal);
}
@@ -279,8 +276,8 @@ enqueue_transfer (async_unit *au, transfer_args *arg, enum aio_do type)
au->tail = tq;
REVOKE_SIGNAL (&(au->emptysignal));
au->empty = false;
- UNLOCK (&au->lock);
SIGNAL (&au->work);
+ UNLOCK (&au->lock);
}
/* Enqueue an st_write_done or st_read_done which contains an ID. */
@@ -303,8 +300,8 @@ enqueue_done_id (async_unit *au, enum aio_do type)
au->empty = false;
ret = au->id.high++;
NOTE ("Enqueue id: %d", ret);
- UNLOCK (&au->lock);
SIGNAL (&au->work);
+ UNLOCK (&au->lock);
return ret;
}
@@ -324,8 +321,8 @@ enqueue_done (async_unit *au, enum aio_do type)
au->tail = tq;
REVOKE_SIGNAL (&(au->emptysignal));
au->empty = false;
- UNLOCK (&au->lock);
SIGNAL (&au->work);
+ UNLOCK (&au->lock);
}
/* Enqueue a CLOSE statement. */
@@ -344,8 +341,8 @@ enqueue_close (async_unit *au)
au->tail = tq;
REVOKE_SIGNAL (&(au->emptysignal));
au->empty = false;
- UNLOCK (&au->lock);
SIGNAL (&au->work);
+ UNLOCK (&au->lock);
}
/* The asynchronous unit keeps the currently active PDT around.
@@ -374,9 +371,9 @@ enqueue_data_transfer_init (async_unit *au, st_parameter_dt *dt, int read_flag)
au->tail->next = tq;
au->tail = tq;
REVOKE_SIGNAL (&(au->emptysignal));
- au->empty = 0;
- UNLOCK (&au->lock);
+ au->empty = false;
SIGNAL (&au->work);
+ UNLOCK (&au->lock);
}
/* Collect the errors that may have happened asynchronously. Return true if
@@ -430,9 +427,7 @@ async_wait_id (st_parameter_common *cmp, async_unit *au, int i)
NOTE ("Waiting for id %d", i);
if (au->id.waiting < i)
au->id.waiting = i;
- UNLOCK (&au->lock);
SIGNAL (&(au->work));
- LOCK (&au->lock);
WAIT_SIGNAL_MUTEX (&(au->id.done),
(au->id.low >= au->id.waiting || au->empty), &au->lock);
LOCK (&au->lock);
@@ -454,8 +449,8 @@ async_wait (st_parameter_common *cmp, async_unit *au)
if (cmp == NULL)
cmp = au->error.cmp;
- SIGNAL (&(au->work));
LOCK (&(au->lock));
+ SIGNAL (&(au->work));
if (au->empty)
{
diff --git a/libgfortran/io/async.h b/libgfortran/io/async.h
index 3ac51772502..0fe407945c3 100644
--- a/libgfortran/io/async.h
+++ b/libgfortran/io/async.h
@@ -229,44 +229,44 @@
#if ASYNC_IO
+/* au->lock has to be held when calling this macro. */
+
#define SIGNAL(advcond) do{ \
- INTERN_LOCK (&(advcond)->lock); \
(advcond)->pending = 1; \
DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_ORANGE "SIGNAL: " DEBUG_NORM \
#advcond, __FUNCTION__, __LINE__, (void *) advcond); \
- T_ERROR (__gthread_cond_broadcast, &(advcond)->signal); \
- INTERN_UNLOCK (&(advcond)->lock); \
+ T_ERROR (__gthread_cond_broadcast, &(advcond)->signal); \
} while (0)
+/* Has to be entered with mutex locked. */
+
#define WAIT_SIGNAL_MUTEX(advcond, condition, mutex) do{ \
__label__ finish; \
- INTERN_LOCK (&((advcond)->lock)); \
DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_BLUE "WAITING: " DEBUG_NORM \
#advcond, __FUNCTION__, __LINE__, (void *) advcond); \
- if ((advcond)->pending || (condition)){ \
- UNLOCK (mutex); \
+ if ((advcond)->pending || (condition)) \
goto finish; \
- } \
- UNLOCK (mutex); \
- while (!__gthread_cond_wait(&(advcond)->signal, &(advcond)->lock)) { \
- { int cond; \
- LOCK (mutex); cond = condition; UNLOCK (mutex); \
- if (cond){ \
- DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_ORANGE "REC: " DEBUG_NORM \
- #advcond, __FUNCTION__, __LINE__, (void *)advcond); \
- break; \
- } \
+ while (1) \
+ { \
+ int err_ret = __gthread_cond_wait(&(advcond)->signal, mutex); \
+ if (err_ret) internal_error (NULL, "WAIT_SIGNAL_MUTEX failed"); \
+ if (condition) \
+ { \
+ DEBUG_PRINTF ("%s%-75s %20s():%-5d %18p\n", aio_prefix, DEBUG_ORANGE \
+ "REC: " DEBUG_NORM \
+ #advcond, __FUNCTION__, __LINE__, (void *)advcond); \
+ break; \
+ } \
} \
- } \
finish: \
- (advcond)->pending = 0; \
- INTERN_UNLOCK (&((advcond)->lock)); \
- } while (0)
+ (advcond)->pending = 0; \
+ UNLOCK (mutex); \
+ } while (0)
+
+/* au->lock has to be held when calling this macro. */
#define REVOKE_SIGNAL(advcond) do{ \
- INTERN_LOCK (&(advcond)->lock); \
(advcond)->pending = 0; \
- INTERN_UNLOCK (&(advcond)->lock); \
} while (0)
#else
@@ -330,7 +330,6 @@ struct adv_cond
{
#if ASYNC_IO
int pending;
- __gthread_mutex_t lock;
__gthread_cond_t signal;
#endif
};