Tweaking CriticalSection.
This commit is contained in:
parent
76e360ba8b
commit
bba8f6391b
|
@ -414,10 +414,11 @@ SHIM_CALL RtlImageXexHeaderField_shim(PPCContext* ppc_state,
|
||||||
struct X_RTL_CRITICAL_SECTION {
|
struct X_RTL_CRITICAL_SECTION {
|
||||||
uint8_t unknown00;
|
uint8_t unknown00;
|
||||||
uint8_t spin_count_div_256; // * 256
|
uint8_t spin_count_div_256; // * 256
|
||||||
uint8_t __padding[6];
|
uint16_t __padding0;
|
||||||
|
uint32_t __padding1;
|
||||||
// uint32_t unknown04; // maybe the handle to the event?
|
// uint32_t unknown04; // maybe the handle to the event?
|
||||||
uint32_t unknown08; // head of queue, pointing to this offset
|
uint32_t queue_head; // head of queue, pointing to this offset
|
||||||
uint32_t unknown0C; // tail of queue?
|
uint32_t queue_tail; // tail of queue?
|
||||||
int32_t lock_count; // -1 -> 0 on first lock 0x10
|
int32_t lock_count; // -1 -> 0 on first lock 0x10
|
||||||
uint32_t recursion_count; // 0 -> 1 on first lock 0x14
|
uint32_t recursion_count; // 0 -> 1 on first lock 0x14
|
||||||
uint32_t owning_thread_id; // 0 unless locked 0x18
|
uint32_t owning_thread_id; // 0 unless locked 0x18
|
||||||
|
@ -425,12 +426,15 @@ struct X_RTL_CRITICAL_SECTION {
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
static_assert_size(X_RTL_CRITICAL_SECTION, 28);
|
static_assert_size(X_RTL_CRITICAL_SECTION, 28);
|
||||||
|
|
||||||
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs) {
|
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
||||||
|
uint32_t cs_ptr) {
|
||||||
// VOID
|
// VOID
|
||||||
// _Out_ LPCRITICAL_SECTION lpCriticalSection
|
// _Out_ LPCRITICAL_SECTION lpCriticalSection
|
||||||
|
|
||||||
cs->unknown00 = 1;
|
cs->unknown00 = 1;
|
||||||
cs->spin_count_div_256 = 0;
|
cs->spin_count_div_256 = 0;
|
||||||
|
cs->queue_head = cs_ptr + 8;
|
||||||
|
cs->queue_tail = cs_ptr + 8;
|
||||||
cs->lock_count = -1;
|
cs->lock_count = -1;
|
||||||
cs->recursion_count = 0;
|
cs->recursion_count = 0;
|
||||||
cs->owning_thread_id = 0;
|
cs->owning_thread_id = 0;
|
||||||
|
@ -443,10 +447,11 @@ SHIM_CALL RtlInitializeCriticalSection_shim(PPCContext* ppc_state,
|
||||||
XELOGD("RtlInitializeCriticalSection(%.8X)", cs_ptr);
|
XELOGD("RtlInitializeCriticalSection(%.8X)", cs_ptr);
|
||||||
|
|
||||||
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
||||||
xeRtlInitializeCriticalSection(cs);
|
xeRtlInitializeCriticalSection(cs, cs_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
||||||
|
uint32_t cs_ptr,
|
||||||
uint32_t spin_count) {
|
uint32_t spin_count) {
|
||||||
// NTSTATUS
|
// NTSTATUS
|
||||||
// _Out_ LPCRITICAL_SECTION lpCriticalSection,
|
// _Out_ LPCRITICAL_SECTION lpCriticalSection,
|
||||||
|
@ -461,6 +466,8 @@ X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
||||||
|
|
||||||
cs->unknown00 = 1;
|
cs->unknown00 = 1;
|
||||||
cs->spin_count_div_256 = spin_count_div_256;
|
cs->spin_count_div_256 = spin_count_div_256;
|
||||||
|
cs->queue_head = cs_ptr + 8;
|
||||||
|
cs->queue_tail = cs_ptr + 8;
|
||||||
cs->lock_count = -1;
|
cs->lock_count = -1;
|
||||||
cs->recursion_count = 0;
|
cs->recursion_count = 0;
|
||||||
cs->owning_thread_id = 0;
|
cs->owning_thread_id = 0;
|
||||||
|
@ -477,14 +484,23 @@ SHIM_CALL RtlInitializeCriticalSectionAndSpinCount_shim(PPCContext* ppc_state,
|
||||||
spin_count);
|
spin_count);
|
||||||
|
|
||||||
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
||||||
X_STATUS result = xeRtlInitializeCriticalSectionAndSpinCount(cs, spin_count);
|
X_STATUS result =
|
||||||
|
xeRtlInitializeCriticalSectionAndSpinCount(cs, cs_ptr, spin_count);
|
||||||
SHIM_SET_RETURN_32(result);
|
SHIM_SET_RETURN_32(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(benvanik): remove the need for passing in thread_id.
|
SHIM_CALL RtlEnterCriticalSection_shim(PPCContext* ppc_state,
|
||||||
void xeRtlEnterCriticalSection(X_RTL_CRITICAL_SECTION* cs, uint32_t thread_id) {
|
KernelState* state) {
|
||||||
// VOID
|
// VOID
|
||||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||||
|
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
|
||||||
|
// XELOGD("RtlEnterCriticalSection(%.8X)", cs_ptr);
|
||||||
|
|
||||||
|
const uint8_t* thread_state_block = ppc_state->membase + ppc_state->r[13];
|
||||||
|
uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block);
|
||||||
|
|
||||||
|
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
||||||
|
|
||||||
uint32_t spin_wait_remaining = cs->spin_count_div_256 * 256;
|
uint32_t spin_wait_remaining = cs->spin_count_div_256 * 256;
|
||||||
spin:
|
spin:
|
||||||
|
@ -515,41 +531,10 @@ spin:
|
||||||
cs->recursion_count = 1;
|
cs->recursion_count = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CALL RtlEnterCriticalSection_shim(PPCContext* ppc_state,
|
|
||||||
KernelState* state) {
|
|
||||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
// XELOGD("RtlEnterCriticalSection(%.8X)", cs_ptr);
|
|
||||||
|
|
||||||
const uint8_t* thread_state_block = ppc_state->membase + ppc_state->r[13];
|
|
||||||
uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block);
|
|
||||||
|
|
||||||
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
|
||||||
xeRtlEnterCriticalSection(cs, thread_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(benvanik): remove the need for passing in thread_id.
|
|
||||||
uint32_t xeRtlTryEnterCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
|
||||||
uint32_t thread_id) {
|
|
||||||
// DWORD
|
|
||||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
|
||||||
|
|
||||||
if (poly::atomic_cas(-1, 0, &cs->lock_count)) {
|
|
||||||
// Able to steal the lock right away.
|
|
||||||
cs->owning_thread_id = thread_id;
|
|
||||||
cs->recursion_count = 1;
|
|
||||||
return 1;
|
|
||||||
} else if (cs->owning_thread_id == thread_id) {
|
|
||||||
poly::atomic_inc(&cs->lock_count);
|
|
||||||
++cs->recursion_count;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
SHIM_CALL RtlTryEnterCriticalSection_shim(PPCContext* ppc_state,
|
SHIM_CALL RtlTryEnterCriticalSection_shim(PPCContext* ppc_state,
|
||||||
KernelState* state) {
|
KernelState* state) {
|
||||||
|
// DWORD
|
||||||
|
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
|
||||||
// XELOGD("RtlTryEnterCriticalSection(%.8X)", cs_ptr);
|
// XELOGD("RtlTryEnterCriticalSection(%.8X)", cs_ptr);
|
||||||
|
@ -558,13 +543,30 @@ SHIM_CALL RtlTryEnterCriticalSection_shim(PPCContext* ppc_state,
|
||||||
uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block);
|
uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block);
|
||||||
|
|
||||||
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
||||||
uint32_t result = xeRtlTryEnterCriticalSection(cs, thread_id);
|
|
||||||
|
uint32_t result = 0;
|
||||||
|
if (poly::atomic_cas(-1, 0, &cs->lock_count)) {
|
||||||
|
// Able to steal the lock right away.
|
||||||
|
cs->owning_thread_id = thread_id;
|
||||||
|
cs->recursion_count = 1;
|
||||||
|
result = 1;
|
||||||
|
} else if (cs->owning_thread_id == thread_id) {
|
||||||
|
poly::atomic_inc(&cs->lock_count);
|
||||||
|
++cs->recursion_count;
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
SHIM_SET_RETURN_64(result);
|
SHIM_SET_RETURN_64(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xeRtlLeaveCriticalSection(X_RTL_CRITICAL_SECTION* cs) {
|
SHIM_CALL RtlLeaveCriticalSection_shim(PPCContext* ppc_state,
|
||||||
|
KernelState* state) {
|
||||||
// VOID
|
// VOID
|
||||||
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
// _Inout_ LPCRITICAL_SECTION lpCriticalSection
|
||||||
|
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
|
||||||
|
// XELOGD("RtlLeaveCriticalSection(%.8X)", cs_ptr);
|
||||||
|
|
||||||
|
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
||||||
|
|
||||||
// Drop recursion count - if we are still not zero'ed return.
|
// Drop recursion count - if we are still not zero'ed return.
|
||||||
uint32_t recursion_count = --cs->recursion_count;
|
uint32_t recursion_count = --cs->recursion_count;
|
||||||
|
@ -582,16 +584,6 @@ void xeRtlLeaveCriticalSection(X_RTL_CRITICAL_SECTION* cs) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SHIM_CALL RtlLeaveCriticalSection_shim(PPCContext* ppc_state,
|
|
||||||
KernelState* state) {
|
|
||||||
uint32_t cs_ptr = SHIM_GET_ARG_32(0);
|
|
||||||
|
|
||||||
// XELOGD("RtlLeaveCriticalSection(%.8X)", cs_ptr);
|
|
||||||
|
|
||||||
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
|
|
||||||
xeRtlLeaveCriticalSection(cs);
|
|
||||||
}
|
|
||||||
|
|
||||||
SHIM_CALL RtlTimeToTimeFields_shim(PPCContext* ppc_state, KernelState* state) {
|
SHIM_CALL RtlTimeToTimeFields_shim(PPCContext* ppc_state, KernelState* state) {
|
||||||
uint32_t time_ptr = SHIM_GET_ARG_32(0);
|
uint32_t time_ptr = SHIM_GET_ARG_32(0);
|
||||||
uint32_t time_fields_ptr = SHIM_GET_ARG_32(1);
|
uint32_t time_fields_ptr = SHIM_GET_ARG_32(1);
|
||||||
|
|
|
@ -18,13 +18,11 @@ namespace kernel {
|
||||||
|
|
||||||
struct X_RTL_CRITICAL_SECTION;
|
struct X_RTL_CRITICAL_SECTION;
|
||||||
|
|
||||||
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs);
|
void xeRtlInitializeCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
||||||
|
uint32_t cs_ptr);
|
||||||
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
X_STATUS xeRtlInitializeCriticalSectionAndSpinCount(X_RTL_CRITICAL_SECTION* cs,
|
||||||
|
uint32_t cs_ptr,
|
||||||
uint32_t spin_count);
|
uint32_t spin_count);
|
||||||
void xeRtlEnterCriticalSection(X_RTL_CRITICAL_SECTION* cs, uint32_t thread_id);
|
|
||||||
uint32_t xeRtlTryEnterCriticalSection(X_RTL_CRITICAL_SECTION* cs,
|
|
||||||
uint32_t thread_id);
|
|
||||||
void xeRtlLeaveCriticalSection(X_RTL_CRITICAL_SECTION* cs);
|
|
||||||
|
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -465,5 +465,6 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver,
|
||||||
"xboxkrnl.exe", ordinals::VdHSIOCalibrationLock, pVdHSIOCalibrationLock);
|
"xboxkrnl.exe", ordinals::VdHSIOCalibrationLock, pVdHSIOCalibrationLock);
|
||||||
auto hsio_lock =
|
auto hsio_lock =
|
||||||
reinterpret_cast<X_RTL_CRITICAL_SECTION*>(mem + pVdHSIOCalibrationLock);
|
reinterpret_cast<X_RTL_CRITICAL_SECTION*>(mem + pVdHSIOCalibrationLock);
|
||||||
xeRtlInitializeCriticalSectionAndSpinCount(hsio_lock, 10000);
|
xeRtlInitializeCriticalSectionAndSpinCount(hsio_lock, pVdHSIOCalibrationLock,
|
||||||
|
10000);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue