summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp26
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,
40const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, 40const 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
44const ResultCode RESULT_INVALID(0xDEADC0DE);
45
46enum ControlMemoryOperation { 43enum 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
144static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { 141static 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) {
173static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { 174static 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}