diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/hle/svc.cpp | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 059451100..01b536084 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -149,15 +149,20 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 149 | bool wait_thread = !wait_all; | 149 | bool wait_thread = !wait_all; |
| 150 | int handle_index = 0; | 150 | int handle_index = 0; |
| 151 | 151 | ||
| 152 | // Handles pointer is invalid | 152 | // Check if 'handles' is invalid |
| 153 | if (handles == nullptr) | 153 | if (handles == nullptr) |
| 154 | return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent).raw; | 154 | return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent).raw; |
| 155 | 155 | ||
| 156 | // Negative handle_count is invalid | 156 | // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If |
| 157 | // this happens, the running application will crash. | ||
| 158 | _assert_msg_(Kernel, out != nullptr, "invalid output pointer specified!"); | ||
| 159 | |||
| 160 | // Check if 'handle_count' is invalid | ||
| 157 | if (handle_count < 0) | 161 | if (handle_count < 0) |
| 158 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; | 162 | return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; |
| 159 | 163 | ||
| 160 | // If handle_count is non-zero, iterate through them and wait the current thread on the objects | 164 | // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if |
| 165 | // necessary | ||
| 161 | if (handle_count != 0) { | 166 | if (handle_count != 0) { |
| 162 | bool selected = false; // True once an object has been selected | 167 | bool selected = false; // True once an object has been selected |
| 163 | for (int i = 0; i < handle_count; ++i) { | 168 | for (int i = 0; i < handle_count; ++i) { |
| @@ -167,7 +172,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 167 | 172 | ||
| 168 | ResultVal<bool> wait = object->Wait(true); | 173 | ResultVal<bool> wait = object->Wait(true); |
| 169 | 174 | ||
| 170 | // Check if the current thread should wait on the object... | 175 | // Check if the current thread should wait on this object... |
| 171 | if (wait.Succeeded() && *wait) { | 176 | if (wait.Succeeded() && *wait) { |
| 172 | // Check we are waiting on all objects... | 177 | // Check we are waiting on all objects... |
| 173 | if (wait_all) | 178 | if (wait_all) |
| @@ -184,15 +189,15 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 184 | } | 189 | } |
| 185 | } | 190 | } |
| 186 | } else { | 191 | } else { |
| 187 | // If no handles were passed in, put the thread to sleep only when wait_all=false | 192 | // If no handles were passed in, put the thread to sleep only when 'wait_all' is false |
| 188 | // NOTE: This is supposed to deadlock the current thread if no timeout was specified | 193 | // NOTE: This should deadlock the current thread if no timeout was specified |
| 189 | if (!wait_all) { | 194 | if (!wait_all) { |
| 190 | wait_thread = true; | 195 | wait_thread = true; |
| 191 | Kernel::WaitCurrentThread(WAITTYPE_SLEEP); | 196 | Kernel::WaitCurrentThread(WAITTYPE_SLEEP); |
| 192 | } | 197 | } |
| 193 | } | 198 | } |
| 194 | 199 | ||
| 195 | // If thread should block, then set its state to waiting and then reschedule... | 200 | // If thread should wait, then set its state to waiting and then reschedule... |
| 196 | if (wait_thread) { | 201 | if (wait_thread) { |
| 197 | // Create an event to wake the thread up after the specified nanosecond delay has passed | 202 | // Create an event to wake the thread up after the specified nanosecond delay has passed |
| 198 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); | 203 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); |