https://github.com/atassis updated https://github.com/llvm/llvm-project/pull/210587
>From 2848afea639bf701e8023e7694c39954b2f6ec1e Mon Sep 17 00:00:00 2001 From: Taimuraz Kaitmazov <[email protected]> Date: Sun, 19 Jul 2026 12:18:36 +0300 Subject: [PATCH] [clang][modules] Write each module's timestamp once per build session Under -fmodules-validate-once-per-build-session, two dependency-scanning workers that share an implicitly-built module can both find its timestamp stale and record it. The value is the same either way, but per-module work and the timestamp_write log should not scale with worker count, and the extra write made ClangScanDeps/logging-two-threads.c flaky. Record the timestamp once under the cache entry's lock so only the first worker writes it. --- .../InProcessModuleCache.cpp | 9 ++++-- .../InProcessModuleCacheTest.cpp | 30 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/clang/lib/DependencyScanning/InProcessModuleCache.cpp b/clang/lib/DependencyScanning/InProcessModuleCache.cpp index bc6ff88c57323..3608a18dd7794 100644 --- a/clang/lib/DependencyScanning/InProcessModuleCache.cpp +++ b/clang/lib/DependencyScanning/InProcessModuleCache.cpp @@ -128,10 +128,15 @@ class InProcessModuleCache : public ModuleCache { void updateModuleTimestamp(StringRef Filename) override { // Note: This essentially replaces FS contention with mutex contention. - auto &Timestamp = getOrCreateEntry(Filename).Timestamp; + ModuleCacheEntry &Entry = getOrCreateEntry(Filename); + std::lock_guard<std::mutex> Lock(Entry.Mutex); + // A shared module may be validated by several workers at once; only the + // first records its timestamp (0 means "not recorded yet"). + if (Entry.Timestamp) + return; + Entry.Timestamp = llvm::sys::toTimeT(std::chrono::system_clock::now()); Logger.log() << "timestamp_write: " << Filename; - Timestamp.store(llvm::sys::toTimeT(std::chrono::system_clock::now())); } void maybePrune(StringRef Path, time_t PruneInterval, diff --git a/clang/unittests/DependencyScanning/InProcessModuleCacheTest.cpp b/clang/unittests/DependencyScanning/InProcessModuleCacheTest.cpp index 5b667a4989f50..1a5aa23ef297c 100644 --- a/clang/unittests/DependencyScanning/InProcessModuleCacheTest.cpp +++ b/clang/unittests/DependencyScanning/InProcessModuleCacheTest.cpp @@ -74,3 +74,33 @@ TEST(InProcessModuleCache, ReadReadInvalidation) { EXPECT_EQ(Buf1->getBuffer().begin(), Buf2->getBuffer().begin()); EXPECT_EQ(Buf1->getBuffer().end(), Buf2->getBuffer().end()); } + +TEST(InProcessModuleCache, TimestampWrittenOncePerSession) { +#ifndef _WIN32 + // Logging (and thus this assertion) is only enabled on non-Windows platforms. + int FD; + llvm::SmallString<256> LogPath; + ASSERT_FALSE(llvm::sys::fs::createTemporaryFile("m", "log", FD, LogPath)); + { + llvm::raw_fd_ostream ClaimFD(FD, /*shouldClose=*/true); + } + + { + ModuleCacheEntries Entries; + AtomicLineLogger Logger(LogPath); + std::shared_ptr<ModuleCache> ModCache = + makeInProcessModuleCache(Entries, Logger); + + // Two workers validating the same shared module race to record its + // timestamp; only the first should record (and log) it. + ModCache->updateModuleTimestamp("A.pcm"); + ModCache->updateModuleTimestamp("A.pcm"); + } + + auto Log = llvm::MemoryBuffer::getFile(LogPath); + ASSERT_TRUE(static_cast<bool>(Log)); + EXPECT_EQ((*Log)->getBuffer().count("timestamp_write:"), 1u); + + llvm::sys::fs::remove(LogPath); +#endif +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
