fix user apc/kernel apc mixup

This commit is contained in:
disjtqz 2023-10-09 16:04:51 -04:00 committed by Radosław Gliński
parent e613134793
commit 32f7241526
3 changed files with 20 additions and 21 deletions

View File

@ -1178,12 +1178,9 @@ void KfLowerIrql_entry(dword_t new_irql, const ppc_context_t& ctx) {
} }
kpcr->current_irql = new_irql; kpcr->current_irql = new_irql;
if (new_irql < 2) { if (new_irql < 2) {
{ // this actually calls a function that eventually calls checkapcs.
// this actually calls a function that eventually calls checkapcs. // the called function does a ton of other stuff including changing the
// the called function does a ton of other stuff including changing the // irql and interrupt_related
// irql and interrupt_related
ctx.CurrentXThread()->CheckApcs();
}
} }
} }
DECLARE_XBOXKRNL_EXPORT2(KfLowerIrql, kThreading, kImplemented, kHighFrequency); DECLARE_XBOXKRNL_EXPORT2(KfLowerIrql, kThreading, kImplemented, kHighFrequency);

View File

@ -33,7 +33,6 @@ DEFINE_bool(ignore_thread_priorities, true,
DEFINE_bool(ignore_thread_affinities, true, DEFINE_bool(ignore_thread_affinities, true,
"Ignores game-specified thread affinities.", "Kernel"); "Ignores game-specified thread affinities.", "Kernel");
#if 0 #if 0
DEFINE_int64(stack_size_multiplier_hack, 1, DEFINE_int64(stack_size_multiplier_hack, 1,
"A hack for games with setjmp/longjmp issues.", "Kernel"); "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"); "A hack for games with setjmp/longjmp issues.", "Kernel");
#endif #endif
namespace xe { namespace xe {
namespace kernel { namespace kernel {
const uint32_t XAPC::kSize; const uint32_t XAPC::kSize;
const uint32_t XAPC::kDummyKernelRoutine; const uint32_t XAPC::kDummyKernelRoutine;
@ -377,22 +376,20 @@ X_STATUS XThread::Create() {
RetainHandle(); RetainHandle();
xe::threading::Thread::CreationParameters params; xe::threading::Thread::CreationParameters params;
params.create_suspended = true; params.create_suspended = true;
#if 0 #if 0
uint64_t stack_size_mult = cvars::stack_size_multiplier_hack; uint64_t stack_size_mult = cvars::stack_size_multiplier_hack;
if (main_thread_) { if (main_thread_) {
stack_size_mult = stack_size_mult =
static_cast<uint64_t>(cvars::main_xthread_stack_size_multiplier_hack); static_cast<uint64_t>(cvars::main_xthread_stack_size_multiplier_hack);
} }
#else #else
uint64_t stack_size_mult = 1; uint64_t stack_size_mult = 1;
#endif #endif
params.stack_size = 16_MiB * stack_size_mult; // Allocate a big host stack. params.stack_size = 16_MiB * stack_size_mult; // Allocate a big host stack.
thread_ = xe::threading::Thread::Create(params, [this]() { thread_ = xe::threading::Thread::Create(params, [this]() {
// Set thread ID override. This is used by logging. // 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); assert_true(XThread::GetCurrentThread() == this);
//TODO(chrispy): not sure if this order is correct, should it come after apcs? //TODO(chrispy): not sure if this order is correct, should it come after apcs?
guest_object<X_KTHREAD>()->terminated = 1; guest_object<X_KTHREAD>()->terminated = 1;
// TODO(benvanik): dispatch events? waiters? etc? // TODO(benvanik): dispatch events? waiters? etc?
RundownAPCs(); RundownAPCs();
@ -590,10 +586,8 @@ void XThread::EnterCriticalRegion() {
void XThread::LeaveCriticalRegion() { void XThread::LeaveCriticalRegion() {
auto kthread = guest_object<X_KTHREAD>(); auto kthread = guest_object<X_KTHREAD>();
// this has nothing to do with user mode apcs!
auto apc_disable_count = ++kthread->apc_disable_count; auto apc_disable_count = ++kthread->apc_disable_count;
if (apc_disable_count == 0) {
CheckApcs();
}
} }
uint32_t XThread::RaiseIrql(uint32_t new_irql) { uint32_t XThread::RaiseIrql(uint32_t new_irql) {
@ -610,7 +604,13 @@ void XThread::UnlockApc(bool queue_delivery) {
bool needs_apc = apc_list_.HasPending(); bool needs_apc = apc_list_.HasPending();
global_critical_region_.mutex().unlock(); global_critical_region_.mutex().unlock();
if (needs_apc && queue_delivery) { 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); UnlockApc(true);
} }
void XThread::SetCurrentThread() { current_xthread_tls_ = this; }
void XThread::DeliverAPCs() { 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=1
// https://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=7 // https://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=7
@ -789,7 +791,7 @@ void XThread::SetActiveCpu(uint8_t cpu_index) {
} }
} else { } else {
//there no good reason why we need to log this... we don't perfectly emulate the 360's scheduler in any way //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");
} }
} }

View File

@ -259,7 +259,7 @@ class XThread : public XObject, public cpu::Thread {
void AcquireMutantOnStartup(object_ref<XMutant> mutant) { void AcquireMutantOnStartup(object_ref<XMutant> mutant) {
pending_mutant_acquires_.push_back(mutant); pending_mutant_acquires_.push_back(mutant);
} }
void SetCurrentThread();
protected: protected:
bool AllocateStack(uint32_t size); bool AllocateStack(uint32_t size);
void FreeStack(); void FreeStack();