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.cpp68
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
88static Result SendSyncRequest(Handle handle) { 89static 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
111static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { 116static 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
185static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { 191static 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
248static Result GetThreadPriority(s32* priority, Handle handle) { 254static 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
254static Result SetThreadPriority(Handle handle, s32 priority) { 263static 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
267static Result ReleaseMutex(Handle handle) { 276static 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
312static Result SignalEvent(Handle evt) { 320static 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
319static Result ClearEvent(Handle evt) { 326static 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