blob: 5edb4a6a616b137199684b38fce40ee99490d369 [file]
// Copyright 2016 The Fuchsia Authors
// Copyright (c) 2012 Travis Geiselbrecht
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
//! Monotonic clock and cycle counter diagnostic console command.
use core::ffi::c_int;
use kprint::kprintln;
use crate::console::CmdArgs;
use crate::kernel::mp::{SMP_MAX_CPUS, cpu_num_to_mask, is_cpu_online};
use crate::kernel::thread::{ThreadPtr, sleep_relative};
use crate::kernel::types::cpu_num_t;
use crate::platform_rs::timer::{DurationMono, current_mono_time};
/// # Safety
///
/// `_argv` is not dereferenced; `unsafe` only to match the console command callback signature.
pub(super) unsafe extern "C" fn clock_tests(
_argc: c_int,
_argv: *const CmdArgs,
_flags: u32,
) -> c_int {
let _ = sleep_relative(DurationMono::from_millis(100));
let mut c = libarch::cycles();
let _ = current_mono_time();
c = libarch::cycles().wrapping_sub(c);
kprintln!("{} cycles per current_mono_time()", c);
kprintln!("making sure time never goes backwards");
{
kprintln!("testing current_mono_time()");
let start = current_mono_time();
let mut last = start;
loop {
let t2 = current_mono_time();
// printf("%llu %llu\n", last, t2);
if t2 < last {
kprintln!(
"WARNING: time ran backwards: {} < {}",
t2.into_nanos(),
last.into_nanos()
);
last = t2;
continue;
}
last = t2;
if last - start > DurationMono::from_seconds(5) {
break;
}
}
}
kprintln!("counting to 5, in one second intervals");
for i in 0..5 {
let _ = sleep_relative(DurationMono::from_seconds(1));
kprintln!("{}", i + 1);
}
// SAFETY: Called from normal thread context after threading initialization.
let old_affinity = unsafe { ThreadPtr::current().get_cpu_affinity() };
for cpu in 0..(SMP_MAX_CPUS as cpu_num_t) {
if !is_cpu_online(cpu) {
continue;
}
kprintln!("measuring cpu clock against current_mono_time() on cpu {}", cpu);
// SAFETY: Called from normal thread context after threading initialization.
unsafe {
ThreadPtr::current().set_cpu_affinity(cpu_num_to_mask(cpu));
}
for _ in 0..3 {
let mut cycles = libarch::cycles();
let start = current_mono_time();
while (current_mono_time() - start) < DurationMono::from_seconds(1) {}
cycles = libarch::cycles().wrapping_sub(cycles);
kprintln!("cpu {}: {} cycles per second", cpu, cycles);
}
}
// SAFETY: Called from normal thread context after threading initialization.
unsafe {
ThreadPtr::current().set_cpu_affinity(old_affinity);
}
0
}