[llvm] [CAS] Support boot time on Windows and tolerate a moving boot time (PR #227433)

Steven Wu via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 29 11:45:56 PDT 2026


https://github.com/cachemeifyoucan created https://github.com/llvm/llvm-project/pull/227433

Compute the boot time on Windows from the current time and
GetTickCount64(), so that validate-if-needed can skip validation once
the data has been validated since boot.

A boot time computed from the current time moves when the clock is
adjusted, so a later computation during the same boot can be earlier
than the recorded one, which the exact comparison treated as a reboot.
Treat a recorded boot time that is not earlier than the current one
as the same boot instead, since a reboot always makes the boot time
later.


>From 506212f8125bf058104a57cc3433167b268b3955 Mon Sep 17 00:00:00 2001
From: Steven Wu <stevenwu at apple.com>
Date: Tue, 29 Sep 2026 11:45:39 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7
---
 llvm/lib/CAS/OnDiskCommon.cpp                 | 13 ++++
 llvm/lib/CAS/OnDiskCommon.h                   |  4 +-
 llvm/lib/CAS/UnifiedOnDiskCache.cpp           |  7 ++-
 llvm/test/tools/llvm-cas/lit.local.cfg        |  2 +-
 llvm/unittests/CAS/UnifiedOnDiskCacheTest.cpp | 59 +++++++++++++++++++
 5 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CAS/OnDiskCommon.cpp b/llvm/lib/CAS/OnDiskCommon.cpp
index 281f3ddfe85e9..50963c51505eb 100644
--- a/llvm/lib/CAS/OnDiskCommon.cpp
+++ b/llvm/lib/CAS/OnDiskCommon.cpp
@@ -12,6 +12,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
+#include <chrono>
 #include <mutex>
 #include <thread>
 
@@ -38,6 +39,10 @@
 #endif
 #endif
 
+#ifdef _WIN32
+#include "llvm/Support/Windows/WindowsSupport.h"
+#endif
+
 using namespace llvm;
 
 static uint64_t OnDiskCASMaxMappingSize = 0;
@@ -220,6 +225,14 @@ Expected<uint64_t> cas::ondisk::getBootTime() {
   if (std::error_code EC = sys::fs::status("/proc", Status))
     return createFileError("/proc", EC);
   return Status.getLastModificationTime().time_since_epoch().count();
+#elif defined(_WIN32)
+  // Compute it from the current time and the time since boot, which includes
+  // time spent asleep.
+  auto Uptime = std::chrono::milliseconds(GetTickCount64());
+  auto Boot = std::chrono::system_clock::now() - Uptime;
+  return std::chrono::duration_cast<std::chrono::seconds>(
+             Boot.time_since_epoch())
+      .count();
 #else
   return 0;
 #endif
diff --git a/llvm/lib/CAS/OnDiskCommon.h b/llvm/lib/CAS/OnDiskCommon.h
index c1d8adeac4240..22c996c8fa626 100644
--- a/llvm/lib/CAS/OnDiskCommon.h
+++ b/llvm/lib/CAS/OnDiskCommon.h
@@ -66,8 +66,8 @@ Expected<size_t> preallocateFileTail(int FD, size_t CurrentSize,
 /// Get boot time for the OS. This can be used to check if the CAS has been
 /// validated since boot.
 ///
-/// \returns the boot time in seconds (0 if operation not supported), or an \c
-/// Error.
+/// \returns the boot time in platform-specific units (0 if operation not
+/// supported), or an \c Error.
 LLVM_ABI_FOR_TEST Expected<uint64_t> getBootTime();
 
 /// Helper RAII class for copying a file to a unique file path. At destruction
diff --git a/llvm/lib/CAS/UnifiedOnDiskCache.cpp b/llvm/lib/CAS/UnifiedOnDiskCache.cpp
index 874dbe557838a..a0c7061e98e71 100644
--- a/llvm/lib/CAS/UnifiedOnDiskCache.cpp
+++ b/llvm/lib/CAS/UnifiedOnDiskCache.cpp
@@ -314,7 +314,12 @@ class LockedValidationFile {
   /// \p BootTime. Always false where the boot time is not known, i.e. 0,
   /// since it cannot be told whether that was during the current boot.
   bool isValidAtBoot(uint64_t BootTime) const {
-    return BootTime != 0 && State == BootTime;
+    // The boot time can be computed from the current time, so it moves when
+    // the clock is adjusted and the recorded one can be later than BootTime
+    // during the same boot. A reboot always makes it later. Pending is larger
+    // than any boot time, so it needs to be excluded.
+    return BootTime != 0 && !isValidationPending() && State &&
+           BootTime <= *State;
   }
 
   bool isValidationPending() const { return State == ValidationPending; }
diff --git a/llvm/test/tools/llvm-cas/lit.local.cfg b/llvm/test/tools/llvm-cas/lit.local.cfg
index 2ee6eb53c7d54..e5dc08600dca4 100644
--- a/llvm/test/tools/llvm-cas/lit.local.cfg
+++ b/llvm/test/tools/llvm-cas/lit.local.cfg
@@ -10,5 +10,5 @@ if config.llvm_cas_plugin_test_path:
 # Validation is only skipped where the boot time is known, see getBootTime().
 # This may not list all such platforms, but tests that require it only need to
 # run on some.
-if platform.system() in ("Darwin", "Linux"):
+if platform.system() in ("Darwin", "Linux", "Windows"):
     config.available_features.add("cas-boot-time")
diff --git a/llvm/unittests/CAS/UnifiedOnDiskCacheTest.cpp b/llvm/unittests/CAS/UnifiedOnDiskCacheTest.cpp
index 45582ec119f7b..c4690d8f4c856 100644
--- a/llvm/unittests/CAS/UnifiedOnDiskCacheTest.cpp
+++ b/llvm/unittests/CAS/UnifiedOnDiskCacheTest.cpp
@@ -324,6 +324,65 @@ TEST_P(CustomHasherOnDiskCASTest, UnifiedOnDiskCacheConcurrentValidation) {
   }
 }
 
+TEST_P(CustomHasherOnDiskCASTest, UnifiedOnDiskCacheBootTimeMoved) {
+  if (!isBootTimeKnown())
+    GTEST_SKIP() << "boot time is not known";
+
+  auto HashFn = GetParam().HashFn;
+  StringRef HashName = GetParam().HashName;
+  size_t HashSize = GetParam().HashSize;
+
+  unittest::TempDir Temp("ondisk-unified", /*Unique=*/true);
+  {
+    std::unique_ptr<UnifiedOnDiskCache> UniDB;
+    ASSERT_THAT_ERROR(UnifiedOnDiskCache::open(Temp.path(),
+                                               /*SizeLimit=*/std::nullopt,
+                                               HashName, HashSize)
+                          .moveInto(UniDB),
+                      Succeeded());
+  }
+  auto validate = [&]() {
+    return UnifiedOnDiskCache::validateIfNeeded(Temp.path(), HashName, HashSize,
+                                                /*CheckHash=*/true, HashFn,
+                                                /*ForceValidation=*/false);
+  };
+  std::string ValidationPath(Temp.path("v1.validation"));
+  auto readBootTime = [&]() -> uint64_t {
+    auto Buf = MemoryBuffer::getFile(ValidationPath);
+    EXPECT_TRUE(bool(Buf));
+    uint64_t Value = 0;
+    if (Buf)
+      EXPECT_FALSE((*Buf)->getBuffer().trim().getAsInteger(10, Value));
+    return Value;
+  };
+  auto writeBootTime = [&](uint64_t Value) {
+    std::error_code EC;
+    raw_fd_ostream OS(ValidationPath, EC);
+    ASSERT_FALSE(EC);
+    OS << Value << '\n';
+  };
+
+  std::optional<ValidationResult> Result;
+  ASSERT_THAT_ERROR(validate().moveInto(Result), Succeeded());
+  EXPECT_EQ(Result, ValidationResult::Valid);
+  uint64_t BootTime = readBootTime();
+  ASSERT_NE(BootTime, 0u);
+
+  // The boot time moved back since the validation, e.g. because the clock was
+  // adjusted, so the recorded one is later. It is still the same boot.
+  writeBootTime(BootTime + 1);
+  ASSERT_THAT_ERROR(validate().moveInto(Result), Succeeded());
+  EXPECT_EQ(Result, ValidationResult::Skipped);
+  EXPECT_EQ(readBootTime(), BootTime + 1);
+
+  // The recorded boot time is earlier, e.g. from an earlier boot, so validation
+  // is performed and records the current boot time.
+  writeBootTime(BootTime - 1);
+  ASSERT_THAT_ERROR(validate().moveInto(Result), Succeeded());
+  EXPECT_EQ(Result, ValidationResult::Valid);
+  EXPECT_EQ(readBootTime(), BootTime);
+}
+
 TEST_P(CustomHasherOnDiskCASTest, UnifiedOnDiskCacheRepeatedRecovery) {
   auto HashFn = GetParam().HashFn;
   StringRef HashName = GetParam().HashName;



More information about the llvm-commits mailing list