# Phase C+8 — KeResetEvent investigation ## Framing (reading-error #28 verification — MANDATORY) Per memory note `phase_c7_keSetEvent_2026_05_14`, reading-error class #28 is **"canary source supersedes NT-doc semantics"**: the predecessor `KeSetEvent` bug was that ours returned the NT-documented "prior signaled state", while canary unconditionally `return 1` from `XEvent::Set`. Before writing any fix we **read canary's actual `XEvent::Reset` body**. ### Canary truth — `xenia-canary/src/xenia/kernel/xevent.cc` (lines 60-82) ```cpp int32_t XEvent::Set(uint32_t priority_increment, bool wait) { set_priority_increment(priority_increment); event_->Set(); return 1; } int32_t XEvent::Pulse(uint32_t priority_increment, bool wait) { set_priority_increment(priority_increment); event_->Pulse(); return 1; } int32_t XEvent::Reset() { event_->Reset(); return 1; // <-- HARDCODED CONSTANT 1, exact sibling of Set() } void XEvent::Query(uint32_t* out_type, uint32_t* out_state) { ... } void XEvent::Clear() { event_->Reset(); } // NB: used only internally ``` ### Canary truth — `xenia-canary/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc` ```cpp dword_result_t KeResetEvent_entry(pointer_t event_ptr) { auto ev = XObject::GetNativeObject(kernel_state(), event_ptr); if (!ev) { assert_always(); return 0; } return ev->Reset(); // <-- returns the 1 from XEvent::Reset } DECLARE_XBOXKRNL_EXPORT1(KeResetEvent, kThreading, kImplemented); ``` ```cpp dword_result_t NtClearEvent_entry(dword_t handle) { return xeNtClearEvent(handle); } DECLARE_XBOXKRNL_EXPORT2(NtClearEvent, kThreading, kImplemented, kHighFrequency); ``` `xeNtClearEvent` (search the file) calls `XEvent::Clear()` which is the `void`-returning variant — it does not propagate `Reset()`'s return. `xeNtClearEvent` returns `X_STATUS_SUCCESS` on hit, `X_STATUS_INVALID_HANDLE` on miss. **No out-pointer**. So `NtClearEvent` is NOT in the same class as `NtSetEvent`: it has no PreviousState argument at all. ### Ours truth pre-fix — `crates/xenia-kernel/src/exports.rs:4160-4172` ```rust fn ke_reset_event(ctx: &mut PpcContext, mem: &GuestMemory, state: &mut KernelState) { let h = ctx.gpr[3] as u32; ensure_dispatcher_object(state, mem, h); let previous = match state.objects.get_mut(&h) { Some(KernelObject::Event { signaled, .. }) => { let prev = *signaled; *signaled = false; prev as u32 } _ => 0, }; ctx.gpr[3] = previous as u64; // <-- BUG: returns prior state } ``` Mirror-image of the pre-C+7 `ke_set_event` bug. Ours returns the prior signaled state (`0` since the event had just been reset earlier in the boot); canary returns the constant `1`. `nt_clear_event` (4197-4203) already returns `STATUS_SUCCESS` — no out pointer involved. Verified canary parity for that branch. ### Phase A event at idx 102164 (raw) ```json canary: {"kind":"kernel.return","payload":{"name":"KeResetEvent", "return_value":1,"status":"0x00000001"},"tid":6, "tid_event_idx":102164} ours: {"kind":"kernel.return","payload":{"name":"KeResetEvent", "return_value":0,"status":"0x00000000"},"tid":1, "tid_event_idx":102164} ``` return_value mismatch exactly matches the canary-hardcoded-`1` premise. ## Fix shape `ke_reset_event`: set return to constant `1` on shadow hit, `0` on miss (canary's `assert_always(); return 0` path). Retain the `*signaled = false` side effect — that is real semantic state used by waiter wake plumbing, and unchanged from pre-fix behavior. Add an `audit_signal`-style record mirroring the predecessor's bookkeeping. Mirror of C+7 `ke_set_event` fix. `nt_clear_event`: already canary-parity. No change. Body LOC: ~10. Tests: ~4 new (mirrors of C+7's `ke_set_event_*` tests). ## Cascade (predictions) - A=verify canary's return: DONE, `1` confirmed. - B=land fix: ~95% (one-line return change + minor bookkeeping). - C=main chain advances past 102164: ~85% (the bug is the diff key). - D=clean re-validation: ~80%. - E=no escalation: ~95% (small).