summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2015-01-30 15:00:17 +0100
committerGravatar Tony Wasserka2015-01-30 15:00:17 +0100
commit28702cbfeb1fe21109f8b1efa189785594319b78 (patch)
tree64e4b1ec43b7699fe1a6ab1be1c688b6d63c0d75 /src/core/hle/svc.cpp
parentMerge pull request #412 from purpasmart96/svc_table_cleanup (diff)
parentKernel: Mark all appropriate kernel objects as "final" (diff)
downloadyuzu-28702cbfeb1fe21109f8b1efa189785594319b78.tar.gz
yuzu-28702cbfeb1fe21109f8b1efa189785594319b78.tar.xz
yuzu-28702cbfeb1fe21109f8b1efa189785594319b78.zip
Merge pull request #503 from yuriks/kernel-lifetime4
Kernel Lifetime Reform Pt. 4
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp296
1 files changed, 187 insertions, 109 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 3d743f125..88813c2ce 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -26,6 +26,7 @@
26// Namespace SVC 26// Namespace SVC
27 27
28using Kernel::SharedPtr; 28using Kernel::SharedPtr;
29using Kernel::ERR_INVALID_HANDLE;
29 30
30namespace SVC { 31namespace SVC {
31 32
@@ -38,7 +39,7 @@ enum ControlMemoryOperation {
38}; 39};
39 40
40/// Map application or GSP heap memory 41/// Map application or GSP heap memory
41static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { 42static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
42 LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", 43 LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X",
43 operation, addr0, addr1, size, permissions); 44 operation, addr0, addr1, size, permissions);
44 45
@@ -58,35 +59,42 @@ static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1,
58 default: 59 default:
59 LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation); 60 LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation);
60 } 61 }
61 return 0; 62 return RESULT_SUCCESS;
62} 63}
63 64
64/// Maps a memory block to specified address 65/// Maps a memory block to specified address
65static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { 66static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) {
67 using Kernel::SharedMemory;
68 using Kernel::MemoryPermission;
69
66 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 70 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
67 handle, addr, permissions, other_permissions); 71 handle, addr, permissions, other_permissions);
68 72
69 Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions); 73 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
74 if (shared_memory == nullptr)
75 return ERR_INVALID_HANDLE;
76
77 MemoryPermission permissions_type = static_cast<MemoryPermission>(permissions);
70 switch (permissions_type) { 78 switch (permissions_type) {
71 case Kernel::MemoryPermission::Read: 79 case MemoryPermission::Read:
72 case Kernel::MemoryPermission::Write: 80 case MemoryPermission::Write:
73 case Kernel::MemoryPermission::ReadWrite: 81 case MemoryPermission::ReadWrite:
74 case Kernel::MemoryPermission::Execute: 82 case MemoryPermission::Execute:
75 case Kernel::MemoryPermission::ReadExecute: 83 case MemoryPermission::ReadExecute:
76 case Kernel::MemoryPermission::WriteExecute: 84 case MemoryPermission::WriteExecute:
77 case Kernel::MemoryPermission::ReadWriteExecute: 85 case MemoryPermission::ReadWriteExecute:
78 case Kernel::MemoryPermission::DontCare: 86 case MemoryPermission::DontCare:
79 Kernel::MapSharedMemory(handle, addr, permissions_type, 87 shared_memory->Map(addr, permissions_type,
80 static_cast<Kernel::MemoryPermission>(other_permissions)); 88 static_cast<MemoryPermission>(other_permissions));
81 break; 89 break;
82 default: 90 default:
83 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 91 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
84 } 92 }
85 return 0; 93 return RESULT_SUCCESS;
86} 94}
87 95
88/// Connect to an OS service given the port name, returns the handle to the port to out 96/// Connect to an OS service given the port name, returns the handle to the port to out
89static Result ConnectToPort(Handle* out, const char* port_name) { 97static ResultCode ConnectToPort(Handle* out, const char* port_name) {
90 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); 98 Service::Interface* service = Service::g_manager->FetchFromPortName(port_name);
91 99
92 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); 100 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name);
@@ -94,33 +102,33 @@ static Result ConnectToPort(Handle* out, const char* port_name) {
94 102
95 *out = service->GetHandle(); 103 *out = service->GetHandle();
96 104
97 return 0; 105 return RESULT_SUCCESS;
98} 106}
99 107
100/// Synchronize to an OS service 108/// Synchronize to an OS service
101static Result SendSyncRequest(Handle handle) { 109static ResultCode SendSyncRequest(Handle handle) {
102 SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle); 110 SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle);
103 if (session == nullptr) { 111 if (session == nullptr) {
104 return InvalidHandle(ErrorModule::Kernel).raw; 112 return ERR_INVALID_HANDLE;
105 } 113 }
106 114
107 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); 115 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str());
108 116
109 return session->SyncRequest().Code().raw; 117 return session->SyncRequest().Code();
110} 118}
111 119
112/// Close a handle 120/// Close a handle
113static Result CloseHandle(Handle handle) { 121static ResultCode CloseHandle(Handle handle) {
114 // ImplementMe 122 // ImplementMe
115 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); 123 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle);
116 return 0; 124 return RESULT_SUCCESS;
117} 125}
118 126
119/// Wait for a handle to synchronize, timeout after the specified nanoseconds 127/// Wait for a handle to synchronize, timeout after the specified nanoseconds
120static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { 128static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
121 auto object = Kernel::g_handle_table.GetWaitObject(handle); 129 auto object = Kernel::g_handle_table.GetWaitObject(handle);
122 if (object == nullptr) 130 if (object == nullptr)
123 return InvalidHandle(ErrorModule::Kernel).raw; 131 return ERR_INVALID_HANDLE;
124 132
125 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, 133 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle,
126 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); 134 object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds);
@@ -137,22 +145,22 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
137 HLE::Reschedule(__func__); 145 HLE::Reschedule(__func__);
138 146
139 // NOTE: output of this SVC will be set later depending on how the thread resumes 147 // NOTE: output of this SVC will be set later depending on how the thread resumes
140 return RESULT_INVALID.raw; 148 return RESULT_INVALID;
141 } 149 }
142 150
143 object->Acquire(); 151 object->Acquire();
144 152
145 return RESULT_SUCCESS.raw; 153 return RESULT_SUCCESS;
146} 154}
147 155
148/// Wait for the given handles to synchronize, timeout after the specified nanoseconds 156/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
149static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { 157static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) {
150 bool wait_thread = !wait_all; 158 bool wait_thread = !wait_all;
151 int handle_index = 0; 159 int handle_index = 0;
152 160
153 // Check if 'handles' is invalid 161 // Check if 'handles' is invalid
154 if (handles == nullptr) 162 if (handles == nullptr)
155 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent).raw; 163 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
156 164
157 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If 165 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
158 // this happens, the running application will crash. 166 // this happens, the running application will crash.
@@ -160,7 +168,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
160 168
161 // Check if 'handle_count' is invalid 169 // Check if 'handle_count' is invalid
162 if (handle_count < 0) 170 if (handle_count < 0)
163 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage).raw; 171 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
164 172
165 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if 173 // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if
166 // necessary 174 // necessary
@@ -169,7 +177,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
169 for (int i = 0; i < handle_count; ++i) { 177 for (int i = 0; i < handle_count; ++i) {
170 auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); 178 auto object = Kernel::g_handle_table.GetWaitObject(handles[i]);
171 if (object == nullptr) 179 if (object == nullptr)
172 return InvalidHandle(ErrorModule::Kernel).raw; 180 return ERR_INVALID_HANDLE;
173 181
174 // Check if the current thread should wait on this object... 182 // Check if the current thread should wait on this object...
175 if (object->ShouldWait()) { 183 if (object->ShouldWait()) {
@@ -213,7 +221,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
213 HLE::Reschedule(__func__); 221 HLE::Reschedule(__func__);
214 222
215 // NOTE: output of this SVC will be set later depending on how the thread resumes 223 // NOTE: output of this SVC will be set later depending on how the thread resumes
216 return RESULT_INVALID.raw; 224 return RESULT_INVALID;
217 } 225 }
218 226
219 // Acquire objects if we did not wait... 227 // Acquire objects if we did not wait...
@@ -235,22 +243,32 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
235 // not seem to set it to any meaningful value. 243 // not seem to set it to any meaningful value.
236 *out = wait_all ? 0 : handle_index; 244 *out = wait_all ? 0 : handle_index;
237 245
238 return RESULT_SUCCESS.raw; 246 return RESULT_SUCCESS;
239} 247}
240 248
241/// Create an address arbiter (to allocate access to shared resources) 249/// Create an address arbiter (to allocate access to shared resources)
242static Result CreateAddressArbiter(u32* arbiter) { 250static ResultCode CreateAddressArbiter(Handle* out_handle) {
243 Handle handle = Kernel::CreateAddressArbiter(); 251 using Kernel::AddressArbiter;
244 *arbiter = handle; 252
245 return 0; 253 CASCADE_RESULT(SharedPtr<AddressArbiter> arbiter, AddressArbiter::Create());
254 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter)));
255 LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle);
256 return RESULT_SUCCESS;
246} 257}
247 258
248/// Arbitrate address 259/// Arbitrate address
249static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { 260static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) {
250 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter, 261 using Kernel::AddressArbiter;
262
263 LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle,
251 address, type, value); 264 address, type, value);
252 return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), 265
253 address, value, nanoseconds).raw; 266 SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle);
267 if (arbiter == nullptr)
268 return ERR_INVALID_HANDLE;
269
270 return arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type),
271 address, value, nanoseconds);
254} 272}
255 273
256/// Used to output a message on a debug hardware unit - does nothing on a retail unit 274/// Used to output a message on a debug hardware unit - does nothing on a retail unit
@@ -259,26 +277,26 @@ static void OutputDebugString(const char* string) {
259} 277}
260 278
261/// Get resource limit 279/// Get resource limit
262static Result GetResourceLimit(Handle* resource_limit, Handle process) { 280static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) {
263 // With regards to proceess values: 281 // With regards to proceess values:
264 // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for 282 // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for
265 // the current KThread. 283 // the current KThread.
266 *resource_limit = 0xDEADBEEF; 284 *resource_limit = 0xDEADBEEF;
267 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process); 285 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process);
268 return 0; 286 return RESULT_SUCCESS;
269} 287}
270 288
271/// Get resource limit current values 289/// Get resource limit current values
272static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, 290static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names,
273 s32 name_count) { 291 s32 name_count) {
274 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", 292 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d",
275 resource_limit, names, name_count); 293 resource_limit, names, name_count);
276 Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now 294 Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now
277 return 0; 295 return RESULT_SUCCESS;
278} 296}
279 297
280/// Creates a new thread 298/// Creates a new thread
281static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { 299static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) {
282 using Kernel::Thread; 300 using Kernel::Thread;
283 301
284 std::string name; 302 std::string name;
@@ -289,25 +307,20 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top
289 name = Common::StringFromFormat("unknown-%08x", entry_point); 307 name = Common::StringFromFormat("unknown-%08x", entry_point);
290 } 308 }
291 309
292 ResultVal<SharedPtr<Thread>> thread_res = Kernel::Thread::Create( 310 CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create(
293 name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE); 311 name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE));
294 if (thread_res.Failed()) 312 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread)));
295 return thread_res.Code().raw;
296 SharedPtr<Thread> thread = std::move(*thread_res);
297
298 // TODO(yuriks): Create new handle instead of using built-in
299 Core::g_app_core->SetReg(1, thread->GetHandle());
300 313
301 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " 314 LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
302 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, 315 "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point,
303 name.c_str(), arg, stack_top, priority, processor_id, thread->GetHandle()); 316 name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
304 317
305 if (THREADPROCESSORID_1 == processor_id) { 318 if (THREADPROCESSORID_1 == processor_id) {
306 LOG_WARNING(Kernel_SVC, 319 LOG_WARNING(Kernel_SVC,
307 "thread designated for system CPU core (UNIMPLEMENTED) will be run with app core scheduling"); 320 "thread designated for system CPU core (UNIMPLEMENTED) will be run with app core scheduling");
308 } 321 }
309 322
310 return 0; 323 return RESULT_SUCCESS;
311} 324}
312 325
313/// Called when a thread exits 326/// Called when a thread exits
@@ -319,128 +332,192 @@ static void ExitThread() {
319} 332}
320 333
321/// Gets the priority for the specified thread 334/// Gets the priority for the specified thread
322static Result GetThreadPriority(s32* priority, Handle handle) { 335static ResultCode GetThreadPriority(s32* priority, Handle handle) {
323 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 336 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
324 if (thread == nullptr) 337 if (thread == nullptr)
325 return InvalidHandle(ErrorModule::Kernel).raw; 338 return ERR_INVALID_HANDLE;
326 339
327 *priority = thread->GetPriority(); 340 *priority = thread->GetPriority();
328 return RESULT_SUCCESS.raw; 341 return RESULT_SUCCESS;
329} 342}
330 343
331/// Sets the priority for the specified thread 344/// Sets the priority for the specified thread
332static Result SetThreadPriority(Handle handle, s32 priority) { 345static ResultCode SetThreadPriority(Handle handle, s32 priority) {
333 SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 346 SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
334 if (thread == nullptr) 347 if (thread == nullptr)
335 return InvalidHandle(ErrorModule::Kernel).raw; 348 return ERR_INVALID_HANDLE;
336 349
337 thread->SetPriority(priority); 350 thread->SetPriority(priority);
338 return RESULT_SUCCESS.raw; 351 return RESULT_SUCCESS;
339} 352}
340 353
341/// Create a mutex 354/// Create a mutex
342static Result CreateMutex(Handle* mutex, u32 initial_locked) { 355static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
343 *mutex = Kernel::CreateMutex((initial_locked != 0)); 356 using Kernel::Mutex;
357
358 CASCADE_RESULT(SharedPtr<Mutex> mutex, Mutex::Create(initial_locked != 0));
359 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex)));
360
344 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", 361 LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X",
345 initial_locked ? "true" : "false", *mutex); 362 initial_locked ? "true" : "false", *out_handle);
346 return 0; 363 return RESULT_SUCCESS;
347} 364}
348 365
349/// Release a mutex 366/// Release a mutex
350static Result ReleaseMutex(Handle handle) { 367static ResultCode ReleaseMutex(Handle handle) {
368 using Kernel::Mutex;
369
351 LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle); 370 LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle);
352 ResultCode res = Kernel::ReleaseMutex(handle); 371
353 return res.raw; 372 SharedPtr<Mutex> mutex = Kernel::g_handle_table.Get<Mutex>(handle);
373 if (mutex == nullptr)
374 return ERR_INVALID_HANDLE;
375
376 mutex->Release();
377 return RESULT_SUCCESS;
354} 378}
355 379
356/// Get the ID for the specified thread. 380/// Get the ID for the specified thread.
357static Result GetThreadId(u32* thread_id, Handle handle) { 381static ResultCode GetThreadId(u32* thread_id, Handle handle) {
358 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); 382 LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle);
359 383
360 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 384 const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
361 if (thread == nullptr) 385 if (thread == nullptr)
362 return InvalidHandle(ErrorModule::Kernel).raw; 386 return ERR_INVALID_HANDLE;
363 387
364 *thread_id = thread->GetThreadId(); 388 *thread_id = thread->GetThreadId();
365 return RESULT_SUCCESS.raw; 389 return RESULT_SUCCESS;
366} 390}
367 391
368/// Creates a semaphore 392/// Creates a semaphore
369static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { 393static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
370 ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); 394 using Kernel::Semaphore;
395
396 CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count));
397 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore)));
398
371 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", 399 LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X",
372 initial_count, max_count, *semaphore); 400 initial_count, max_count, *out_handle);
373 return res.raw; 401 return RESULT_SUCCESS;
374} 402}
375 403
376/// Releases a certain number of slots in a semaphore 404/// Releases a certain number of slots in a semaphore
377static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { 405static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
378 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); 406 using Kernel::Semaphore;
379 ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); 407
380 return res.raw; 408 LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle);
409
410 SharedPtr<Semaphore> semaphore = Kernel::g_handle_table.Get<Semaphore>(handle);
411 if (semaphore == nullptr)
412 return ERR_INVALID_HANDLE;
413
414 CASCADE_RESULT(*count, semaphore->Release(release_count));
415 return RESULT_SUCCESS;
381} 416}
382 417
383/// Query memory 418/// Query memory
384static Result QueryMemory(void* info, void* out, u32 addr) { 419static ResultCode QueryMemory(void* info, void* out, u32 addr) {
385 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); 420 LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr);
386 return 0; 421 return RESULT_SUCCESS;
387} 422}
388 423
389/// Create an event 424/// Create an event
390static Result CreateEvent(Handle* evt, u32 reset_type) { 425static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
391 *evt = Kernel::CreateEvent((ResetType)reset_type); 426 CASCADE_RESULT(auto evt, Kernel::Event::Create(static_cast<ResetType>(reset_type)));
427 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt)));
428
392 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 429 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
393 reset_type, *evt); 430 reset_type, *out_handle);
394 return 0; 431 return RESULT_SUCCESS;
395} 432}
396 433
397/// Duplicates a kernel handle 434/// Duplicates a kernel handle
398static Result DuplicateHandle(Handle* out, Handle handle) { 435static ResultCode DuplicateHandle(Handle* out, Handle handle) {
399 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle); 436 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle);
400 if (out_h.Succeeded()) { 437 if (out_h.Succeeded()) {
401 *out = *out_h; 438 *out = *out_h;
402 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); 439 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
403 } 440 }
404 return out_h.Code().raw; 441 return out_h.Code();
405} 442}
406 443
407/// Signals an event 444/// Signals an event
408static Result SignalEvent(Handle evt) { 445static ResultCode SignalEvent(Handle handle) {
409 LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); 446 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
447
448 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
449 if (evt == nullptr)
450 return ERR_INVALID_HANDLE;
451
452 evt->Signal();
410 HLE::Reschedule(__func__); 453 HLE::Reschedule(__func__);
411 return Kernel::SignalEvent(evt).raw; 454 return RESULT_SUCCESS;
412} 455}
413 456
414/// Clears an event 457/// Clears an event
415static Result ClearEvent(Handle evt) { 458static ResultCode ClearEvent(Handle handle) {
416 LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); 459 LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle);
417 return Kernel::ClearEvent(evt).raw; 460
461 auto evt = Kernel::g_handle_table.Get<Kernel::Event>(handle);
462 if (evt == nullptr)
463 return ERR_INVALID_HANDLE;
464
465 evt->Clear();
466 return RESULT_SUCCESS;
418} 467}
419 468
420/// Creates a timer 469/// Creates a timer
421static Result CreateTimer(Handle* handle, u32 reset_type) { 470static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
422 ResultCode res = Kernel::CreateTimer(handle, static_cast<ResetType>(reset_type)); 471 using Kernel::Timer;
472
473 CASCADE_RESULT(auto timer, Timer::Create(static_cast<ResetType>(reset_type)));
474 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer)));
475
423 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", 476 LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X",
424 reset_type, *handle); 477 reset_type, *out_handle);
425 return res.raw; 478 return RESULT_SUCCESS;
426} 479}
427 480
428/// Clears a timer 481/// Clears a timer
429static Result ClearTimer(Handle handle) { 482static ResultCode ClearTimer(Handle handle) {
483 using Kernel::Timer;
484
430 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); 485 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
431 return Kernel::ClearTimer(handle).raw; 486
487 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
488 if (timer == nullptr)
489 return ERR_INVALID_HANDLE;
490
491 timer->Clear();
492 return RESULT_SUCCESS;
432} 493}
433 494
434/// Starts a timer 495/// Starts a timer
435static Result SetTimer(Handle handle, s64 initial, s64 interval) { 496static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
497 using Kernel::Timer;
498
436 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); 499 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
437 return Kernel::SetTimer(handle, initial, interval).raw; 500
501 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
502 if (timer == nullptr)
503 return ERR_INVALID_HANDLE;
504
505 timer->Set(initial, interval);
506 return RESULT_SUCCESS;
438} 507}
439 508
440/// Cancels a timer 509/// Cancels a timer
441static Result CancelTimer(Handle handle) { 510static ResultCode CancelTimer(Handle handle) {
511 using Kernel::Timer;
512
442 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); 513 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
443 return Kernel::CancelTimer(handle).raw; 514
515 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
516 if (timer == nullptr)
517 return ERR_INVALID_HANDLE;
518
519 timer->Cancel();
520 return RESULT_SUCCESS;
444} 521}
445 522
446/// Sleep the current thread 523/// Sleep the current thread
@@ -462,15 +539,16 @@ static s64 GetSystemTick() {
462} 539}
463 540
464/// Creates a memory block at the specified address with the specified permissions and size 541/// Creates a memory block at the specified address with the specified permissions and size
465static Result CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 my_permission, 542static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission,
466 u32 other_permission) { 543 u32 other_permission) {
467 544 using Kernel::SharedMemory;
468 // TODO(Subv): Implement this function 545 // TODO(Subv): Implement this function
469 546
470 Handle shared_memory = Kernel::CreateSharedMemory(); 547 CASCADE_RESULT(auto shared_memory, SharedMemory::Create());
471 *memblock = shared_memory; 548 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
549
472 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); 550 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr);
473 return 0; 551 return RESULT_SUCCESS;
474} 552}
475 553
476const HLE::FunctionDef SVC_Table[] = { 554const HLE::FunctionDef SVC_Table[] = {