[flang-commits] [flang] 00a1c6d - [flang] Restore old unit locking behavior
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Thu Dec 8 08:34:55 PST 2022
Author: Peter Klausler
Date: 2022-12-08T08:34:46-08:00
New Revision: 00a1c6d036328db46c20cda88edb020ddbda05b4
URL: https://github.com/llvm/llvm-project/commit/00a1c6d036328db46c20cda88edb020ddbda05b4
DIFF: https://github.com/llvm/llvm-project/commit/00a1c6d036328db46c20cda88edb020ddbda05b4.diff
LOG: [flang] Restore old unit locking behavior
Rework the recursive I/O error check on I/O units so that
threads again hold a lock on a unit throughout an I/O statement.
Add an API to the runtime's Lock class implementation for pthreads
to allow detection of solf-deadlock without depending on EDEADLK
or recursive mutexes.
This should fix I/O from OpenMP threads.
Differential Revision: https://reviews.llvm.org/D139477
Added:
Modified:
flang/runtime/lock.h
flang/runtime/unit.cpp
flang/runtime/unit.h
Removed:
################################################################################
diff --git a/flang/runtime/lock.h b/flang/runtime/lock.h
index 7af1ab89758ed..5fdcf4745c21c 100644
--- a/flang/runtime/lock.h
+++ b/flang/runtime/lock.h
@@ -41,9 +41,24 @@ class Lock {
void Take() {
while (pthread_mutex_lock(&mutex_)) {
}
+ holder_ = pthread_self();
+ isBusy_ = true;
+ }
+ bool TakeIfNoDeadlock() {
+ if (isBusy_) {
+ auto thisThread{pthread_self()};
+ if (pthread_equal(thisThread, holder_)) {
+ return false;
+ }
+ }
+ Take();
+ return true;
}
bool Try() { return pthread_mutex_trylock(&mutex_) == 0; }
- void Drop() { pthread_mutex_unlock(&mutex_); }
+ void Drop() {
+ isBusy_ = false;
+ pthread_mutex_unlock(&mutex_);
+ }
#elif defined(_WIN32)
Lock() { InitializeCriticalSection(&cs_); }
~Lock() { DeleteCriticalSection(&cs_); }
@@ -66,6 +81,8 @@ class Lock {
private:
#if USE_PTHREADS
pthread_mutex_t mutex_{};
+ volatile bool isBusy_{false};
+ volatile pthread_t holder_;
#elif defined(_WIN32)
CRITICAL_SECTION cs_;
#else
diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp
index 357d237c63e43..092a0a27b5c23 100644
--- a/flang/runtime/unit.cpp
+++ b/flang/runtime/unit.cpp
@@ -714,8 +714,7 @@ bool ExternalFileUnit::SetDirectRec(
void ExternalFileUnit::EndIoStatement() {
io_.reset();
u_.emplace<std::monostate>();
- CriticalSection critical{lock_};
- isBusy_ = false;
+ lock_.Drop();
}
void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord(
diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index 9f2b0bf3a9861..c49f479830338 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -71,17 +71,14 @@ class ExternalFileUnit : public ConnectionState,
template <typename A, typename... X>
IoStatementState &BeginIoStatement(const Terminator &terminator, X &&...xs) {
- bool alreadyBusy{false};
- {
- CriticalSection critical{lock_};
- alreadyBusy = isBusy_;
- isBusy_ = true; // cleared in EndIoStatement()
- }
- if (alreadyBusy) {
- terminator.Crash("Could not acquire exclusive lock on unit %d, perhaps "
- "due to an attempt to perform recursive I/O",
- unitNumber_);
+ // Take lock_ and hold it until EndIoStatement().
+#if USE_PTHREADS
+ if (!lock_.TakeIfNoDeadlock()) {
+ terminator.Crash("Recursive I/O attempted on unit %d", unitNumber_);
}
+#else
+ lock_.Take();
+#endif
A &state{u_.emplace<A>(std::forward<X>(xs)...)};
if constexpr (!std::is_same_v<A, OpenStatementState>) {
state.mutableModes() = ConnectionState::modes;
@@ -137,8 +134,6 @@ class ExternalFileUnit : public ConnectionState,
std::int32_t ReadHeaderOrFooter(std::int64_t frameOffset);
Lock lock_;
- // TODO: replace with a thread ID
- bool isBusy_{false}; // under lock_
int unitNumber_{-1};
Direction direction_{Direction::Output};
More information about the flang-commits
mailing list