moved xsemaphore to xthread.d
add typed guest pointer template add X_KSPINLOCK, rework spinlock functions. rework irql related code, use irql on pcr instead of on XThread add guest linked list helper functions renamed ProcessInfoBlock to X_KPROCESS assigned names to many kernel structure fields
This commit is contained in:
committed by
Radosław Gliński
parent
32f7241526
commit
b5ddd30572
@@ -26,8 +26,8 @@ void KeEnableFpuExceptions_entry(
|
||||
// has to be saved to kthread, the irql changes, the machine state register is
|
||||
// changed to enable exceptions
|
||||
|
||||
X_KTHREAD* kthread = ctx->TranslateVirtual<X_KTHREAD*>(
|
||||
ctx->TranslateVirtualGPR<X_KPCR*>(ctx->r[13])->current_thread);
|
||||
X_KTHREAD* kthread = ctx->TranslateVirtual(
|
||||
ctx->TranslateVirtualGPR<X_KPCR*>(ctx->r[13])->prcb_data.current_thread);
|
||||
kthread->fpu_exceptions_on = static_cast<uint32_t>(ctx->r[3]) != 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(KeEnableFpuExceptions, kNone, kStub);
|
||||
|
||||
@@ -234,7 +234,7 @@ dword_result_t NtSuspendThread_entry(dword_t handle,
|
||||
if (thread->type() == XObject::Type::Thread) {
|
||||
auto current_pcr = context->TranslateVirtualGPR<X_KPCR*>(context->r[13]);
|
||||
|
||||
if (current_pcr->current_thread == thread->guest_object() ||
|
||||
if (current_pcr->prcb_data.current_thread == thread->guest_object() ||
|
||||
!thread->guest_object<X_KTHREAD>()->terminated) {
|
||||
result = thread->Suspend(&suspend_count);
|
||||
} else {
|
||||
@@ -1041,88 +1041,68 @@ DECLARE_XBOXKRNL_EXPORT3(NtSignalAndWaitForSingleObjectEx, kThreading,
|
||||
|
||||
static void PrefetchForCAS(const void* value) { swcache::PrefetchW(value); }
|
||||
|
||||
uint32_t xeKeKfAcquireSpinLock(uint32_t* lock, uint64_t r13 = 1) {
|
||||
// XELOGD(
|
||||
// "KfAcquireSpinLock({:08X})",
|
||||
// lock_ptr);
|
||||
uint32_t xeKeKfAcquireSpinLock(PPCContext* ctx, X_KSPINLOCK* lock,
|
||||
bool change_irql)
|
||||
{
|
||||
auto old_irql = change_irql ? xeKfRaiseIrql(ctx, 2) : 0;
|
||||
|
||||
PrefetchForCAS(lock);
|
||||
assert_true(*lock != static_cast<uint32_t>(r13));
|
||||
assert_true(lock->prcb_of_owner != static_cast<uint32_t>(ctx->r[13]));
|
||||
// Lock.
|
||||
while (!xe::atomic_cas(0, xe::byte_swap(static_cast<uint32_t>(r13)), lock)) {
|
||||
while (!xe::atomic_cas(0, xe::byte_swap(static_cast<uint32_t>(ctx->r[13])),
|
||||
&lock->prcb_of_owner.value)) {
|
||||
// Spin!
|
||||
// TODO(benvanik): error on deadlock?
|
||||
xe::threading::MaybeYield();
|
||||
}
|
||||
|
||||
// Raise IRQL to DISPATCH.
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
auto old_irql = thread->RaiseIrql(2);
|
||||
|
||||
return old_irql;
|
||||
}
|
||||
|
||||
dword_result_t KfAcquireSpinLock_entry(lpdword_t lock_ptr,
|
||||
const ppc_context_t& ppc_context) {
|
||||
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
|
||||
return xeKeKfAcquireSpinLock(lock, ppc_context->r[13]);
|
||||
dword_result_t KfAcquireSpinLock_entry(pointer_t<X_KSPINLOCK> lock_ptr,
|
||||
const ppc_context_t& context) {
|
||||
return xeKeKfAcquireSpinLock(context, lock_ptr, true);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT3(KfAcquireSpinLock, kThreading, kImplemented, kBlocking,
|
||||
kHighFrequency);
|
||||
|
||||
void xeKeKfReleaseSpinLock(uint32_t* lock, dword_t old_irql) {
|
||||
void xeKeKfReleaseSpinLock(PPCContext* ctx, X_KSPINLOCK* lock, dword_t old_irql,
|
||||
bool change_irql) {
|
||||
assert_true(lock->prcb_of_owner == static_cast<uint32_t>(ctx->r[13]));
|
||||
// Unlock.
|
||||
*lock = 0;
|
||||
if (old_irql >= 2) {
|
||||
return;
|
||||
lock->prcb_of_owner.value = 0;
|
||||
|
||||
if (change_irql) {
|
||||
// Unlock.
|
||||
if (old_irql >= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Restore IRQL.
|
||||
xeKfLowerIrql(ctx, old_irql);
|
||||
}
|
||||
// Restore IRQL.
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
thread->LowerIrql(old_irql);
|
||||
}
|
||||
|
||||
void KfReleaseSpinLock_entry(lpdword_t lock_ptr, dword_t old_irql,
|
||||
void KfReleaseSpinLock_entry(pointer_t<X_KSPINLOCK> lock_ptr, dword_t old_irql,
|
||||
const ppc_context_t& ppc_ctx) {
|
||||
assert_true(*lock_ptr == static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
|
||||
*lock_ptr = 0;
|
||||
if (old_irql >= 2) {
|
||||
return;
|
||||
}
|
||||
// Restore IRQL.
|
||||
XThread* thread = XThread::GetCurrentThread();
|
||||
thread->LowerIrql(old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_ctx, lock_ptr, old_irql, true);
|
||||
}
|
||||
|
||||
DECLARE_XBOXKRNL_EXPORT2(KfReleaseSpinLock, kThreading, kImplemented,
|
||||
kHighFrequency);
|
||||
// todo: this is not accurate
|
||||
void KeAcquireSpinLockAtRaisedIrql_entry(lpdword_t lock_ptr,
|
||||
void KeAcquireSpinLockAtRaisedIrql_entry(pointer_t<X_KSPINLOCK> lock_ptr,
|
||||
const ppc_context_t& ppc_ctx) {
|
||||
// Lock.
|
||||
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
|
||||
// must not be our own thread
|
||||
assert_true(*lock_ptr != static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
|
||||
PrefetchForCAS(lock);
|
||||
while (!xe::atomic_cas(
|
||||
0, xe::byte_swap(static_cast<uint32_t>(ppc_ctx->r[13])), lock)) {
|
||||
#if XE_ARCH_AMD64 == 1
|
||||
// todo: this is just a nop if they don't have SMT, which is not great
|
||||
// either...
|
||||
|
||||
_mm_pause();
|
||||
#endif
|
||||
// Spin!
|
||||
// TODO(benvanik): error on deadlock?
|
||||
}
|
||||
xeKeKfAcquireSpinLock(ppc_ctx, lock_ptr, false);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT3(KeAcquireSpinLockAtRaisedIrql, kThreading,
|
||||
kImplemented, kBlocking, kHighFrequency);
|
||||
|
||||
dword_result_t KeTryToAcquireSpinLockAtRaisedIrql_entry(
|
||||
lpdword_t lock_ptr, const ppc_context_t& ppc_ctx) {
|
||||
pointer_t<X_KSPINLOCK> lock_ptr, const ppc_context_t& ppc_ctx) {
|
||||
// Lock.
|
||||
auto lock = reinterpret_cast<uint32_t*>(lock_ptr.host_address());
|
||||
assert_true(*lock_ptr != static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
assert_true(lock_ptr->prcb_of_owner != static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
PrefetchForCAS(lock);
|
||||
if (!xe::atomic_cas(0, xe::byte_swap(static_cast<uint32_t>(ppc_ctx->r[13])),
|
||||
lock)) {
|
||||
@@ -1133,12 +1113,11 @@ dword_result_t KeTryToAcquireSpinLockAtRaisedIrql_entry(
|
||||
DECLARE_XBOXKRNL_EXPORT4(KeTryToAcquireSpinLockAtRaisedIrql, kThreading,
|
||||
kImplemented, kBlocking, kHighFrequency, kSketchy);
|
||||
|
||||
void KeReleaseSpinLockFromRaisedIrql_entry(lpdword_t lock_ptr,
|
||||
void KeReleaseSpinLockFromRaisedIrql_entry(pointer_t<X_KSPINLOCK> lock_ptr,
|
||||
const ppc_context_t& ppc_ctx) {
|
||||
// Unlock.
|
||||
assert_true(*lock_ptr == static_cast<uint32_t>(ppc_ctx->r[13]));
|
||||
*lock_ptr = 0;
|
||||
xeKeKfReleaseSpinLock(ppc_ctx, lock_ptr, 0, false);
|
||||
}
|
||||
|
||||
DECLARE_XBOXKRNL_EXPORT2(KeReleaseSpinLockFromRaisedIrql, kThreading,
|
||||
kImplemented, kHighFrequency);
|
||||
|
||||
@@ -1168,29 +1147,26 @@ dword_result_t KeRaiseIrqlToDpcLevel_entry(const ppc_context_t& ctx) {
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT2(KeRaiseIrqlToDpcLevel, kThreading, kImplemented,
|
||||
kHighFrequency);
|
||||
|
||||
// irql is supposed to be per thread afaik...
|
||||
void KfLowerIrql_entry(dword_t new_irql, const ppc_context_t& ctx) {
|
||||
X_KPCR* kpcr = ctx.GetPCR();
|
||||
void xeKfLowerIrql(PPCContext* ctx, unsigned char new_irql) {
|
||||
X_KPCR* kpcr = ctx->TranslateVirtualGPR<X_KPCR*>(ctx->r[13]);
|
||||
|
||||
if (new_irql > kpcr->current_irql) {
|
||||
XELOGE("KfLowerIrql : new_irql > kpcr->current_irql!");
|
||||
}
|
||||
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
|
||||
// irql and interrupt_related
|
||||
}
|
||||
}
|
||||
// irql is supposed to be per thread afaik...
|
||||
void KfLowerIrql_entry(dword_t new_irql, const ppc_context_t& ctx) {
|
||||
xeKfLowerIrql(ctx, static_cast<unsigned char>(new_irql));
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT2(KfLowerIrql, kThreading, kImplemented, kHighFrequency);
|
||||
|
||||
// used by aurora's nova plugin
|
||||
// like the other irql related functions, writes to an unknown mmio range (
|
||||
// 0x7FFF ). The range is indexed by the low 16 bits of the KPCR's pointer (so
|
||||
// r13)
|
||||
dword_result_t KfRaiseIrql_entry(dword_t new_irql, const ppc_context_t& ctx) {
|
||||
X_KPCR* v1 = ctx.GetPCR();
|
||||
unsigned char xeKfRaiseIrql(PPCContext* ctx, unsigned char new_irql) {
|
||||
X_KPCR* v1 = ctx->TranslateVirtualGPR<X_KPCR*>(ctx->r[13]);
|
||||
|
||||
uint32_t old_irql = v1->current_irql;
|
||||
v1->current_irql = new_irql;
|
||||
@@ -1200,6 +1176,13 @@ dword_result_t KfRaiseIrql_entry(dword_t new_irql, const ppc_context_t& ctx) {
|
||||
}
|
||||
return old_irql;
|
||||
}
|
||||
// used by aurora's nova plugin
|
||||
// like the other irql related functions, writes to an unknown mmio range (
|
||||
// 0x7FFF ). The range is indexed by the low 16 bits of the KPCR's pointer (so
|
||||
// r13)
|
||||
dword_result_t KfRaiseIrql_entry(dword_t new_irql, const ppc_context_t& ctx) {
|
||||
return xeKfRaiseIrql(ctx, new_irql);
|
||||
}
|
||||
|
||||
DECLARE_XBOXKRNL_EXPORT2(KfRaiseIrql, kThreading, kImplemented, kHighFrequency);
|
||||
|
||||
@@ -1222,19 +1205,29 @@ void NtQueueApcThread_entry(dword_t thread_handle, lpvoid_t apc_routine,
|
||||
thread->EnqueueApc(apc_routine, apc_routine_context, arg1, arg2);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(NtQueueApcThread, kThreading, kImplemented);
|
||||
|
||||
void xeKeInitializeApc(XAPC* apc, uint32_t thread_ptr, uint32_t kernel_routine,
|
||||
uint32_t rundown_routine, uint32_t normal_routine,
|
||||
uint32_t apc_mode, uint32_t normal_context) {
|
||||
apc->thread_ptr = thread_ptr;
|
||||
apc->kernel_routine = kernel_routine;
|
||||
apc->rundown_routine = rundown_routine;
|
||||
apc->normal_routine = normal_routine;
|
||||
apc->type = 18;
|
||||
if (normal_routine) {
|
||||
apc->apc_mode = apc_mode;
|
||||
apc->normal_context = normal_context;
|
||||
} else {
|
||||
apc->apc_mode = 0;
|
||||
apc->normal_context = 0;
|
||||
}
|
||||
apc->enqueued = 0;
|
||||
}
|
||||
void KeInitializeApc_entry(pointer_t<XAPC> apc, lpvoid_t thread_ptr,
|
||||
lpvoid_t kernel_routine, lpvoid_t rundown_routine,
|
||||
lpvoid_t normal_routine, dword_t processor_mode,
|
||||
lpvoid_t normal_context) {
|
||||
apc->Initialize();
|
||||
apc->processor_mode = processor_mode;
|
||||
apc->thread_ptr = thread_ptr.guest_address();
|
||||
apc->kernel_routine = kernel_routine.guest_address();
|
||||
apc->rundown_routine = rundown_routine.guest_address();
|
||||
apc->normal_routine = normal_routine.guest_address();
|
||||
apc->normal_context =
|
||||
normal_routine.guest_address() ? normal_context.guest_address() : 0;
|
||||
xeKeInitializeApc(apc, thread_ptr, kernel_routine, rundown_routine,
|
||||
normal_routine, processor_mode, normal_context);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(KeInitializeApc, kThreading, kImplemented);
|
||||
|
||||
@@ -1310,29 +1303,9 @@ dword_result_t KiApcNormalRoutineNop_entry(dword_t unk0 /* output? */,
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(KiApcNormalRoutineNop, kThreading, kStub);
|
||||
|
||||
typedef struct {
|
||||
xe::be<uint32_t> unknown;
|
||||
xe::be<uint32_t> flink;
|
||||
xe::be<uint32_t> blink;
|
||||
xe::be<uint32_t> routine;
|
||||
xe::be<uint32_t> context;
|
||||
xe::be<uint32_t> arg1;
|
||||
xe::be<uint32_t> arg2;
|
||||
} XDPC;
|
||||
|
||||
void KeInitializeDpc_entry(pointer_t<XDPC> dpc, lpvoid_t routine,
|
||||
lpvoid_t context) {
|
||||
// KDPC (maybe) 0x18 bytes?
|
||||
uint32_t type = 19; // DpcObject
|
||||
uint32_t importance = 0;
|
||||
uint32_t number = 0; // ?
|
||||
dpc->unknown = (type << 24) | (importance << 16) | (number);
|
||||
dpc->flink = 0;
|
||||
dpc->blink = 0;
|
||||
dpc->routine = routine.guest_address();
|
||||
dpc->context = context.guest_address();
|
||||
dpc->arg1 = 0;
|
||||
dpc->arg2 = 0;
|
||||
dpc->Initialize(routine, context);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT2(KeInitializeDpc, kThreading, kImplemented, kSketchy);
|
||||
|
||||
@@ -1385,7 +1358,7 @@ struct X_ERWLOCK {
|
||||
be<uint32_t> readers_entry_count; // 0xC
|
||||
X_KEVENT writer_event; // 0x10
|
||||
X_KSEMAPHORE reader_semaphore; // 0x20
|
||||
uint32_t spin_lock; // 0x34
|
||||
X_KSPINLOCK spin_lock; // 0x34
|
||||
};
|
||||
static_assert_size(X_ERWLOCK, 0x38);
|
||||
|
||||
@@ -1396,24 +1369,23 @@ void ExInitializeReadWriteLock_entry(pointer_t<X_ERWLOCK> lock_ptr) {
|
||||
lock_ptr->readers_entry_count = 0;
|
||||
KeInitializeEvent_entry(&lock_ptr->writer_event, 1, 0);
|
||||
KeInitializeSemaphore_entry(&lock_ptr->reader_semaphore, 0, 0x7FFFFFFF);
|
||||
lock_ptr->spin_lock = 0;
|
||||
lock_ptr->spin_lock.prcb_of_owner = 0;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExInitializeReadWriteLock, kThreading, kImplemented);
|
||||
|
||||
void ExAcquireReadWriteLockExclusive_entry(pointer_t<X_ERWLOCK> lock_ptr,
|
||||
const ppc_context_t& ppc_context) {
|
||||
auto old_irql =
|
||||
xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
auto old_irql = xeKeKfAcquireSpinLock(ppc_context, &lock_ptr->spin_lock);
|
||||
|
||||
int32_t lock_count = ++lock_ptr->lock_count;
|
||||
if (!lock_count) {
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
return;
|
||||
}
|
||||
|
||||
lock_ptr->writers_waiting_count++;
|
||||
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
xeKeWaitForSingleObject(&lock_ptr->writer_event, 7, 0, 0, nullptr);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockExclusive, kThreading,
|
||||
@@ -1422,7 +1394,7 @@ DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockExclusive, kThreading,
|
||||
dword_result_t ExTryToAcquireReadWriteLockExclusive_entry(
|
||||
pointer_t<X_ERWLOCK> lock_ptr, const ppc_context_t& ppc_context) {
|
||||
auto old_irql =
|
||||
xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
xeKeKfAcquireSpinLock(ppc_context, &lock_ptr->spin_lock);
|
||||
|
||||
uint32_t result;
|
||||
if (lock_ptr->lock_count < 0) {
|
||||
@@ -1432,7 +1404,7 @@ dword_result_t ExTryToAcquireReadWriteLockExclusive_entry(
|
||||
result = 0;
|
||||
}
|
||||
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExTryToAcquireReadWriteLockExclusive, kThreading,
|
||||
@@ -1440,20 +1412,19 @@ DECLARE_XBOXKRNL_EXPORT1(ExTryToAcquireReadWriteLockExclusive, kThreading,
|
||||
|
||||
void ExAcquireReadWriteLockShared_entry(pointer_t<X_ERWLOCK> lock_ptr,
|
||||
const ppc_context_t& ppc_context) {
|
||||
auto old_irql =
|
||||
xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
auto old_irql = xeKeKfAcquireSpinLock(ppc_context, & lock_ptr->spin_lock);
|
||||
|
||||
int32_t lock_count = ++lock_ptr->lock_count;
|
||||
if (!lock_count ||
|
||||
(lock_ptr->readers_entry_count && !lock_ptr->writers_waiting_count)) {
|
||||
lock_ptr->readers_entry_count++;
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, & lock_ptr->spin_lock, old_irql);
|
||||
return;
|
||||
}
|
||||
|
||||
lock_ptr->readers_waiting_count++;
|
||||
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
xeKeWaitForSingleObject(&lock_ptr->reader_semaphore, 7, 0, 0, nullptr);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockShared, kThreading, kImplemented,
|
||||
@@ -1461,8 +1432,7 @@ DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockShared, kThreading, kImplemented,
|
||||
|
||||
dword_result_t ExTryToAcquireReadWriteLockShared_entry(
|
||||
pointer_t<X_ERWLOCK> lock_ptr, const ppc_context_t& ppc_context) {
|
||||
auto old_irql =
|
||||
xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
auto old_irql = xeKeKfAcquireSpinLock(ppc_context, & lock_ptr->spin_lock);
|
||||
|
||||
uint32_t result;
|
||||
if (lock_ptr->lock_count < 0 ||
|
||||
@@ -1474,7 +1444,7 @@ dword_result_t ExTryToAcquireReadWriteLockShared_entry(
|
||||
result = 0;
|
||||
}
|
||||
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
return result;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExTryToAcquireReadWriteLockShared, kThreading,
|
||||
@@ -1482,14 +1452,13 @@ DECLARE_XBOXKRNL_EXPORT1(ExTryToAcquireReadWriteLockShared, kThreading,
|
||||
|
||||
void ExReleaseReadWriteLock_entry(pointer_t<X_ERWLOCK> lock_ptr,
|
||||
const ppc_context_t& ppc_context) {
|
||||
auto old_irql =
|
||||
xeKeKfAcquireSpinLock(&lock_ptr->spin_lock, ppc_context->r[13]);
|
||||
auto old_irql = xeKeKfAcquireSpinLock(ppc_context, & lock_ptr->spin_lock);
|
||||
|
||||
int32_t lock_count = --lock_ptr->lock_count;
|
||||
|
||||
if (lock_count < 0) {
|
||||
lock_ptr->readers_entry_count = 0;
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1498,7 +1467,7 @@ void ExReleaseReadWriteLock_entry(pointer_t<X_ERWLOCK> lock_ptr,
|
||||
if (readers_waiting_count) {
|
||||
lock_ptr->readers_waiting_count = 0;
|
||||
lock_ptr->readers_entry_count = readers_waiting_count;
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
xeKeReleaseSemaphore(&lock_ptr->reader_semaphore, 1,
|
||||
readers_waiting_count, 0);
|
||||
return;
|
||||
@@ -1507,12 +1476,12 @@ void ExReleaseReadWriteLock_entry(pointer_t<X_ERWLOCK> lock_ptr,
|
||||
|
||||
auto readers_entry_count = --lock_ptr->readers_entry_count;
|
||||
if (readers_entry_count) {
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
return;
|
||||
}
|
||||
|
||||
lock_ptr->writers_waiting_count--;
|
||||
xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql);
|
||||
xeKeKfReleaseSpinLock(ppc_context, &lock_ptr->spin_lock, old_irql);
|
||||
xeKeSetEvent(&lock_ptr->writer_event, 1, 0);
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExReleaseReadWriteLock, kThreading, kImplemented);
|
||||
|
||||
@@ -50,6 +50,16 @@ uint32_t ExTerminateThread(uint32_t exit_code);
|
||||
uint32_t NtResumeThread(uint32_t handle, uint32_t* suspend_count_ptr);
|
||||
|
||||
uint32_t NtClose(uint32_t handle);
|
||||
void xeKeInitializeApc(XAPC* apc, uint32_t thread_ptr, uint32_t kernel_routine,
|
||||
uint32_t rundown_routine, uint32_t normal_routine,
|
||||
uint32_t apc_mode, uint32_t normal_context);
|
||||
|
||||
void xeKfLowerIrql(PPCContext* ctx, unsigned char new_irql);
|
||||
unsigned char xeKfRaiseIrql(PPCContext* ctx, unsigned char new_irql);
|
||||
|
||||
void xeKeKfReleaseSpinLock(PPCContext* ctx, X_KSPINLOCK* lock, dword_t old_irql, bool change_irql=true);
|
||||
uint32_t xeKeKfAcquireSpinLock(PPCContext* ctx, X_KSPINLOCK* lock, bool change_irql=true);
|
||||
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
|
||||
Reference in New Issue
Block a user