//! Kernel object tracking for HLE. use std::sync::Arc; use xenia_cpu::ThreadRef; /// Kernel object types tracked by handle. /// /// Sync variants (`Event`, `Semaphore`, `Mutex`, `Thread`) carry an in-place /// waiter list so wait/set/release sites keep invariants local — dropping the /// object implicitly drops its waiters. Waiters are stored as `ThreadRef` /// (post-Axis-1) — a bare `hw_id: u8` would have been ambiguous under per-slot /// runqueues where multiple guest threads share one HW slot. #[derive(Debug)] pub enum KernelObject { Event { manual_reset: bool, signaled: bool, /// Guest threads parked on this event. waiters: Vec, }, Semaphore { count: i32, max: i32, waiters: Vec, }, File { /// Normalized VFS path (e.g. "default.xex", "media/shared/foo.pkg"). path: String, /// Full file size in bytes. size: u64, /// Current read/write cursor. position: u64, /// Whole-file buffer — VFS reads the entire file up front so /// subsequent NtReadFile calls are O(1) slice copies. /// `Arc>` so duplicate handles could share backing storage. data: Arc>, /// Directory-enumeration cursor consumed by `NtQueryDirectoryFile`. /// `None` before the first call; `Some(N)` = next VFS entry index /// to emit. Reset to `Some(0)` when the guest passes /// `restart_scan=1`. Unused on non-directory files. dir_enum_pos: Option, }, Thread { id: u32, /// HW thread slot currently running this guest thread (None once exited /// — `exit_code` becomes Some). hw_id: Option, /// None while the thread is running; populated on ExTerminateThread /// or halt-sentinel return. exit_code: Option, /// Guest threads parked in KeWaitForSingleObject on this thread handle. waiters: Vec, }, Timer { /// Xbox 360 timer_type 0 = NotificationTimer (manual-reset), /// 1 = SynchronizationTimer (auto-reset). Same shape as Event. manual_reset: bool, signaled: bool, /// Absolute tick-space deadline; None when disarmed. deadline: Option, /// Period in ticks (same units as `deadline`); 0 = one-shot. period_ticks: u64, /// Original ms value (canary's SetTimer keeps it for diagnostics). period_ms: u32, /// APC routine (deferred — see `timer_apc` warn in nt_set_timer_ex). callback_routine: u32, callback_arg: u32, waiters: Vec, }, Mutex { /// HW thread id currently holding the mutex; None when free. owner: Option, recursion: u32, waiters: Vec, }, } impl KernelObject { /// Returns the per-object waiter list for the 5 sync variants (Event, /// Semaphore, Thread, Timer, Mutex) and `None` for `File`. Used by /// deadline-expiry scrub in `KernelState::handle_timeout_wake` so a /// timed-out waiter isn't left stranded in a handle's waiters list. pub fn waiters_mut(&mut self) -> Option<&mut Vec> { match self { KernelObject::Event { waiters, .. } | KernelObject::Semaphore { waiters, .. } | KernelObject::Thread { waiters, .. } | KernelObject::Timer { waiters, .. } | KernelObject::Mutex { waiters, .. } => Some(waiters), KernelObject::File { .. } => None, } } }