#![no_std]
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::{
clean_trace_state, end_trace, guest_trace_info, init_guest_tracing, is_trace_enabled,
set_start_tsc,
};
#[cfg(feature = "trace")]
mod trace {
extern crate alloc;
use alloc::sync::{Arc, Weak};
use spin::Mutex;
use super::*;
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) {
if tracing_core::dispatcher::has_been_set() {
return;
}
let sub = GuestSubscriber::new(guest_start_tsc);
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 set_start_tsc(guest_start_tsc: u64) {
if let Some(w) = GUEST_STATE.get()
&& let Some(state) = w.upgrade()
{
state.lock().set_start_tsc(guest_start_tsc);
}
}
pub fn end_trace() {
if let Some(w) = GUEST_STATE.get()
&& let Some(state) = w.upgrade()
{
state.lock().end_trace();
}
}
pub fn clean_trace_state() {
if let Some(w) = GUEST_STATE.get()
&& let Some(state) = w.upgrade()
{
state.lock().clean();
}
}
pub fn guest_trace_info() -> Option<TraceBatchInfo> {
let mut res = None;
if let Some(w) = GUEST_STATE.get()
&& let Some(state) = w.upgrade()
{
res = Some(state.lock().guest_trace_info());
}
res
}
pub fn is_trace_enabled() -> bool {
GUEST_STATE
.get()
.map(|w| w.upgrade().is_some())
.unwrap_or(false)
}
}