ax-task 0.6.10

ArceOS task management module
Documentation
use super::*;

#[test]
fn held_lock_display_includes_class_addr_and_location() {
    let held = HeldLock {
        class_id: 3,
        kind: HeldLockKind::Spin,
        mode: HeldLockMode::Exclusive,
        sleep_forbidden: true,
        addr: 0x1234,
        caller: Location::caller(),
    };
    let rendered = held.to_string();
    assert!(rendered.contains("kind=spin"));
    assert!(rendered.contains("mode=exclusive"));
    assert!(rendered.contains("sleep_forbidden=true"));
    assert!(rendered.contains("class=3"));
    assert!(rendered.contains("addr=0x1234"));
    assert!(rendered.contains("acquired_at="));
}

#[cfg(target_pointer_width = "64")]
#[test]
fn subclass_support_does_not_increase_held_lock_state_size() {
    assert_eq!(core::mem::size_of::<HeldLock>(), 24);
    assert_eq!(core::mem::size_of::<HeldLockStack>(), 776);
    assert_eq!(core::mem::size_of::<HeldLockSnapshot>(), 776);
    assert_eq!(core::mem::size_of::<PreparedAcquire>(), 800);
}

#[test]
fn held_stack_display_marks_top_entry() {
    let caller = Location::caller();
    let mut snapshot = HeldLockSnapshot::new();
    snapshot.push(HeldLock {
        class_id: 2,
        kind: HeldLockKind::Spin,
        mode: HeldLockMode::Exclusive,
        sleep_forbidden: true,
        addr: 0x10,
        caller,
    });
    snapshot.push(HeldLock {
        class_id: 3,
        kind: HeldLockKind::Mutex,
        mode: HeldLockMode::Exclusive,
        sleep_forbidden: false,
        addr: 0x20,
        caller,
    });

    let rendered = HeldLockStackDisplay {
        snapshot: &snapshot,
        subclasses: &HeldLockSubclassSnapshot {
            values: [DEFAULT_LOCK_SUBCLASS; MAX_HELD_LOCK_SNAPSHOT],
        },
    }
    .to_string();
    assert!(rendered.contains("[0] held: kind=spin mode=exclusive sleep_forbidden=true class=2"));
    assert!(rendered.contains("[1] top: kind=mutex mode=exclusive sleep_forbidden=false class=3"));
}

#[test]
fn dynamic_lock_instances_do_not_consume_class_slots() {
    let locks: Vec<_> = (0..(MAX_LOCK_CLASSES + 128))
        .map(|_| LockdepMap::new_dynamic())
        .collect();

    for lock in &locks {
        let prepared = prepare_acquire_with_snapshot_checked(
            lock,
            "test lock",
            lock as *const _ as usize,
            Location::caller(),
            HeldLockSnapshot::new(),
        )
        .unwrap();
        assert_ne!(prepared.class_id(), 0);
    }
}

#[test]
fn subclass_tracks_same_base_class_nesting() {
    fn prepare_with_subclass(
        map: &LockdepMap,
        held_before: HeldLockSnapshot,
        subclass: LockSubclass,
    ) -> PreparedAcquire {
        prepare_acquire_with_snapshot_checked_nested(
            map,
            "test lock",
            map as *const _ as usize,
            Location::caller(),
            held_before,
            subclass,
        )
        .unwrap()
    }

    let parent = LockdepMap::new_dynamic();
    let child = LockdepMap::new_dynamic();
    let parent_acquire =
        prepare_with_subclass(&parent, HeldLockSnapshot::new(), DEFAULT_LOCK_SUBCLASS);
    let parent_class = parent_acquire.class_id();
    let mut parent_held = HeldLockSnapshot::new();
    parent_held.push(HeldLock {
        class_id: parent_class,
        kind: HeldLockKind::Spin,
        mode: HeldLockMode::Exclusive,
        sleep_forbidden: true,
        addr: &parent as *const _ as usize,
        caller: Location::caller(),
    });
    let child_acquire = prepare_with_subclass(&child, parent_held, 1);
    assert_eq!(class_subclass(parent_class), DEFAULT_LOCK_SUBCLASS);
    assert_eq!(class_subclass(child_acquire.class_id()), 1);

    let mut held_locks = HeldLockStack::new();
    finish_acquire_with_stack(
        parent_acquire,
        &parent as *const _ as usize,
        &mut held_locks,
    );
    finish_acquire_with_stack(child_acquire, &child as *const _ as usize, &mut held_locks);
    release_from_stack(&child as *const _ as usize, &mut held_locks);
    release_from_stack(&parent as *const _ as usize, &mut held_locks);

    let mut nested_held = HeldLockSnapshot::new();
    nested_held.push(HeldLock {
        class_id: child_acquire.class_id(),
        kind: HeldLockKind::Spin,
        mode: HeldLockMode::Exclusive,
        sleep_forbidden: true,
        addr: &child as *const _ as usize,
        caller: Location::caller(),
    });
    let reverse = prepare_acquire_with_snapshot_checked_nested(
        &parent,
        "test lock",
        &parent as *const _ as usize,
        Location::caller(),
        nested_held,
        DEFAULT_LOCK_SUBCLASS,
    );
    assert!(matches!(reverse, Err(LockdepCheckError::OrderInversion)));
}