[flang-commits] [flang] c7f4c33 - [flang] Make NEWUNIT= use a range suitable for INTEGER(KIND=1) and recycle unit numbers

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon Jan 31 15:20:28 PST 2022


Author: Peter Klausler
Date: 2022-01-31T15:20:21-08:00
New Revision: c7f4c333af2bd7b21dfb58df6cea59b30f6576d7

URL: https://github.com/llvm/llvm-project/commit/c7f4c333af2bd7b21dfb58df6cea59b30f6576d7
DIFF: https://github.com/llvm/llvm-project/commit/c7f4c333af2bd7b21dfb58df6cea59b30f6576d7.diff

LOG: [flang] Make NEWUNIT= use a range suitable for INTEGER(KIND=1) and recycle unit numbers

Use a bit-set to manage runtime-generated I/O unit numbers, recycle
them after they're closed, and use a range of values that fits in
a minimal-sized integer.

Differential Revision: https://reviews.llvm.org/D118651

Added: 
    

Modified: 
    flang/runtime/io-api.cpp
    flang/runtime/unit-map.cpp
    flang/runtime/unit-map.h
    flang/runtime/unit.h

Removed: 
    


################################################################################
diff  --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp
index 9c50adf18489..5d35c009ebfb 100644
--- a/flang/runtime/io-api.cpp
+++ b/flang/runtime/io-api.cpp
@@ -304,7 +304,8 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
 Cookie IONAME(BeginOpenNewUnit)( // OPEN(NEWUNIT=j)
     const char *sourceFile, int sourceLine) {
   Terminator terminator{sourceFile, sourceLine};
-  ExternalFileUnit &unit{ExternalFileUnit::NewUnit(terminator)};
+  ExternalFileUnit &unit{
+      ExternalFileUnit::NewUnit(terminator, false /*not child I/O*/)};
   return &unit.BeginIoStatement<OpenStatementState>(
       unit, false /*was an existing file*/, sourceFile, sourceLine);
 }

diff  --git a/flang/runtime/unit-map.cpp b/flang/runtime/unit-map.cpp
index 4c931871c017..385ab9820ecb 100644
--- a/flang/runtime/unit-map.cpp
+++ b/flang/runtime/unit-map.cpp
@@ -10,6 +10,21 @@
 
 namespace Fortran::runtime::io {
 
+// See 12.5.6.12 in Fortran 2018.  NEWUNIT= unit numbers are negative,
+// and not equal -1 (or ERROR_UNIT, if it were negative, which it isn't.)
+ExternalFileUnit &UnitMap::NewUnit(const Terminator &terminator) {
+  CriticalSection critical{lock_};
+  std::optional<std::size_t> n;
+  n = (~busyNewUnits_).LeastElement();
+  if (!n.has_value()) {
+    terminator.Crash(
+        "No available unit number for NEWUNIT= or internal child I/O");
+  }
+  busyNewUnits_.set(*n);
+  // bit position 0 <-> unit -2; kind=1 units are in [-65..-2]
+  return Create(static_cast<int>(-2 - *n), terminator);
+}
+
 ExternalFileUnit *UnitMap::LookUpForClose(int n) {
   CriticalSection critical{lock_};
   Chain *previous{nullptr};
@@ -36,6 +51,10 @@ void UnitMap::DestroyClosed(ExternalFileUnit &unit) {
     Chain *previous{nullptr};
     for (p = closing_.get(); p; previous = p, p = p->next.get()) {
       if (&p->unit == &unit) {
+        int n{unit.unitNumber()};
+        if (n <= -2) {
+          busyNewUnits_.reset(static_cast<std::size_t>(-2 - n));
+        }
         if (previous) {
           previous->next.swap(p->next);
         } else {

diff  --git a/flang/runtime/unit-map.h b/flang/runtime/unit-map.h
index d7d3613b53e6..b7f9aeee8243 100644
--- a/flang/runtime/unit-map.h
+++ b/flang/runtime/unit-map.h
@@ -14,7 +14,9 @@
 
 #include "lock.h"
 #include "unit.h"
+#include "flang/Common/constexpr-bitset.h"
 #include "flang/Runtime/memory.h"
+#include <cstdint>
 #include <cstdlib>
 
 namespace Fortran::runtime::io {
@@ -40,10 +42,7 @@ class UnitMap {
     return Find(path);
   }
 
-  ExternalFileUnit &NewUnit(const Terminator &terminator) {
-    CriticalSection critical{lock_};
-    return Create(nextNewUnit_--, terminator);
-  }
+  ExternalFileUnit &NewUnit(const Terminator &);
 
   // To prevent races, the unit is removed from the map if it exists,
   // and put on the closing_ list until DestroyClosed() is called.
@@ -84,7 +83,7 @@ class UnitMap {
 
   Lock lock_;
   OwningPtr<Chain> bucket_[buckets_]{}; // all owned by *this
-  int nextNewUnit_{-1000}; // see 12.5.6.12 in Fortran 2018
+  common::BitSet<64> busyNewUnits_;
   OwningPtr<Chain> closing_{nullptr}; // units during CLOSE statement
 };
 } // namespace Fortran::runtime::io

diff  --git a/flang/runtime/unit.h b/flang/runtime/unit.h
index eaaccd578d8b..b7f4e271c01f 100644
--- a/flang/runtime/unit.h
+++ b/flang/runtime/unit.h
@@ -50,7 +50,7 @@ class ExternalFileUnit : public ConnectionState,
   static ExternalFileUnit *LookUp(const char *path);
   static ExternalFileUnit &CreateNew(int unit, const Terminator &);
   static ExternalFileUnit *LookUpForClose(int unit);
-  static ExternalFileUnit &NewUnit(const Terminator &, bool forChildIo = false);
+  static ExternalFileUnit &NewUnit(const Terminator &, bool forChildIo);
   static void CloseAll(IoErrorHandler &);
   static void FlushAll(IoErrorHandler &);
 


        


More information about the flang-commits mailing list