snapshot: preserve the uncommitted Canary instrumentation (not authored here)
Some checks failed
Orchestrator / Commit Message Validation (push) Has been skipped
Orchestrator / Lint (push) Failing after 2m0s
Orchestrator / Windows (x86-64) (push) Has been skipped
Orchestrator / Linux (x86-64) (push) Has been skipped
Orchestrator / Create Release (push) Has been skipped

Working-tree snapshot taken 2026-07-28 so this work is not lost. To be clear
about provenance: NONE of this was written in the session that committed it —
it is pre-existing uncommitted work on phase-a-tracing, last committed 2026-07-09,
from the xenia-rs decoder/deadlock investigation. It is recorded verbatim, not
reviewed and not tested.

Contents: 24 tracked modifications (ppc_emit_memory, xex_module, object_table,
shim_utils, xboxkrnl threading/rtl, xevent/xobject/xthread, memory) plus the
untracked probe sources audit_68_host_mem_watch, audit_69_event_signal_watch,
audit_70_semaphore_release_watch, phase_b_snapshot, and cmake/toolchains.

Deliberately excluded: build-cross/ (51 GB of build output) and
vkd3d-proton.cache. Note third_party/snappy is a submodule pointer change whose
target may not be pushed anywhere, so this branch is a preservation record rather
than a guaranteed-buildable tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-28 20:03:33 +00:00
parent a154309022
commit 30d05ee97b
34 changed files with 2981 additions and 32 deletions

View File

@@ -21,7 +21,9 @@
#include "xenia/base/threading.h"
#include "xenia/cpu/processor.h"
#include "xenia/emulator.h"
#include "xenia/kernel/event_log.h"
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/phase_b_snapshot.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
@@ -116,6 +118,11 @@ XThread* XThread::GetCurrentThread() {
return thread;
}
// Phase C+15-α: non-asserting variant. See xthread.h.
XThread* XThread::TryGetCurrentThread() {
return reinterpret_cast<XThread*>(current_xthread_tls_);
}
uint32_t XThread::GetCurrentThreadHandle() {
XThread* thread = XThread::GetCurrentThread();
return thread->handle();
@@ -470,6 +477,14 @@ X_STATUS XThread::Create() {
X_STATUS XThread::Exit(int exit_code) {
// This may only be called on the thread itself.
assert_true(XThread::GetCurrentThread() == this);
// Phase C+15-α: schema-v1 `thread.exit` event. Emit BEFORE Exit()
// unwinds via threading::Thread::Exit (does not return). This
// covers both `ExTerminateThread` and implicit thread-entry returns
// — XThread::Execute calls Exit() at line ~641 after entry_pc
// returns. Symmetric with ours's `ex_terminate_thread`.
if (phase_a::IsEnabled()) {
phase_a::EmitThreadExit(static_cast<uint32_t>(exit_code));
}
// TODO(chrispy): not sure if this order is correct, should it come after
// apcs?
auto kthread = guest_object<X_KTHREAD>();
@@ -575,6 +590,11 @@ void XThread::Execute() {
// On Windows, setjmp/longjmp is used because MSVC's longjmp performs SEH
// stack unwinding which already calls destructors.
uint32_t next_address;
// Phase B snapshot. No-op when phase_b_snapshot_dir cvar is empty
// (default). When set, fires once on the entry-point thread immediately
// before its first guest instruction executes. See
// xenia/kernel/phase_b_snapshot.h.
::xe::kernel::phase_b::FireIfEntryThread(this, thread_state_, address);
#if !XE_PLATFORM_WIN32
try {
exit_code = static_cast<int>(kernel_state()->processor()->Execute(