Expand linux-kpi wireless and networking scaffolding

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-17 00:03:08 +01:00
parent 7126a76f54
commit e2d2fd138c
25 changed files with 1655 additions and 42 deletions
@@ -184,3 +184,135 @@ pub extern "C" fn wait_event_timeout(
) -> i32 {
wait_event_timeout_impl(wq, || condition(), timeout_ms)
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
#[derive(Copy, Clone)]
struct SendWq(*mut WaitQueueHead);
unsafe impl Send for SendWq {}
impl SendWq {
fn ptr(&self) -> *mut WaitQueueHead {
self.0
}
}
#[test]
fn init_waitqueue_head_initializes() {
let mut wq = std::mem::MaybeUninit::<WaitQueueHead>::uninit();
init_waitqueue_head(wq.as_mut_ptr());
let wq_ref = unsafe { &*wq.as_ptr() };
let guard = wq_ref.mutex.lock().unwrap();
assert!(!*guard);
}
#[test]
fn init_waitqueue_head_null_is_safe() {
init_waitqueue_head(std::ptr::null_mut());
}
#[test]
fn wake_up_null_is_safe() {
wake_up(std::ptr::null_mut());
}
#[test]
fn wait_event_unblocks_on_wake_up() {
let mut wq = std::mem::MaybeUninit::<WaitQueueHead>::uninit();
init_waitqueue_head(wq.as_mut_ptr());
let send = SendWq(wq.as_mut_ptr());
static WOKE: AtomicBool = AtomicBool::new(false);
WOKE.store(false, AtomicOrdering::Relaxed);
extern "C" fn cond_check_woke() -> bool {
WOKE.load(AtomicOrdering::Relaxed)
}
let handle = std::thread::spawn(move || {
wait_event(send.ptr(), cond_check_woke);
});
std::thread::sleep(std::time::Duration::from_millis(20));
assert!(!handle.is_finished());
WOKE.store(true, AtomicOrdering::Relaxed);
wake_up(wq.as_mut_ptr());
handle.join().expect("wait_event thread should complete");
}
#[test]
fn wait_event_returns_immediately_when_condition_true() {
let mut wq = std::mem::MaybeUninit::<WaitQueueHead>::uninit();
init_waitqueue_head(wq.as_mut_ptr());
extern "C" fn cond_true() -> bool {
true
}
let send = SendWq(wq.as_mut_ptr());
let handle = std::thread::spawn(move || {
wait_event(send.ptr(), cond_true);
});
assert!(handle.join().is_ok());
}
#[test]
fn wait_event_timeout_returns_one_when_condition_met() {
let mut wq = std::mem::MaybeUninit::<WaitQueueHead>::uninit();
init_waitqueue_head(wq.as_mut_ptr());
extern "C" fn cond_true() -> bool {
true
}
assert_eq!(wait_event_timeout(wq.as_mut_ptr(), cond_true, 100), 1);
}
#[test]
fn wait_event_timeout_returns_zero_on_timeout() {
let mut wq = std::mem::MaybeUninit::<WaitQueueHead>::uninit();
init_waitqueue_head(wq.as_mut_ptr());
extern "C" fn cond_false() -> bool {
false
}
assert_eq!(wait_event_timeout(wq.as_mut_ptr(), cond_false, 10), 0);
}
#[test]
fn wait_event_timeout_wakes_early() {
let mut wq = std::mem::MaybeUninit::<WaitQueueHead>::uninit();
init_waitqueue_head(wq.as_mut_ptr());
let send = SendWq(wq.as_mut_ptr());
static WOKE: AtomicBool = AtomicBool::new(false);
WOKE.store(false, AtomicOrdering::Relaxed);
extern "C" fn cond_check() -> bool {
WOKE.load(AtomicOrdering::Relaxed)
}
let handle = std::thread::spawn(move || wait_event_timeout(send.ptr(), cond_check, 5000));
std::thread::sleep(std::time::Duration::from_millis(20));
WOKE.store(true, AtomicOrdering::Relaxed);
wake_up(wq.as_mut_ptr());
let result = handle.join().expect("thread should complete");
assert_eq!(result, 1);
}
#[test]
fn wait_event_timeout_null_returns_zero() {
extern "C" fn cond_true() -> bool {
true
}
assert_eq!(wait_event_timeout(std::ptr::null_mut(), cond_true, 100), 0);
}
}