blob: 7c62e92c7a5a87c4053c621777f3881dedb9d0f6 [file] [log] [blame] [edit]
// 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 "vdso-calculate-time.h"
#include "vdso-platform.h"
// This is in its own source file so it can be unit tested.
int64_t calculate_utc_time_nsec() {
int64_t monotonic_time = calculate_monotonic_time_nsec();
// Mono 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 mono_to_utc_reference_offset =
vvar.mono_to_utc_reference_offset.load(std::memory_order_acquire);
int64_t mono_to_utc_synthetic_offset =
vvar.mono_to_utc_synthetic_offset.load(std::memory_order_acquire);
uint32_t mono_to_utc_reference_ticks =
vvar.mono_to_utc_reference_ticks.load(std::memory_order_acquire);
uint32_t mono_to_utc_synthetic_ticks =
vvar.mono_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 mono_to_utc_ratio(mono_to_utc_synthetic_ticks, mono_to_utc_reference_ticks);
return mono_to_utc_ratio.Scale(monotonic_time - mono_to_utc_reference_offset) +
mono_to_utc_synthetic_offset;
}