From: Peter Klausler Date: Tue, 6 Dec 2022 22:00:21 +0000 (-0800) Subject: [flang] Restore old unit locking behavior X-Git-Tag: upstream/17.0.6~24669 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=00a1c6d036328db46c20cda88edb020ddbda05b4;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/flang/runtime/lock.h b/flang/runtime/lock.h index 7af1ab8..5fdcf47 100644 --- a/flang/runtime/lock.h +++ b/flang/runtime/lock.h @@ -41,9 +41,24 @@ public: 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 @@ public: 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 357d237..092a0a2 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(); - CriticalSection critical{lock_}; - isBusy_ = false; + lock_.Drop(); } void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord( diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index 9f2b0bf..c49f479 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -71,17 +71,14 @@ public: template 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(std::forward(xs)...)}; if constexpr (!std::is_same_v) { state.mutableModes() = ConnectionState::modes; @@ -137,8 +134,6 @@ private: 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};