[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