blob: 4356d299ebb5eadbcb6bd8d315955b26f6e3a1a7 [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/affine/ratio.h>
#include "src/starnix/kernel/vdso/vdso_calculate_time.h"
#include "src/starnix/kernel/vdso/vdso_platform.h"
// This is in its own source file so it can be unit tested.
int64_t calculate_utc_time_nsec() {
int64_t reference_boot_instant = calculate_boot_time_nsec();
// Boot time to utc transform is read from vvar_data. The data is protected by a seqlock, and so
// a seqlock reader is implemented
// Check that the state of the seqlock shows that the transform is not being updated
uint64_t seq_num1 = vvar.seq_num.load(std::memory_order_acquire);
if (seq_num1 & 1) {
// Cannot read, because a write is in progress
return kUtcInvalid;
}
int64_t boot_to_utc_reference_offset =
vvar.boot_to_utc_reference_offset.load(std::memory_order_acquire);
int64_t boot_to_utc_synthetic_offset =
vvar.boot_to_utc_synthetic_offset.load(std::memory_order_acquire);
uint32_t boot_to_utc_reference_ticks =
vvar.boot_to_utc_reference_ticks.load(std::memory_order_acquire);
uint32_t boot_to_utc_synthetic_ticks =
vvar.boot_to_utc_synthetic_ticks.load(std::memory_order_acquire);
// Check that the state of the seqlock has not changed while reading the transform
uint64_t seq_num2 = vvar.seq_num.load(std::memory_order_acquire);
if (seq_num1 != seq_num2) {
// Data has been updated during the reading of it, so is invalid
return kUtcInvalid;
}
affine::Ratio boot_to_utc_ratio(boot_to_utc_synthetic_ticks, boot_to_utc_reference_ticks);
return boot_to_utc_ratio.Scale(reference_boot_instant - boot_to_utc_reference_offset) +
boot_to_utc_synthetic_offset;
}