From e795337071c162bfff276037801f49acfb9064c5 Mon Sep 17 00:00:00 2001 From: gibbed Date: Fri, 7 Jan 2022 09:18:10 -0600 Subject: [PATCH] [xboxkrnl] ExReleaseReadWriteLock fixes. [xboxkrnl] ExReleaseReadWriteLock fixes: - Don't unncessarily double-load lock members. - Reset readers entry count when lock count becomes negative. - Properly decrease writers waiting count when writer event fired. --- .../kernel/xboxkrnl/xboxkrnl_threading.cc | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc index 178dbe447..62c445635 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc @@ -1201,9 +1201,11 @@ DECLARE_XBOXKRNL_EXPORT2(ExAcquireReadWriteLockExclusive, kThreading, void ExReleaseReadWriteLock(pointer_t lock_ptr) { auto old_irql = xeKeKfAcquireSpinLock(&lock_ptr->spin_lock); - lock_ptr->lock_count--; - if (lock_ptr->lock_count < 0) { + 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); return; } @@ -1220,14 +1222,17 @@ void ExReleaseReadWriteLock(pointer_t lock_ptr) { } } - auto count = lock_ptr->readers_entry_count--; - xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); - if (!count) { - xeKeSetEvent(&lock_ptr->writer_event, 1, 0); + auto readers_entry_count = --lock_ptr->readers_entry_count; + if (readers_entry_count) { + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + return; } + + lock_ptr->writers_waiting_count--; + xeKeKfReleaseSpinLock(&lock_ptr->spin_lock, old_irql); + xeKeSetEvent(&lock_ptr->writer_event, 1, 0); } -DECLARE_XBOXKRNL_EXPORT2(ExReleaseReadWriteLock, kThreading, kImplemented, - kSketchy); +DECLARE_XBOXKRNL_EXPORT1(ExReleaseReadWriteLock, kThreading, kImplemented); // NOTE: This function is very commonly inlined, and probably won't be called! pointer_result_t InterlockedPushEntrySList(