diff options
Diffstat (limited to 'src/core/hle/svc.cpp')
| -rw-r--r-- | src/core/hle/svc.cpp | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index d1555c753..6cde4fc87 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -40,9 +40,6 @@ const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, | |||
| 40 | const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, | 40 | const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, |
| 41 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E | 41 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E |
| 42 | 42 | ||
| 43 | /// An invalid result code that is meant to be overwritten when a thread resumes from waiting | ||
| 44 | const ResultCode RESULT_INVALID(0xDEADC0DE); | ||
| 45 | |||
| 46 | enum ControlMemoryOperation { | 43 | enum ControlMemoryOperation { |
| 47 | MEMORY_OPERATION_HEAP = 0x00000003, | 44 | MEMORY_OPERATION_HEAP = 0x00000003, |
| 48 | MEMORY_OPERATION_GSP_HEAP = 0x00010003, | 45 | MEMORY_OPERATION_GSP_HEAP = 0x00010003, |
| @@ -143,6 +140,10 @@ static ResultCode CloseHandle(Handle handle) { | |||
| 143 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds | 140 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds |
| 144 | static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { | 141 | static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { |
| 145 | auto object = Kernel::g_handle_table.GetWaitObject(handle); | 142 | auto object = Kernel::g_handle_table.GetWaitObject(handle); |
| 143 | Kernel::Thread* thread = Kernel::GetCurrentThread(); | ||
| 144 | |||
| 145 | thread->waitsynch_waited = false; | ||
| 146 | |||
| 146 | if (object == nullptr) | 147 | if (object == nullptr) |
| 147 | return ERR_INVALID_HANDLE; | 148 | return ERR_INVALID_HANDLE; |
| 148 | 149 | ||
| @@ -154,14 +155,14 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { | |||
| 154 | // Check for next thread to schedule | 155 | // Check for next thread to schedule |
| 155 | if (object->ShouldWait()) { | 156 | if (object->ShouldWait()) { |
| 156 | 157 | ||
| 157 | object->AddWaitingThread(Kernel::GetCurrentThread()); | 158 | object->AddWaitingThread(thread); |
| 158 | Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false); | 159 | Kernel::WaitCurrentThread_WaitSynchronization({ object }, false, false); |
| 159 | 160 | ||
| 160 | // Create an event to wake the thread up after the specified nanosecond delay has passed | 161 | // Create an event to wake the thread up after the specified nanosecond delay has passed |
| 161 | Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds); | 162 | thread->WakeAfterDelay(nano_seconds); |
| 162 | 163 | ||
| 163 | // NOTE: output of this SVC will be set later depending on how the thread resumes | 164 | // NOTE: output of this SVC will be set later depending on how the thread resumes |
| 164 | return RESULT_INVALID; | 165 | return HLE::RESULT_INVALID; |
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | object->Acquire(); | 168 | object->Acquire(); |
| @@ -173,6 +174,9 @@ static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { | |||
| 173 | static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { | 174 | static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { |
| 174 | bool wait_thread = !wait_all; | 175 | bool wait_thread = !wait_all; |
| 175 | int handle_index = 0; | 176 | int handle_index = 0; |
| 177 | Kernel::Thread* thread = Kernel::GetCurrentThread(); | ||
| 178 | bool was_waiting = thread->waitsynch_waited; | ||
| 179 | thread->waitsynch_waited = false; | ||
| 176 | 180 | ||
| 177 | // Check if 'handles' is invalid | 181 | // Check if 'handles' is invalid |
| 178 | if (handles == nullptr) | 182 | if (handles == nullptr) |
| @@ -190,6 +194,9 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou | |||
| 190 | // necessary | 194 | // necessary |
| 191 | if (handle_count != 0) { | 195 | if (handle_count != 0) { |
| 192 | bool selected = false; // True once an object has been selected | 196 | bool selected = false; // True once an object has been selected |
| 197 | |||
| 198 | Kernel::SharedPtr<Kernel::WaitObject> wait_object; | ||
| 199 | |||
| 193 | for (int i = 0; i < handle_count; ++i) { | 200 | for (int i = 0; i < handle_count; ++i) { |
| 194 | auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); | 201 | auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); |
| 195 | if (object == nullptr) | 202 | if (object == nullptr) |
| @@ -204,10 +211,11 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou | |||
| 204 | wait_thread = true; | 211 | wait_thread = true; |
| 205 | } else { | 212 | } else { |
| 206 | // Do not wait on this object, check if this object should be selected... | 213 | // Do not wait on this object, check if this object should be selected... |
| 207 | if (!wait_all && !selected) { | 214 | if (!wait_all && (!selected || (wait_object == object && was_waiting))) { |
| 208 | // Do not wait the thread | 215 | // Do not wait the thread |
| 209 | wait_thread = false; | 216 | wait_thread = false; |
| 210 | handle_index = i; | 217 | handle_index = i; |
| 218 | wait_object = object; | ||
| 211 | selected = true; | 219 | selected = true; |
| 212 | } | 220 | } |
| 213 | } | 221 | } |
| @@ -241,7 +249,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou | |||
| 241 | Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds); | 249 | Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds); |
| 242 | 250 | ||
| 243 | // NOTE: output of this SVC will be set later depending on how the thread resumes | 251 | // NOTE: output of this SVC will be set later depending on how the thread resumes |
| 244 | return RESULT_INVALID; | 252 | return HLE::RESULT_INVALID; |
| 245 | } | 253 | } |
| 246 | 254 | ||
| 247 | // Acquire objects if we did not wait... | 255 | // Acquire objects if we did not wait... |
| @@ -261,7 +269,7 @@ static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_cou | |||
| 261 | 269 | ||
| 262 | // TODO(bunnei): If 'wait_all' is true, this is probably wrong. However, real hardware does | 270 | // TODO(bunnei): If 'wait_all' is true, this is probably wrong. However, real hardware does |
| 263 | // not seem to set it to any meaningful value. | 271 | // not seem to set it to any meaningful value. |
| 264 | *out = wait_all ? 0 : handle_index; | 272 | *out = handle_count != 0 ? (wait_all ? -1 : handle_index) : 0; |
| 265 | 273 | ||
| 266 | return RESULT_SUCCESS; | 274 | return RESULT_SUCCESS; |
| 267 | } | 275 | } |