driver-manager: fix scheme collision and scheme availability check; redox-driver-sys: CPU affinity logging; redbear-hwutils: timer characterization
This commit is contained in:
@@ -291,12 +291,21 @@ fn read_cpu_count() -> Result<u8> {
|
||||
#[cfg(target_os = "redox")]
|
||||
fn alloc_cpu_id() -> u8 {
|
||||
match read_cpu_count() {
|
||||
Ok(n) if n > 0 => {
|
||||
Ok(0) => {
|
||||
log::warn!("redox-driver-sys: read_cpu_count returned 0, defaulting to BSP (cpu 0)");
|
||||
0
|
||||
}
|
||||
Ok(n) => {
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
static NEXT: AtomicU8 = AtomicU8::new(0);
|
||||
NEXT.fetch_add(1, Ordering::Relaxed) % n
|
||||
let cpu_id = NEXT.fetch_add(1, Ordering::Relaxed) % n;
|
||||
log::debug!("redox-driver-sys: alloc_cpu_id selected cpu {} (of {})", cpu_id, n);
|
||||
cpu_id
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("redox-driver-sys: read_cpu_count failed ({}), defaulting to BSP (cpu 0)", err);
|
||||
0
|
||||
}
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,18 @@
|
||||
path = "source"
|
||||
|
||||
[build]
|
||||
template = "cargo"
|
||||
template = "custom"
|
||||
script = """
|
||||
# driver-manager runs in both rootfs and initfs; initfs has no dynamic linker,
|
||||
# so we must build a statically linked binary.
|
||||
export RUSTFLAGS="${RUSTFLAGS} -Ctarget-feature=+crt-static -L native=${COOKBOOK_SYSROOT}/lib"
|
||||
"${COOKBOOK_CARGO}" build \
|
||||
--manifest-path "${COOKBOOK_SOURCE}/Cargo.toml" \
|
||||
--target "${TARGET}" \
|
||||
${build_flags}
|
||||
mkdir -pv "${COOKBOOK_STAGE}/usr/bin"
|
||||
cp -v "target/${TARGET}/${build_type}/driver-manager" "${COOKBOOK_STAGE}/usr/bin/driver-manager"
|
||||
"""
|
||||
|
||||
[dependencies]
|
||||
redox-driver-core = {}
|
||||
|
||||
@@ -176,10 +176,24 @@ fn open_pcid_channel(device_path: &str) -> Result<OwnedFd, ProbeResult> {
|
||||
}
|
||||
|
||||
fn check_scheme_available(name: &str) -> bool {
|
||||
if std::path::Path::new(&format!("/scheme/{}", name)).exists() {
|
||||
return true;
|
||||
let path = format!("/scheme/{}", name);
|
||||
// Use read_dir instead of Path::exists() because Redox scheme paths
|
||||
// may not respond correctly to exists()/metadata() while still being
|
||||
// fully functional for directory enumeration and file open.
|
||||
// This was the root cause of "dependency scheme not ready: pci" even
|
||||
// though PciBus::enumerate_devices (which uses read_dir) succeeded.
|
||||
match fs::read_dir(&path) {
|
||||
Ok(_) => true,
|
||||
Err(err) => {
|
||||
log::debug!(
|
||||
"driver-manager: scheme availability check failed for {}: {} (exists={})",
|
||||
path,
|
||||
err,
|
||||
std::path::Path::new(&path).exists()
|
||||
);
|
||||
false
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
impl Driver for DriverConfig {
|
||||
|
||||
@@ -52,6 +52,7 @@ impl log::Log for StderrLogger {
|
||||
fn run_enumeration(
|
||||
manager: &Arc<Mutex<DeviceManager>>,
|
||||
scheme: &DriverManagerScheme,
|
||||
initfs: bool,
|
||||
) -> (usize, usize) {
|
||||
let enum_start = Instant::now();
|
||||
let events = match manager.lock() {
|
||||
@@ -92,7 +93,11 @@ fn run_enumeration(
|
||||
log::info!("bus {} enumerated {} device(s)", bus, device_count);
|
||||
}
|
||||
ProbeEvent::BusEnumerationFailed { bus, error } => {
|
||||
log::error!("bus {} enumeration failed: {:?}", bus, error);
|
||||
if initfs && *bus == "pci" {
|
||||
log::warn!("bus {} enumeration not yet ready (initfs, pcid may still be starting): {:?}", bus, error);
|
||||
} else {
|
||||
log::error!("bus {} enumeration failed: {:?}", bus, error);
|
||||
}
|
||||
}
|
||||
ProbeEvent::AlreadyBound {
|
||||
device,
|
||||
@@ -418,7 +423,7 @@ fn main() {
|
||||
|
||||
if manager_config.async_probe {
|
||||
let handle = thread::spawn(move || {
|
||||
let (bound, deferred) = run_enumeration(&mgr_clone, scheme_clone.as_ref());
|
||||
let (bound, deferred) = run_enumeration(&mgr_clone, scheme_clone.as_ref(), initfs);
|
||||
log::info!("async enum: {} bound, {} deferred", bound, deferred);
|
||||
});
|
||||
if handle.join().is_err() {
|
||||
@@ -426,13 +431,21 @@ fn main() {
|
||||
process::exit(1);
|
||||
}
|
||||
} else {
|
||||
let (bound, deferred) = run_enumeration(&manager, scheme.as_ref());
|
||||
let (bound, deferred) = run_enumeration(&manager, scheme.as_ref(), initfs);
|
||||
log::info!("enum complete: {} bound, {} deferred", bound, deferred);
|
||||
}
|
||||
|
||||
if let Err(err) = scheme::start_scheme_server(Arc::clone(&scheme)) {
|
||||
log::error!("{err}");
|
||||
process::exit(1);
|
||||
match scheme::start_scheme_server(Arc::clone(&scheme)) {
|
||||
Ok(true) => {
|
||||
log::info!("driver-manager: scheme server started successfully");
|
||||
}
|
||||
Ok(false) => {
|
||||
log::warn!("driver-manager: scheme already registered — another instance is active, continuing without scheme server");
|
||||
}
|
||||
Err(err) => {
|
||||
log::error!("{err}");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if hotplug_mode {
|
||||
|
||||
@@ -425,13 +425,19 @@ pub fn notify_unbind(scheme: &DriverManagerScheme, pci_addr: &str) {
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
pub fn start_scheme_server(scheme: Arc<DriverManagerScheme>) -> std::result::Result<(), String> {
|
||||
pub fn start_scheme_server(scheme: Arc<DriverManagerScheme>) -> std::result::Result<bool, String> {
|
||||
let socket = Socket::create()
|
||||
.map_err(|err| format!("driver-manager: failed to create scheme socket: {err}"))?;
|
||||
let mut server = SchemeServer::new(scheme);
|
||||
|
||||
register_sync_scheme(&socket, SCHEME_NAME, &mut server)
|
||||
.map_err(|err| format!("driver-manager: failed to register scheme:{SCHEME_NAME}: {err}"))?;
|
||||
if let Err(err) = register_sync_scheme(&socket, SCHEME_NAME, &mut server) {
|
||||
let msg = format!("{err}");
|
||||
if msg.contains("File exists") {
|
||||
log::warn!("driver-manager: scheme:{SCHEME_NAME} already registered (initfs instance active), returning gracefully");
|
||||
return Ok(false);
|
||||
}
|
||||
return Err(format!("driver-manager: failed to register scheme:{SCHEME_NAME}: {err}"));
|
||||
}
|
||||
|
||||
log::info!("driver-manager: registered scheme:{SCHEME_NAME}");
|
||||
|
||||
@@ -464,10 +470,10 @@ pub fn start_scheme_server(scheme: Arc<DriverManagerScheme>) -> std::result::Res
|
||||
})
|
||||
.map_err(|err| format!("driver-manager: failed to spawn scheme server thread: {err}"))?;
|
||||
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "redox"))]
|
||||
pub fn start_scheme_server(_scheme: Arc<DriverManagerScheme>) -> std::result::Result<(), String> {
|
||||
Ok(())
|
||||
pub fn start_scheme_server(_scheme: Arc<DriverManagerScheme>) -> std::result::Result<bool, String> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
@@ -47,6 +47,16 @@ fn timespec_to_nanos(time: &TimeSpec) -> i128 {
|
||||
i128::from(time.tv_sec) * 1_000_000_000i128 + i128::from(time.tv_nsec)
|
||||
}
|
||||
|
||||
fn check_timer_source(name: &str, path: &str) -> &'static str {
|
||||
if Path::new(path).exists() {
|
||||
println!("timer_source={} path={} present=1", name, path);
|
||||
"present"
|
||||
} else {
|
||||
println!("timer_source={} path={} present=0", name, path);
|
||||
"missing"
|
||||
}
|
||||
}
|
||||
|
||||
fn run() -> Result<(), String> {
|
||||
parse_args(PROGRAM, USAGE, std::env::args()).map_err(|err| {
|
||||
if err.is_empty() {
|
||||
@@ -57,6 +67,10 @@ fn run() -> Result<(), String> {
|
||||
|
||||
println!("=== Red Bear OS Timer Runtime Check ===");
|
||||
|
||||
check_timer_source("hpet", "/scheme/sys/hpet");
|
||||
check_timer_source("pit", "/scheme/sys/pit");
|
||||
check_timer_source("lapic", "/scheme/sys/lapic");
|
||||
|
||||
let time_path = monotonic_path()?;
|
||||
|
||||
let time_fd = Fd::open(&time_path, flag::O_RDWR, 0)
|
||||
@@ -78,6 +92,17 @@ fn run() -> Result<(), String> {
|
||||
return Err("monotonic timer did not advance".to_string());
|
||||
}
|
||||
|
||||
let expected_ns: i128 = 50_000_000;
|
||||
let deviation_ns = (delta_ns - expected_ns).abs();
|
||||
println!("monotonic_expected_ns={expected_ns}");
|
||||
println!("monotonic_deviation_ns={deviation_ns}");
|
||||
|
||||
if deviation_ns > 20_000_000 {
|
||||
println!("timer_precision=coarse deviation_ns={deviation_ns} (threshold=20000000)");
|
||||
} else {
|
||||
println!("timer_precision=ok deviation_ns={deviation_ns} (threshold=20000000)");
|
||||
}
|
||||
|
||||
println!("monotonic_progress=ok");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user