diff options
Diffstat (limited to 'src/core/hle/svc.cpp')
| -rw-r--r-- | src/core/hle/svc.cpp | 68 |
1 files changed, 37 insertions, 31 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 3a06d6765..87d768856 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "core/hle/kernel/thread.h" | 16 | #include "core/hle/kernel/thread.h" |
| 17 | 17 | ||
| 18 | #include "core/hle/function_wrappers.h" | 18 | #include "core/hle/function_wrappers.h" |
| 19 | #include "core/hle/result.h" | ||
| 19 | #include "core/hle/service/service.h" | 20 | #include "core/hle/service/service.h" |
| 20 | 21 | ||
| 21 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 22 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| @@ -86,18 +87,22 @@ static Result ConnectToPort(Handle* out, const char* port_name) { | |||
| 86 | 87 | ||
| 87 | /// Synchronize to an OS service | 88 | /// Synchronize to an OS service |
| 88 | static Result SendSyncRequest(Handle handle) { | 89 | static Result SendSyncRequest(Handle handle) { |
| 90 | // TODO(yuriks): ObjectPool::Get tries to check the Object type, which fails since this is a generic base Object, | ||
| 91 | // so we are forced to use GetFast and manually verify the handle. | ||
| 92 | if (!Kernel::g_object_pool.IsValid(handle)) { | ||
| 93 | return InvalidHandle(ErrorModule::Kernel).raw; | ||
| 94 | } | ||
| 89 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); | 95 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); |
| 90 | 96 | ||
| 91 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); | 97 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); |
| 92 | DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str()); | 98 | DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str()); |
| 93 | 99 | ||
| 94 | bool wait = false; | 100 | ResultVal<bool> wait = object->SyncRequest(); |
| 95 | Result res = object->SyncRequest(&wait); | 101 | if (wait.Succeeded() && *wait) { |
| 96 | if (wait) { | ||
| 97 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? | 102 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? |
| 98 | } | 103 | } |
| 99 | 104 | ||
| 100 | return res; | 105 | return wait.Code().raw; |
| 101 | } | 106 | } |
| 102 | 107 | ||
| 103 | /// Close a handle | 108 | /// Close a handle |
| @@ -110,25 +115,25 @@ static Result CloseHandle(Handle handle) { | |||
| 110 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds | 115 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds |
| 111 | static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { | 116 | static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { |
| 112 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this | 117 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this |
| 113 | bool wait = false; | ||
| 114 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated | 118 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated |
| 115 | 119 | ||
| 120 | if (!Kernel::g_object_pool.IsValid(handle)) { | ||
| 121 | return InvalidHandle(ErrorModule::Kernel).raw; | ||
| 122 | } | ||
| 116 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); | 123 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); |
| 124 | _dbg_assert_(KERNEL, object != nullptr); | ||
| 117 | 125 | ||
| 118 | DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), | 126 | DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), |
| 119 | object->GetName().c_str(), nano_seconds); | 127 | object->GetName().c_str(), nano_seconds); |
| 120 | 128 | ||
| 121 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); | 129 | ResultVal<bool> wait = object->WaitSynchronization(); |
| 122 | |||
| 123 | Result res = object->WaitSynchronization(&wait); | ||
| 124 | 130 | ||
| 125 | // Check for next thread to schedule | 131 | // Check for next thread to schedule |
| 126 | if (wait) { | 132 | if (wait.Succeeded() && *wait) { |
| 127 | HLE::Reschedule(__func__); | 133 | HLE::Reschedule(__func__); |
| 128 | return 0; | ||
| 129 | } | 134 | } |
| 130 | 135 | ||
| 131 | return res; | 136 | return wait.Code().raw; |
| 132 | } | 137 | } |
| 133 | 138 | ||
| 134 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 139 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| @@ -143,20 +148,21 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 143 | 148 | ||
| 144 | // Iterate through each handle, synchronize kernel object | 149 | // Iterate through each handle, synchronize kernel object |
| 145 | for (s32 i = 0; i < handle_count; i++) { | 150 | for (s32 i = 0; i < handle_count; i++) { |
| 146 | bool wait = false; | 151 | if (!Kernel::g_object_pool.IsValid(handles[i])) { |
| 152 | return InvalidHandle(ErrorModule::Kernel).raw; | ||
| 153 | } | ||
| 147 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]); | 154 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]); |
| 148 | 155 | ||
| 149 | _assert_msg_(KERNEL, (object != nullptr), "called handle=0x%08X, but kernel object " | ||
| 150 | "is nullptr!", handles[i]); | ||
| 151 | |||
| 152 | DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), | 156 | DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), |
| 153 | object->GetName().c_str()); | 157 | object->GetName().c_str()); |
| 154 | 158 | ||
| 155 | Result res = object->WaitSynchronization(&wait); | 159 | // TODO(yuriks): Verify how the real function behaves when an error happens here |
| 160 | ResultVal<bool> wait_result = object->WaitSynchronization(); | ||
| 161 | bool wait = wait_result.Succeeded() && *wait_result; | ||
| 156 | 162 | ||
| 157 | if (!wait && !wait_all) { | 163 | if (!wait && !wait_all) { |
| 158 | *out = i; | 164 | *out = i; |
| 159 | return 0; | 165 | return RESULT_SUCCESS.raw; |
| 160 | } else { | 166 | } else { |
| 161 | unlock_all = false; | 167 | unlock_all = false; |
| 162 | } | 168 | } |
| @@ -164,13 +170,13 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 164 | 170 | ||
| 165 | if (wait_all && unlock_all) { | 171 | if (wait_all && unlock_all) { |
| 166 | *out = handle_count; | 172 | *out = handle_count; |
| 167 | return 0; | 173 | return RESULT_SUCCESS.raw; |
| 168 | } | 174 | } |
| 169 | 175 | ||
| 170 | // Check for next thread to schedule | 176 | // Check for next thread to schedule |
| 171 | HLE::Reschedule(__func__); | 177 | HLE::Reschedule(__func__); |
| 172 | 178 | ||
| 173 | return 0; | 179 | return RESULT_SUCCESS.raw; |
| 174 | } | 180 | } |
| 175 | 181 | ||
| 176 | /// Create an address arbiter (to allocate access to shared resources) | 182 | /// Create an address arbiter (to allocate access to shared resources) |
| @@ -183,8 +189,8 @@ static Result CreateAddressArbiter(u32* arbiter) { | |||
| 183 | 189 | ||
| 184 | /// Arbitrate address | 190 | /// Arbitrate address |
| 185 | static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { | 191 | static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { |
| 186 | return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), address, | 192 | return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), |
| 187 | value); | 193 | address, value).raw; |
| 188 | } | 194 | } |
| 189 | 195 | ||
| 190 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 196 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| @@ -246,13 +252,16 @@ static u32 ExitThread() { | |||
| 246 | 252 | ||
| 247 | /// Gets the priority for the specified thread | 253 | /// Gets the priority for the specified thread |
| 248 | static Result GetThreadPriority(s32* priority, Handle handle) { | 254 | static Result GetThreadPriority(s32* priority, Handle handle) { |
| 249 | *priority = Kernel::GetThreadPriority(handle); | 255 | ResultVal<u32> priority_result = Kernel::GetThreadPriority(handle); |
| 250 | return 0; | 256 | if (priority_result.Succeeded()) { |
| 257 | *priority = *priority_result; | ||
| 258 | } | ||
| 259 | return priority_result.Code().raw; | ||
| 251 | } | 260 | } |
| 252 | 261 | ||
| 253 | /// Sets the priority for the specified thread | 262 | /// Sets the priority for the specified thread |
| 254 | static Result SetThreadPriority(Handle handle, s32 priority) { | 263 | static Result SetThreadPriority(Handle handle, s32 priority) { |
| 255 | return Kernel::SetThreadPriority(handle, priority); | 264 | return Kernel::SetThreadPriority(handle, priority).raw; |
| 256 | } | 265 | } |
| 257 | 266 | ||
| 258 | /// Create a mutex | 267 | /// Create a mutex |
| @@ -266,9 +275,8 @@ static Result CreateMutex(Handle* mutex, u32 initial_locked) { | |||
| 266 | /// Release a mutex | 275 | /// Release a mutex |
| 267 | static Result ReleaseMutex(Handle handle) { | 276 | static Result ReleaseMutex(Handle handle) { |
| 268 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); | 277 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); |
| 269 | _assert_msg_(KERNEL, (handle != 0), "called, but handle is nullptr!"); | 278 | ResultCode res = Kernel::ReleaseMutex(handle); |
| 270 | Kernel::ReleaseMutex(handle); | 279 | return res.raw; |
| 271 | return 0; | ||
| 272 | } | 280 | } |
| 273 | 281 | ||
| 274 | /// Get current thread ID | 282 | /// Get current thread ID |
| @@ -310,16 +318,14 @@ static Result DuplicateHandle(Handle* out, Handle handle) { | |||
| 310 | 318 | ||
| 311 | /// Signals an event | 319 | /// Signals an event |
| 312 | static Result SignalEvent(Handle evt) { | 320 | static Result SignalEvent(Handle evt) { |
| 313 | Result res = Kernel::SignalEvent(evt); | ||
| 314 | DEBUG_LOG(SVC, "called event=0x%08X", evt); | 321 | DEBUG_LOG(SVC, "called event=0x%08X", evt); |
| 315 | return res; | 322 | return Kernel::SignalEvent(evt).raw; |
| 316 | } | 323 | } |
| 317 | 324 | ||
| 318 | /// Clears an event | 325 | /// Clears an event |
| 319 | static Result ClearEvent(Handle evt) { | 326 | static Result ClearEvent(Handle evt) { |
| 320 | Result res = Kernel::ClearEvent(evt); | ||
| 321 | DEBUG_LOG(SVC, "called event=0x%08X", evt); | 327 | DEBUG_LOG(SVC, "called event=0x%08X", evt); |
| 322 | return res; | 328 | return Kernel::ClearEvent(evt).raw; |
| 323 | } | 329 | } |
| 324 | 330 | ||
| 325 | /// Sleep the current thread | 331 | /// Sleep the current thread |