120 lines
3.5 KiB
Rust

// GStreamer
//
// Copyright (C) 2015-2023 Sebastian Dröge <sebastian@centricular.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
// If a copy of the MPL was not distributed with this file, You can obtain one at
// <https://mozilla.org/MPL/2.0/>.
//
// SPDX-License-Identifier: MPL-2.0
#[cfg(target_os = "macos")]
/// Returns the monotonic system clock in nanoseconds or 0 on error.
pub fn time() -> u64 {
use std::{
mem,
sync::atomic::{self, AtomicU32},
};
use crate::ffi::unix::macos::*;
static TIMEBASE_N: AtomicU32 = AtomicU32::new(0);
static TIMEBASE_D: AtomicU32 = AtomicU32::new(0);
let mut timebase_n = TIMEBASE_N.load(atomic::Ordering::Relaxed);
let mut timebase_d = TIMEBASE_D.load(atomic::Ordering::Relaxed);
if timebase_n == 0 || timebase_d == 0 {
// SAFETY: This is safe to call at any time and returns the timebase. Returns 0 on success.
unsafe {
let mut timebase = mem::MaybeUninit::uninit();
if mach_timebase_info(timebase.as_mut_ptr()) != 0 {
return 0;
}
let timebase = timebase.assume_init();
timebase_n = timebase.numer;
timebase_d = timebase.denom;
TIMEBASE_N.store(timebase_n, atomic::Ordering::Relaxed);
TIMEBASE_D.store(timebase_d, atomic::Ordering::Relaxed);
}
}
// SAFETY: This is safe to call at any time.
let time = unsafe { mach_absolute_time() };
(time as u128 * timebase_n as u128 / timebase_d as u128) as u64
}
#[cfg(target_os = "windows")]
/// Returns the monotonic system clock in nanoseconds or 0 on error.
pub fn time() -> u64 {
use std::{
mem,
sync::atomic::{self, AtomicI64},
};
use crate::ffi::windows::*;
static FREQUENCY: AtomicI64 = AtomicI64::new(0);
let mut freq = FREQUENCY.load(atomic::Ordering::Relaxed);
if freq == 0 {
// SAFETY: This is safe to call at any time and will never fail on Windows XP or newer.
unsafe {
QueryPerformanceFrequency(&mut freq);
}
FREQUENCY.store(freq, atomic::Ordering::Relaxed);
}
// SAFETY: This is safe to call at any time and will never fail on Windows XP or newer.
let time = unsafe {
let mut time = mem::MaybeUninit::uninit();
QueryPerformanceCounter(time.as_mut_ptr());
time.assume_init()
};
(time as u128 * 1_000_000_000 / freq as u128) as u64
}
#[cfg(any(
target_os = "linux",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly",
target_os = "solaris",
target_os = "illumos",
target_os = "hurd",
))]
/// Returns the monotonic system clock in nanoseconds or 0 on error.
pub fn time() -> u64 {
use std::mem;
use crate::ffi::unix::clock_gettime::*;
// SAFETY: This is safe to call at any time. 0 will be returned on success, any other value on
// error.
unsafe {
let mut timespec = mem::MaybeUninit::uninit();
let res = clock_gettime(CLOCK_MONOTONIC, timespec.as_mut_ptr());
if res == 0 {
let timespec = timespec.assume_init();
timespec.tv_sec as u64 * 1_000_000_000 + timespec.tv_nsec as u64
} else {
0
}
}
}
#[cfg(test)]
mod test {
#[test]
fn test_clock() {
// Check that this doesn't return 0 as that's very likely an indication of things going
// wrong.
let now = super::time();
assert_ne!(now, 0);
}
}