#![no_std]
#[cfg(target_arch = "x86_64")]
pub mod invariant_tsc;
#[cfg(feature = "trace")]
mod state;
#[cfg(feature = "trace")]
mod subscriber;
#[cfg(feature = "trace")]
mod visitor;
#[cfg(feature = "trace")]
pub use state::TraceBatchInfo;
#[cfg(feature = "trace")]
pub use trace::{
end_trace, flush, init_guest_tracing, is_trace_enabled, new_call, reset, serialized_data,
};
#[cfg(feature = "trace")]
mod trace {
extern crate alloc;
use alloc::sync::{Arc, Weak};
use spin::Mutex;
use tracing_core::LevelFilter;
use crate::state::GuestState;
use crate::subscriber::GuestSubscriber;
static GUEST_STATE: spin::Once<Weak<Mutex<GuestState>>> = spin::Once::new();
pub fn init_guest_tracing(guest_start_tsc: u64, max_log_level: LevelFilter) {
if tracing_core::dispatcher::has_been_set() {
return;
}
let sub = GuestSubscriber::new(guest_start_tsc, max_log_level);
let state = sub.state();
GUEST_STATE.call_once(|| Arc::downgrade(state));
let _ = tracing_core::dispatcher::set_global_default(tracing_core::Dispatch::new(sub));
}
pub fn end_trace() {
if let Some(w) = GUEST_STATE.get()
&& let Some(state_mutex) = w.upgrade()
{
let mut state = state_mutex
.try_lock()
.expect("guest_tracing: Unable to lock guest tracing state in `end_trace`");
state.end_trace();
}
}
pub fn flush() {
if let Some(w) = GUEST_STATE.get()
&& let Some(state_mutex) = w.upgrade()
{
let mut state = state_mutex
.try_lock()
.expect("Unable to lock GuestState in `flush`");
state.flush();
}
}
pub fn new_call(guest_start_tsc: u64) {
if let Some(w) = GUEST_STATE.get()
&& let Some(state_mutex) = w.upgrade()
{
let mut state = state_mutex
.try_lock()
.expect("Unable to lock GuestState in `new_call`");
state.new_call(guest_start_tsc);
}
}
pub fn reset() {
if let Some(w) = GUEST_STATE.get()
&& let Some(state_mutex) = w.upgrade()
{
let mut state = state_mutex
.try_lock()
.expect("Unable to lock GuestState in `reset`");
state.reset();
}
}
pub fn serialized_data() -> Option<(u64, u64)> {
if let Some(w) = GUEST_STATE.get()
&& let Some(state_mutex) = w.upgrade()
{
let state = state_mutex
.try_lock()
.expect("Unable to lock GuestState in `serialized_data`");
state.serialized_data()
} else {
None
}
}
pub fn is_trace_enabled() -> bool {
GUEST_STATE
.get()
.map(|w| w.upgrade().is_some())
.unwrap_or(false)
}
}