From 32f7241526ea08b01a65290d9f84b8fc89f0241b Mon Sep 17 00:00:00 2001 From: disjtqz Date: Mon, 9 Oct 2023 16:04:51 -0400 Subject: [PATCH] fix user apc/kernel apc mixup --- .../kernel/xboxkrnl/xboxkrnl_threading.cc | 9 ++---- src/xenia/kernel/xthread.cc | 30 ++++++++++--------- src/xenia/kernel/xthread.h | 2 +- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc index df513bb6a..e826f2598 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc @@ -1178,12 +1178,9 @@ void KfLowerIrql_entry(dword_t new_irql, const ppc_context_t& ctx) { } kpcr->current_irql = new_irql; if (new_irql < 2) { - { - // this actually calls a function that eventually calls checkapcs. - // the called function does a ton of other stuff including changing the - // irql and interrupt_related - ctx.CurrentXThread()->CheckApcs(); - } + // this actually calls a function that eventually calls checkapcs. + // the called function does a ton of other stuff including changing the + // irql and interrupt_related } } DECLARE_XBOXKRNL_EXPORT2(KfLowerIrql, kThreading, kImplemented, kHighFrequency); diff --git a/src/xenia/kernel/xthread.cc b/src/xenia/kernel/xthread.cc index 0afbaa8ba..5f6c2d2a0 100644 --- a/src/xenia/kernel/xthread.cc +++ b/src/xenia/kernel/xthread.cc @@ -33,7 +33,6 @@ DEFINE_bool(ignore_thread_priorities, true, DEFINE_bool(ignore_thread_affinities, true, "Ignores game-specified thread affinities.", "Kernel"); - #if 0 DEFINE_int64(stack_size_multiplier_hack, 1, "A hack for games with setjmp/longjmp issues.", "Kernel"); @@ -41,7 +40,7 @@ DEFINE_int64(main_xthread_stack_size_multiplier_hack, 1, "A hack for games with setjmp/longjmp issues.", "Kernel"); #endif namespace xe { - namespace kernel { +namespace kernel { const uint32_t XAPC::kSize; const uint32_t XAPC::kDummyKernelRoutine; @@ -377,22 +376,20 @@ X_STATUS XThread::Create() { RetainHandle(); xe::threading::Thread::CreationParameters params; - - params.create_suspended = true; - #if 0 +#if 0 uint64_t stack_size_mult = cvars::stack_size_multiplier_hack; if (main_thread_) { stack_size_mult = static_cast(cvars::main_xthread_stack_size_multiplier_hack); - } - #else + } +#else uint64_t stack_size_mult = 1; - #endif +#endif params.stack_size = 16_MiB * stack_size_mult; // Allocate a big host stack. thread_ = xe::threading::Thread::Create(params, [this]() { // Set thread ID override. This is used by logging. @@ -454,7 +451,6 @@ X_STATUS XThread::Exit(int exit_code) { assert_true(XThread::GetCurrentThread() == this); //TODO(chrispy): not sure if this order is correct, should it come after apcs? guest_object()->terminated = 1; - // TODO(benvanik): dispatch events? waiters? etc? RundownAPCs(); @@ -590,10 +586,8 @@ void XThread::EnterCriticalRegion() { void XThread::LeaveCriticalRegion() { auto kthread = guest_object(); + // this has nothing to do with user mode apcs! auto apc_disable_count = ++kthread->apc_disable_count; - if (apc_disable_count == 0) { - CheckApcs(); - } } uint32_t XThread::RaiseIrql(uint32_t new_irql) { @@ -610,7 +604,13 @@ void XThread::UnlockApc(bool queue_delivery) { bool needs_apc = apc_list_.HasPending(); global_critical_region_.mutex().unlock(); if (needs_apc && queue_delivery) { - thread_->QueueUserCallback([this]() { DeliverAPCs(); }); + thread_->QueueUserCallback([this]() { + cpu::ThreadState::Bind(this->thread_state()); + this->SetCurrentThread(); // we store current thread in TLS, but tls + // slots are different in windows user + // callback! + DeliverAPCs(); + }); } } @@ -638,6 +638,8 @@ void XThread::EnqueueApc(uint32_t normal_routine, uint32_t normal_context, UnlockApc(true); } +void XThread::SetCurrentThread() { current_xthread_tls_ = this; } + void XThread::DeliverAPCs() { // https://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=1 // https://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=7 @@ -789,7 +791,7 @@ void XThread::SetActiveCpu(uint8_t cpu_index) { } } else { //there no good reason why we need to log this... we don't perfectly emulate the 360's scheduler in any way - // XELOGW("Too few processor cores - scheduling will be wonky"); + // XELOGW("Too few processor cores - scheduling will be wonky"); } } diff --git a/src/xenia/kernel/xthread.h b/src/xenia/kernel/xthread.h index f5bac2942..74139e679 100644 --- a/src/xenia/kernel/xthread.h +++ b/src/xenia/kernel/xthread.h @@ -259,7 +259,7 @@ class XThread : public XObject, public cpu::Thread { void AcquireMutantOnStartup(object_ref mutant) { pending_mutant_acquires_.push_back(mutant); } - + void SetCurrentThread(); protected: bool AllocateStack(uint32_t size); void FreeStack();