diff options
| author | 2018-06-21 20:25:57 -0600 | |
|---|---|---|
| committer | 2018-06-21 20:25:57 -0600 | |
| commit | dc70a87af1576e29dd6fda1d0313aca260982498 (patch) | |
| tree | ad2458fcae93251cd0110ab02f8d3a2db766b3dc /src/core/hle/kernel | |
| parent | Kernel/Arbiters: Initialize arb_wait_address in thread struct. (diff) | |
| download | yuzu-dc70a87af1576e29dd6fda1d0313aca260982498.tar.gz yuzu-dc70a87af1576e29dd6fda1d0313aca260982498.tar.xz yuzu-dc70a87af1576e29dd6fda1d0313aca260982498.zip | |
Kernel/Arbiters: HLE is atomic, adjust code to reflect that.
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 49 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 1 |
2 files changed, 13 insertions, 37 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 63cdcb559..01c5bf61b 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp | |||
| @@ -20,14 +20,14 @@ namespace Kernel { | |||
| 20 | ResultCode WaitForAddress(VAddr address, s64 timeout) { | 20 | ResultCode WaitForAddress(VAddr address, s64 timeout) { |
| 21 | SharedPtr<Thread> current_thread = GetCurrentThread(); | 21 | SharedPtr<Thread> current_thread = GetCurrentThread(); |
| 22 | current_thread->arb_wait_address = address; | 22 | current_thread->arb_wait_address = address; |
| 23 | current_thread->arb_wait_result = RESULT_TIMEOUT; | ||
| 24 | current_thread->status = THREADSTATUS_WAIT_ARB; | 23 | current_thread->status = THREADSTATUS_WAIT_ARB; |
| 25 | current_thread->wakeup_callback = nullptr; | 24 | current_thread->wakeup_callback = nullptr; |
| 26 | 25 | ||
| 27 | current_thread->WakeAfterDelay(timeout); | 26 | current_thread->WakeAfterDelay(timeout); |
| 28 | 27 | ||
| 29 | Core::System::GetInstance().CpuCore(current_thread->processor_id).PrepareReschedule(); | 28 | Core::System::GetInstance().CpuCore(current_thread->processor_id).PrepareReschedule(); |
| 30 | return current_thread->arb_wait_result; | 29 | // This should never actually execute. |
| 30 | return RESULT_SUCCESS; | ||
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | // Gets the threads waiting on an address. | 33 | // Gets the threads waiting on an address. |
| @@ -67,7 +67,7 @@ namespace Kernel { | |||
| 67 | // TODO: Rescheduling should not occur while waking threads. How can it be prevented? | 67 | // TODO: Rescheduling should not occur while waking threads. How can it be prevented? |
| 68 | for (size_t i = 0; i < last; i++) { | 68 | for (size_t i = 0; i < last; i++) { |
| 69 | ASSERT(waiting_threads[i]->status = THREADSTATUS_WAIT_ARB); | 69 | ASSERT(waiting_threads[i]->status = THREADSTATUS_WAIT_ARB); |
| 70 | waiting_threads[i]->arb_wait_result = RESULT_SUCCESS; | 70 | waiting_threads[i]->SetWaitSynchronizationResult(RESULT_SUCCESS); |
| 71 | waiting_threads[i]->arb_wait_address = 0; | 71 | waiting_threads[i]->arb_wait_address = 0; |
| 72 | waiting_threads[i]->ResumeFromWait(); | 72 | waiting_threads[i]->ResumeFromWait(); |
| 73 | } | 73 | } |
| @@ -91,17 +91,9 @@ namespace Kernel { | |||
| 91 | return ERR_INVALID_ADDRESS_STATE; | 91 | return ERR_INVALID_ADDRESS_STATE; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | s32 cur_value; | 94 | if ((s32)Memory::Read32(address) == value) { |
| 95 | // Get value, incrementing if equal. | 95 | Memory::Write32(address, (u32)(value + 1)); |
| 96 | { | 96 | } else { |
| 97 | // Increment if Equal must be an atomic operation. | ||
| 98 | std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); | ||
| 99 | cur_value = (s32)Memory::Read32(address); | ||
| 100 | if (cur_value == value) { | ||
| 101 | Memory::Write32(address, (u32)(cur_value + 1)); | ||
| 102 | } | ||
| 103 | } | ||
| 104 | if (cur_value != value) { | ||
| 105 | return ERR_INVALID_STATE; | 97 | return ERR_INVALID_STATE; |
| 106 | } | 98 | } |
| 107 | 99 | ||
| @@ -128,18 +120,10 @@ namespace Kernel { | |||
| 128 | } else { | 120 | } else { |
| 129 | updated_value = value; | 121 | updated_value = value; |
| 130 | } | 122 | } |
| 131 | s32 cur_value; | ||
| 132 | // Perform an atomic update if equal. | ||
| 133 | { | ||
| 134 | std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); | ||
| 135 | cur_value = (s32)Memory::Read32(address); | ||
| 136 | if (cur_value == value) { | ||
| 137 | Memory::Write32(address, (u32)(updated_value)); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | 123 | ||
| 141 | // Only continue if equal. | 124 | if ((s32)Memory::Read32(address) == value) { |
| 142 | if (cur_value != value) { | 125 | Memory::Write32(address, (u32)(updated_value)); |
| 126 | } else { | ||
| 143 | return ERR_INVALID_STATE; | 127 | return ERR_INVALID_STATE; |
| 144 | } | 128 | } |
| 145 | 129 | ||
| @@ -154,17 +138,10 @@ namespace Kernel { | |||
| 154 | return ERR_INVALID_ADDRESS_STATE; | 138 | return ERR_INVALID_ADDRESS_STATE; |
| 155 | } | 139 | } |
| 156 | 140 | ||
| 157 | s32 cur_value; | 141 | s32 cur_value = (s32)Memory::Read32(address); |
| 158 | // Get value, decrementing if less than | 142 | if (cur_value < value) { |
| 159 | { | 143 | Memory::Write32(address, (u32)(cur_value - 1)); |
| 160 | // Decrement if less than must be an atomic operation. | 144 | } else { |
| 161 | std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); | ||
| 162 | cur_value = (s32)Memory::Read32(address); | ||
| 163 | if (cur_value < value) { | ||
| 164 | Memory::Write32(address, (u32)(cur_value - 1)); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | if (cur_value >= value) { | ||
| 168 | return ERR_INVALID_STATE; | 145 | return ERR_INVALID_STATE; |
| 169 | } | 146 | } |
| 170 | // Short-circuit without rescheduling, if timeout is zero. | 147 | // Short-circuit without rescheduling, if timeout is zero. |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 7a28f3c1c..3851d1085 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -233,7 +233,6 @@ public: | |||
| 233 | 233 | ||
| 234 | // If waiting for an AddressArbiter, this is the address being waited on. | 234 | // If waiting for an AddressArbiter, this is the address being waited on. |
| 235 | VAddr arb_wait_address{0}; | 235 | VAddr arb_wait_address{0}; |
| 236 | ResultCode arb_wait_result{RESULT_SUCCESS}; ///< Result returned when done waiting on AddressArbiter. | ||
| 237 | 236 | ||
| 238 | std::string name; | 237 | std::string name; |
| 239 | 238 | ||