From a2e623180a37f1c7418c55f5632d03034ffa526d Mon Sep 17 00:00:00 2001 From: Fisherman166 Date: Mon, 25 May 2020 16:11:51 -0700 Subject: [PATCH 1/7] Implement ExAcquireReadWriteLockExclusive. --- import/OpenXDK/include/xboxkrnl/ex.h | 2 +- src/core/kernel/exports/EmuKrnlEx.cpp | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/import/OpenXDK/include/xboxkrnl/ex.h b/import/OpenXDK/include/xboxkrnl/ex.h index 2be00ad40..ec4bd3dc3 100644 --- a/import/OpenXDK/include/xboxkrnl/ex.h +++ b/import/OpenXDK/include/xboxkrnl/ex.h @@ -12,7 +12,7 @@ #ifndef XBOXKRNL_EX_H #define XBOXKRNL_EX_H -XBSYSAPI EXPORTNUM(12) NTSTATUS NTAPI ExAcquireReadWriteLockExclusive +XBSYSAPI EXPORTNUM(12) VOID NTAPI ExAcquireReadWriteLockExclusive ( IN PERWLOCK ReadWriteLock ); diff --git a/src/core/kernel/exports/EmuKrnlEx.cpp b/src/core/kernel/exports/EmuKrnlEx.cpp index 46315a2bf..ed6092efe 100644 --- a/src/core/kernel/exports/EmuKrnlEx.cpp +++ b/src/core/kernel/exports/EmuKrnlEx.cpp @@ -144,17 +144,29 @@ static bool eeprom_data_is_valid(xboxkrnl::XC_VALUE_INDEX index) // * 0x000C - ExAcquireReadWriteLockExclusive() // ****************************************************************** // Source:APILogger - Uncertain -XBSYSAPI EXPORTNUM(12) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExAcquireReadWriteLockExclusive +XBSYSAPI EXPORTNUM(12) xboxkrnl::VOID NTAPI xboxkrnl::ExAcquireReadWriteLockExclusive ( IN PERWLOCK ReadWriteLock ) { LOG_FUNC_ONE_ARG(ReadWriteLock); - // KeWaitForSingleObject - LOG_UNIMPLEMENTED(); - - RETURN(S_OK); + bool interrupt_mode = DisableInterrupts(); + ReadWriteLock->LockCount++; + if (ReadWriteLock->LockCount != 0) { + ReadWriteLock->WritersWaitingCount++; + RestoreInterruptMode(interrupt_mode); + KeWaitForSingleObject( + &ReadWriteLock->WriterEvent, + Executive, + 0, + 0, + 0 + ); + } + else { + RestoreInterruptMode(interrupt_mode); + } } // ****************************************************************** From f375bbf6ba1e630818a4f6f2bc6501e5f49e530f Mon Sep 17 00:00:00 2001 From: Fisherman166 Date: Mon, 25 May 2020 16:12:22 -0700 Subject: [PATCH 2/7] Add offset comments to _ERWLOCK and _KSEMAPHORE structs. --- import/OpenXDK/include/xboxkrnl/xboxkrnl.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h index 6bb308ec4..8877319cc 100644 --- a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h +++ b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h @@ -1279,8 +1279,8 @@ EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION; // ****************************************************************** typedef struct _KSEMAPHORE { - DISPATCHER_HEADER Header; - LONG Limit; + DISPATCHER_HEADER Header; // 0x00 + LONG Limit; // 0x10 } KSEMAPHORE, *PKSEMAPHORE, *RESTRICTED_POINTER PRKSEMAPHORE; @@ -1310,12 +1310,12 @@ MUTANT_BASIC_INFORMATION, *PMUTANT_BASIC_INFORMATION; // ****************************************************************** typedef struct _ERWLOCK { - LONG LockCount; - ULONG WritersWaitingCount; - ULONG ReadersWaitingCount; - ULONG ReadersEntryCount; - KEVENT WriterEvent; - KSEMAPHORE ReaderSemaphore; + LONG LockCount; // 0x00 + ULONG WritersWaitingCount; // 0x04 + ULONG ReadersWaitingCount; // 0x08 + ULONG ReadersEntryCount; // 0x0C + KEVENT WriterEvent; // 0x10 + KSEMAPHORE ReaderSemaphore; // 0x20 } ERWLOCK, *PERWLOCK; From 6f5a1f2c46ae89a4ff05fa070e4a83c7b28a1480 Mon Sep 17 00:00:00 2001 From: Fisherman166 Date: Mon, 25 May 2020 16:13:11 -0700 Subject: [PATCH 3/7] Implement ExAcquireReadWriteLockShared. --- import/OpenXDK/include/xboxkrnl/ex.h | 2 +- src/core/kernel/exports/EmuKrnlEx.cpp | 46 ++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/import/OpenXDK/include/xboxkrnl/ex.h b/import/OpenXDK/include/xboxkrnl/ex.h index ec4bd3dc3..3eab959e2 100644 --- a/import/OpenXDK/include/xboxkrnl/ex.h +++ b/import/OpenXDK/include/xboxkrnl/ex.h @@ -17,7 +17,7 @@ XBSYSAPI EXPORTNUM(12) VOID NTAPI ExAcquireReadWriteLockExclusive IN PERWLOCK ReadWriteLock ); -XBSYSAPI EXPORTNUM(13) NTSTATUS NTAPI ExAcquireReadWriteLockShared +XBSYSAPI EXPORTNUM(13) VOID NTAPI ExAcquireReadWriteLockShared ( IN PERWLOCK ReadWriteLock ); diff --git a/src/core/kernel/exports/EmuKrnlEx.cpp b/src/core/kernel/exports/EmuKrnlEx.cpp index ed6092efe..db0584059 100644 --- a/src/core/kernel/exports/EmuKrnlEx.cpp +++ b/src/core/kernel/exports/EmuKrnlEx.cpp @@ -173,17 +173,53 @@ XBSYSAPI EXPORTNUM(12) xboxkrnl::VOID NTAPI xboxkrnl::ExAcquireReadWriteLockExcl // * 0x000D - ExAcquireReadWriteLockShared() // ****************************************************************** // Source:APILogger - Uncertain -XBSYSAPI EXPORTNUM(13) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExAcquireReadWriteLockShared +XBSYSAPI EXPORTNUM(13) xboxkrnl::VOID NTAPI xboxkrnl::ExAcquireReadWriteLockShared ( IN PERWLOCK ReadWriteLock ) { LOG_FUNC_ONE_ARG(ReadWriteLock); - // KeWaitForSingleObject - LOG_UNIMPLEMENTED(); - - RETURN(S_OK); + bool interrupt_mode = DisableInterrupts(); + ReadWriteLock->LockCount++; + if (ReadWriteLock->LockCount != 0) { + if (ReadWriteLock->ReadersEntryCount == 0) { + ReadWriteLock->ReadersWaitingCount++; + RestoreInterruptMode(interrupt_mode); +#if 0 //FIXME - Enable once KeReleaseSempahore is implemented (used in ExFreeReadWriteLock for Sharedlocks). + KeWaitForSingleObject( + &ReadWriteLock->ReaderSemaphore, + Executive, + 0, + 0, + 0 + ); +#endif + } + else { + if (ReadWriteLock->WritersWaitingCount == 0) { + ReadWriteLock->ReadersEntryCount++; + RestoreInterruptMode(interrupt_mode); + } + else { + ReadWriteLock->ReadersWaitingCount++; + RestoreInterruptMode(interrupt_mode); +#if 0 //FIXME - Enable once KeReleaseSempahore is implemented (used in ExFreeReadWriteLock for Sharedlocks). + KeWaitForSingleObject( + &ReadWriteLock->ReaderSemaphore, + Executive, + 0, + 0, + 0 + ); +#endif + } + } + } + else { + ReadWriteLock->ReadersEntryCount++; + RestoreInterruptMode(interrupt_mode); + } } // ****************************************************************** From a679073ec6620b8a7e9cf088245e61102b88a0d1 Mon Sep 17 00:00:00 2001 From: Fisherman166 Date: Mon, 25 May 2020 16:13:39 -0700 Subject: [PATCH 4/7] Implement ExReleaseReadWriteLock. --- import/OpenXDK/include/xboxkrnl/ex.h | 2 +- src/core/kernel/exports/EmuKrnlEx.cpp | 38 ++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/import/OpenXDK/include/xboxkrnl/ex.h b/import/OpenXDK/include/xboxkrnl/ex.h index 3eab959e2..5b4da1933 100644 --- a/import/OpenXDK/include/xboxkrnl/ex.h +++ b/import/OpenXDK/include/xboxkrnl/ex.h @@ -134,7 +134,7 @@ XBSYSAPI EXPORTNUM(27) VOID NTAPI ExRaiseStatus IN NTSTATUS Status ); -XBSYSAPI EXPORTNUM(28) NTSTATUS NTAPI ExReleaseReadWriteLock +XBSYSAPI EXPORTNUM(28) VOID NTAPI ExReleaseReadWriteLock ( IN PERWLOCK ReadWriteLock ); diff --git a/src/core/kernel/exports/EmuKrnlEx.cpp b/src/core/kernel/exports/EmuKrnlEx.cpp index db0584059..820d35ece 100644 --- a/src/core/kernel/exports/EmuKrnlEx.cpp +++ b/src/core/kernel/exports/EmuKrnlEx.cpp @@ -601,16 +601,46 @@ XBSYSAPI EXPORTNUM(27) xboxkrnl::VOID NTAPI xboxkrnl::ExRaiseStatus // * 0x001C - ExReleaseReadWriteLock() // ****************************************************************** // Source:APILogger - Uncertain -XBSYSAPI EXPORTNUM(28) xboxkrnl::NTSTATUS NTAPI xboxkrnl::ExReleaseReadWriteLock +XBSYSAPI EXPORTNUM(28) xboxkrnl::VOID NTAPI xboxkrnl::ExReleaseReadWriteLock ( IN PERWLOCK ReadWriteLock ) { LOG_FUNC_ONE_ARG(ReadWriteLock); - LOG_UNIMPLEMENTED(); - - RETURN(S_OK); + bool interrupt_mode = DisableInterrupts(); + ReadWriteLock->LockCount--; + if (ReadWriteLock->LockCount >= 0) { + if(ReadWriteLock->ReadersEntryCount == 0) { + if(ReadWriteLock->ReadersWaitingCount == 0) { + ReadWriteLock->WritersWaitingCount--; + RestoreInterruptMode(interrupt_mode); + KeSetEvent(&ReadWriteLock->WriterEvent, 1, 0); + } + else { + ULONG temp_readers_waiting = ReadWriteLock->ReadersWaitingCount; + ReadWriteLock->ReadersEntryCount = ReadWriteLock->ReadersWaitingCount; + ReadWriteLock->ReadersWaitingCount = 0; + RestoreInterruptMode(interrupt_mode); + KeReleaseSemaphore(&ReadWriteLock->ReaderSemaphore, 1, (BOOLEAN)temp_readers_waiting, 0); + } + } + else { + ReadWriteLock->ReadersEntryCount--; + if(ReadWriteLock->ReadersEntryCount == 0) { + ReadWriteLock->WritersWaitingCount--; + RestoreInterruptMode(interrupt_mode); + KeSetEvent(&ReadWriteLock->WriterEvent, 1, 0); + } + else { + RestoreInterruptMode(interrupt_mode); + } + } + } + else { + ReadWriteLock->ReadersEntryCount = 0; + RestoreInterruptMode(interrupt_mode); + } } // ****************************************************************** From b72be80b8878adf05fd0aec0d4f84a3f064fbf5a Mon Sep 17 00:00:00 2001 From: Fisherman166 Date: Tue, 26 May 2020 09:20:15 -0700 Subject: [PATCH 5/7] Refactor ExAcquireReadWriteLockShared to remove duplicate code. --- src/core/kernel/exports/EmuKrnlEx.cpp | 44 ++++++++------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/src/core/kernel/exports/EmuKrnlEx.cpp b/src/core/kernel/exports/EmuKrnlEx.cpp index 820d35ece..8e305527f 100644 --- a/src/core/kernel/exports/EmuKrnlEx.cpp +++ b/src/core/kernel/exports/EmuKrnlEx.cpp @@ -181,40 +181,22 @@ XBSYSAPI EXPORTNUM(13) xboxkrnl::VOID NTAPI xboxkrnl::ExAcquireReadWriteLockShar LOG_FUNC_ONE_ARG(ReadWriteLock); bool interrupt_mode = DisableInterrupts(); + bool must_wait_on_active_write = ReadWriteLock->ReadersEntryCount == 0; + bool must_wait_on_queued_write = (ReadWriteLock->ReadersEntryCount != 0) && (ReadWriteLock->WritersWaitingCount != 0); + bool must_wait = must_wait_on_active_write || must_wait_on_queued_write; ReadWriteLock->LockCount++; - if (ReadWriteLock->LockCount != 0) { - if (ReadWriteLock->ReadersEntryCount == 0) { - ReadWriteLock->ReadersWaitingCount++; - RestoreInterruptMode(interrupt_mode); + if ((ReadWriteLock->LockCount != 0) && must_wait) { + ReadWriteLock->ReadersWaitingCount++; + RestoreInterruptMode(interrupt_mode); #if 0 //FIXME - Enable once KeReleaseSempahore is implemented (used in ExFreeReadWriteLock for Sharedlocks). - KeWaitForSingleObject( - &ReadWriteLock->ReaderSemaphore, - Executive, - 0, - 0, - 0 - ); + KeWaitForSingleObject( + &ReadWriteLock->ReaderSemaphore, + Executive, + 0, + 0, + 0 + ); #endif - } - else { - if (ReadWriteLock->WritersWaitingCount == 0) { - ReadWriteLock->ReadersEntryCount++; - RestoreInterruptMode(interrupt_mode); - } - else { - ReadWriteLock->ReadersWaitingCount++; - RestoreInterruptMode(interrupt_mode); -#if 0 //FIXME - Enable once KeReleaseSempahore is implemented (used in ExFreeReadWriteLock for Sharedlocks). - KeWaitForSingleObject( - &ReadWriteLock->ReaderSemaphore, - Executive, - 0, - 0, - 0 - ); -#endif - } - } } else { ReadWriteLock->ReadersEntryCount++; From 49e68a1eccf20286bcea3c7c85df4667aa94d473 Mon Sep 17 00:00:00 2001 From: Fisherman166 Date: Thu, 28 May 2020 09:10:51 -0700 Subject: [PATCH 6/7] Refactor ExReleaseReadWriteLock. --- src/core/kernel/exports/EmuKrnlEx.cpp | 50 ++++++++++++--------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/core/kernel/exports/EmuKrnlEx.cpp b/src/core/kernel/exports/EmuKrnlEx.cpp index 8e305527f..6f1185a99 100644 --- a/src/core/kernel/exports/EmuKrnlEx.cpp +++ b/src/core/kernel/exports/EmuKrnlEx.cpp @@ -592,37 +592,33 @@ XBSYSAPI EXPORTNUM(28) xboxkrnl::VOID NTAPI xboxkrnl::ExReleaseReadWriteLock bool interrupt_mode = DisableInterrupts(); ReadWriteLock->LockCount--; - if (ReadWriteLock->LockCount >= 0) { - if(ReadWriteLock->ReadersEntryCount == 0) { - if(ReadWriteLock->ReadersWaitingCount == 0) { - ReadWriteLock->WritersWaitingCount--; - RestoreInterruptMode(interrupt_mode); - KeSetEvent(&ReadWriteLock->WriterEvent, 1, 0); - } - else { - ULONG temp_readers_waiting = ReadWriteLock->ReadersWaitingCount; - ReadWriteLock->ReadersEntryCount = ReadWriteLock->ReadersWaitingCount; - ReadWriteLock->ReadersWaitingCount = 0; - RestoreInterruptMode(interrupt_mode); - KeReleaseSemaphore(&ReadWriteLock->ReaderSemaphore, 1, (BOOLEAN)temp_readers_waiting, 0); - } - } - else { - ReadWriteLock->ReadersEntryCount--; - if(ReadWriteLock->ReadersEntryCount == 0) { - ReadWriteLock->WritersWaitingCount--; - RestoreInterruptMode(interrupt_mode); - KeSetEvent(&ReadWriteLock->WriterEvent, 1, 0); - } - else { - RestoreInterruptMode(interrupt_mode); - } + if (ReadWriteLock->LockCount == -1) { + ReadWriteLock->ReadersEntryCount = 0; + RestoreInterruptMode(interrupt_mode); + return; + } + + if (ReadWriteLock->ReadersEntryCount == 0) { + if (ReadWriteLock->ReadersWaitingCount != 0) { + ULONG temp_readers_waiting = ReadWriteLock->ReadersWaitingCount; + ReadWriteLock->ReadersEntryCount = ReadWriteLock->ReadersWaitingCount; + ReadWriteLock->ReadersWaitingCount = 0; + RestoreInterruptMode(interrupt_mode); + KeReleaseSemaphore(&ReadWriteLock->ReaderSemaphore, 1, (BOOLEAN)temp_readers_waiting, 0); + return; } } else { - ReadWriteLock->ReadersEntryCount = 0; - RestoreInterruptMode(interrupt_mode); + ReadWriteLock->ReadersEntryCount--; + if (ReadWriteLock->ReadersEntryCount != 0) { + RestoreInterruptMode(interrupt_mode); + return; + } } + + ReadWriteLock->WritersWaitingCount--; + RestoreInterruptMode(interrupt_mode); + KeSetEvent(&ReadWriteLock->WriterEvent, 1, 0); } // ****************************************************************** From 52f18bca28f3e954fe0d8aed2507f2bcdbb624bf Mon Sep 17 00:00:00 2001 From: Fisherman166 Date: Thu, 28 May 2020 09:13:19 -0700 Subject: [PATCH 7/7] Add size offsets for the KSEMAPHORE and ERWLOCK structs. --- import/OpenXDK/include/xboxkrnl/xboxkrnl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h index 8877319cc..da9c774eb 100644 --- a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h +++ b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h @@ -1281,7 +1281,7 @@ typedef struct _KSEMAPHORE { DISPATCHER_HEADER Header; // 0x00 LONG Limit; // 0x10 -} +} // 0x14 KSEMAPHORE, *PKSEMAPHORE, *RESTRICTED_POINTER PRKSEMAPHORE; // ****************************************************************** @@ -1316,7 +1316,7 @@ typedef struct _ERWLOCK ULONG ReadersEntryCount; // 0x0C KEVENT WriterEvent; // 0x10 KSEMAPHORE ReaderSemaphore; // 0x20 -} +} // 0x34 ERWLOCK, *PERWLOCK; // ******************************************************************