use crate::core::detector;
#[cfg(feature = "logging-and-visualization")]
use crate::core::logger;
use crate::ffi::{DEADLOCK_CALLBACK, DEADLOCK_DETECTED, INITIALIZED, IS_LOGGING_ENABLED};
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int};
use std::sync::atomic::Ordering;
#[cfg(feature = "stress-test")]
use crate::StressMode;
#[cfg(feature = "stress-test")]
use crate::ffi::{STRESS_CONFIG, STRESS_MODE};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn deloxide_init(
log_path: *const c_char,
callback: Option<extern "C" fn(*const c_char)>,
) -> c_int {
unsafe {
if INITIALIZED.load(Ordering::SeqCst) {
return 1; }
let log_path_option = if !log_path.is_null() {
match CStr::from_ptr(log_path).to_str() {
Ok(s) => Some(s),
Err(_) => return -1, }
} else {
None };
DEADLOCK_CALLBACK = callback;
#[cfg(feature = "logging-and-visualization")]
let logger = if let Some(log_path) = log_path_option {
match logger::EventLogger::with_file(log_path) {
Ok(logger) => {
IS_LOGGING_ENABLED.store(true, Ordering::SeqCst);
Some(logger)
}
Err(_) => return -2, }
} else {
IS_LOGGING_ENABLED.store(false, Ordering::SeqCst);
None
};
#[cfg(not(feature = "logging-and-visualization"))]
{
if log_path_option.is_some() {
return -3; }
IS_LOGGING_ENABLED.store(false, Ordering::SeqCst);
}
let deadlock_callback = move |deadlock_info| {
#[allow(static_mut_refs)]
DEADLOCK_DETECTED.store(true, Ordering::SeqCst);
if let Some(cb) = DEADLOCK_CALLBACK {
if let Ok(json) = serde_json::to_string(&deadlock_info) {
if let Ok(c_str) = CString::new(json) {
cb(c_str.as_ptr());
}
}
}
};
let config = detector::DetectorConfig {
callback: Box::new(deadlock_callback),
#[cfg(feature = "lock-order-graph")]
check_lock_order: false, #[cfg(feature = "stress-test")]
stress_mode: {
#[cfg(feature = "stress-test")]
{
match STRESS_MODE.load(Ordering::SeqCst) {
1 => StressMode::RandomPreemption,
2 => StressMode::ComponentBased,
_ => StressMode::None,
}
}
#[cfg(not(feature = "stress-test"))]
{
unreachable!()
}
},
#[cfg(feature = "stress-test")]
stress_config: {
#[cfg(feature = "stress-test")]
{
#[allow(static_mut_refs)]
STRESS_CONFIG.take()
}
#[cfg(not(feature = "stress-test"))]
{
None
}
},
#[cfg(feature = "logging-and-visualization")]
logger,
};
detector::init_detector(config);
INITIALIZED.store(true, Ordering::SeqCst);
0 }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn deloxide_is_deadlock_detected() -> c_int {
unsafe {
#[allow(static_mut_refs)]
if DEADLOCK_DETECTED.load(Ordering::SeqCst) {
1
} else {
0
}
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn deloxide_reset_deadlock_flag() {
unsafe {
#[allow(static_mut_refs)]
DEADLOCK_DETECTED.store(false, Ordering::SeqCst);
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn deloxide_is_logging_enabled() -> c_int {
if IS_LOGGING_ENABLED.load(Ordering::SeqCst) {
1
} else {
0
}
}