# Phase C+7-only diff (synthesized from working tree minus cumulative C+5/C+6/C+6½/XAM changes) # # Full uncommitted diff is in `fix.diff` (1431 lines, includes all # pre-existing Phase C work since HEAD). # # This file isolates the ~30 LOC body changes + ~160 LOC test additions # that constitute Phase C+7. --- a/crates/xenia-kernel/src/exports.rs (C+6½ baseline) +++ b/crates/xenia-kernel/src/exports.rs (C+7) # Body 1: ke_set_event — match canary's constant-1 return (xevent.cc:60-64) -fn ke_set_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 = true; - prev as u32 - } - _ => 0, - }; - state.audit_signal(h, ctx.lr as u32, "KeSetEvent", previous as u64); - wake_eligible_waiters(state, h); - ctx.gpr[3] = previous as u64; -} +fn ke_set_event(ctx: &mut PpcContext, mem: &GuestMemory, state: &mut KernelState) { + let h = ctx.gpr[3] as u32; + ensure_dispatcher_object(state, mem, h); + // Canary parity (xevent.cc:60-64): `XEvent::Set` returns constant `1` + // on success, NOT the prior signaled state as the NT contract claims. + // We compute `previous` for internal bookkeeping (audit_signal, + // wake_eligible_waiters honor the prior-state read), but report + // `1` for success / `0` for "no dispatcher found" to match the + // canary Phase A oracle. See Phase C+7 investigation.md. + let (previous, found) = match state.objects.get_mut(&h) { + Some(KernelObject::Event { signaled, .. }) => { + let prev = *signaled; + *signaled = true; + (prev as u32, true) + } + _ => (0u32, false), + }; + state.audit_signal(h, ctx.lr as u32, "KeSetEvent", previous as u64); + wake_eligible_waiters(state, h); + ctx.gpr[3] = if found { 1 } else { 0 }; +} # Body 2: nt_set_event — out-pointer writes constant 1 not prior state # (xboxkrnl_threading.cc:610-628 + xevent.cc:60-64 chain) -fn nt_set_event(ctx: &mut PpcContext, mem: &GuestMemory, state: &mut KernelState) { - let handle = ctx.gpr[3] as u32; - let prev_ptr = ctx.gpr[4] as u32; - let previous = match state.objects.get_mut(&handle) { - Some(KernelObject::Event { signaled, .. }) => { - let prev = *signaled; - *signaled = true; - prev as u32 - } - _ => 0, - }; - state.audit_signal(handle, ctx.lr as u32, "NtSetEvent", previous as u64); - wake_eligible_waiters(state, handle); - if prev_ptr != 0 { - mem.write_u32(prev_ptr, previous); - } - ctx.gpr[3] = STATUS_SUCCESS; -} +fn nt_set_event(ctx: &mut PpcContext, mem: &GuestMemory, state: &mut KernelState) { + let handle = ctx.gpr[3] as u32; + let prev_ptr = ctx.gpr[4] as u32; + // Canary parity (xboxkrnl_threading.cc:610-628): the optional out-pointer + // is filled with `was_signalled` = `ev->Set()` = constant 1 (see + // xevent.cc:60-64), NOT the prior signaled state. r3 carries + // STATUS_SUCCESS. We retain `previous` for internal audit/wake plumbing. + let (previous, found) = match state.objects.get_mut(&handle) { + Some(KernelObject::Event { signaled, .. }) => { + let prev = *signaled; + *signaled = true; + (prev as u32, true) + } + _ => (0u32, false), + }; + state.audit_signal(handle, ctx.lr as u32, "NtSetEvent", previous as u64); + wake_eligible_waiters(state, handle); + if prev_ptr != 0 && found { + mem.write_u32(prev_ptr, 1); + } + ctx.gpr[3] = STATUS_SUCCESS; +} # Test additions (in tests module): 6 new unit tests; see file lines 7179-7340 # - ke_set_event_returns_constant_one_on_unsignaled_auto_reset # - ke_set_event_returns_constant_one_on_already_signaled_manual_reset # - nt_set_event_null_prev_ptr_returns_status_success_no_write # - nt_set_event_valid_prev_ptr_writes_constant_one_and_returns_success # - nt_set_event_on_signaled_event_writes_one # - ke_set_event_post_fix_still_wakes_waiter # LOC summary (Phase C+7 only, additive on C+6½ baseline): # body changes: ~14 net added lines across 2 functions # test additions: ~160 lines (6 tests) # total: ~174 LOC, 1 file