================
@@ -262,44 +357,73 @@ 
DependencyScanningWorkerFilesystem::getOrEmplaceSharedEntryForUID(
                                        std::move(TEntry.Contents));
 }
 
-const CachedFileSystemEntry *
-DependencyScanningWorkerFilesystem::findEntryByFilenameWithWriteThrough(
-    StringRef Filename) {
-  if (const auto *Entry = LocalCache.findEntryByFilename(Filename))
-    return Entry;
-  auto &Shard = SharedCache.getShardForFilename(Filename);
-  if (const auto *Entry = Shard.findEntryByFilename(Filename))
-    return &LocalCache.insertEntryForFilename(Filename, *Entry);
-  return nullptr;
-}
-
 llvm::ErrorOr<const CachedFileSystemEntry &>
 DependencyScanningWorkerFilesystem::computeAndStoreResult(
     StringRef OriginalFilename, StringRef FilenameForLookup) {
-  llvm::ErrorOr<llvm::vfs::Status> Stat =
-      getUnderlyingFS().status(OriginalFilename);
-  if (!Stat) {
-    const auto &Entry =
-        getOrEmplaceSharedEntryForFilename(FilenameForLookup, Stat.getError());
-    return insertLocalEntryForFilename(FilenameForLookup, Entry);
-  }
-
-  if (const auto *Entry = findSharedEntryByUID(*Stat))
-    return insertLocalEntryForFilename(FilenameForLookup, *Entry);
-
-  auto TEntry =
-      Stat->isDirectory() ? TentativeEntry(*Stat) : readFile(OriginalFilename);
+  auto &FilenameShard = SharedCache.getShardForFilename(FilenameForLookup);
+
+  // Acquire a per-filename in-progress entry. If another worker has already
+  // produced an entry under this filename, or is currently producing one,
+  // adopt its result instead of duplicating the underlying filesystem.
+  auto FilenameSlot = FilenameShard.acquireFilenameSlot(FilenameForLookup);
+  if (FilenameSlot.Resolved)
+    return insertLocalEntryForFilename(FilenameForLookup,
+                                       *FilenameSlot.Resolved);
+
+  // Compute the result.
+  std::shared_ptr<DependencyScanningFilesystemSharedCache::InProgressEntry>
+      ProducerSlot = std::move(FilenameSlot.Produce);
+  const CachedFileSystemEntry *ProducedEntry = nullptr;
+  auto ComputeResult = [&]() -> llvm::ErrorOr<const CachedFileSystemEntry &> {
+    llvm::ErrorOr<llvm::vfs::Status> Stat =
+        getUnderlyingFS().status(OriginalFilename);
+    if (!Stat) {
+      const auto &Entry = getOrEmplaceSharedEntryForFilename(FilenameForLookup,
+                                                             Stat.getError());
+      ProducedEntry = &Entry;
+      return insertLocalEntryForFilename(FilenameForLookup, Entry);
+    }
 
-  const CachedFileSystemEntry *SharedEntry = [&]() {
-    if (TEntry) {
-      const auto &UIDEntry = getOrEmplaceSharedEntryForUID(std::move(*TEntry));
-      return &getOrInsertSharedEntryForFilename(FilenameForLookup, UIDEntry);
+    // Acquire a per-UID producer slot to dedup concurrent readFile()
+    // calls across workers that arrived under different filenames
+    // pointing at the same on-disk file.
+    auto &UIDShard = SharedCache.getShardForUID(Stat->getUniqueID());
+    auto UIDSlot = UIDShard.acquireUIDSlot(Stat->getUniqueID());
+    const CachedFileSystemEntry *SharedEntry = nullptr;
+    if (UIDSlot.Resolved) {
+      SharedEntry = UIDSlot.Resolved;
+    } else {
+      auto TEntry = Stat->isDirectory() ? TentativeEntry(*Stat)
+                                        : readFile(OriginalFilename);
+      if (TEntry) {
+        SharedEntry = &getOrEmplaceSharedEntryForUID(std::move(*TEntry));
+        // Publish the UID-keyed entry to anyone waiting on this UID.
+        UIDShard.fulfilUIDSlot(Stat->getUniqueID(), UIDSlot.Produce,
+                               SharedEntry);
+      } else {
+        // `readFile` failed despite `stat` succeeding. Cache
+        // the failure under the filename, and publish that same entry under
+        // the UID so that awaiting workers surface the error rather than 
racing
+        // to retry the open.
+        SharedEntry = &getOrEmplaceSharedEntryForFilename(FilenameForLookup,
+                                                          TEntry.getError());
+        UIDShard.fulfilUIDSlot(Stat->getUniqueID(), UIDSlot.Produce,
+                               SharedEntry);
+      }
     }
-    return &getOrEmplaceSharedEntryForFilename(FilenameForLookup,
-                                               TEntry.getError());
-  }();
 
-  return insertLocalEntryForFilename(FilenameForLookup, *SharedEntry);
+    // Bind the resolved/produced entry to this filename in the shared cache
+    // (idempotent if already there) and the local cache.
+    SharedEntry =
+        &getOrInsertSharedEntryForFilename(FilenameForLookup, *SharedEntry);
+    ProducedEntry = SharedEntry;
+    return insertLocalEntryForFilename(FilenameForLookup, *SharedEntry);
+  };
+
+  auto Result = ComputeResult();
----------------
artemcm wrote:

Done. 

https://github.com/llvm/llvm-project/pull/199680
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to