diff options
| author | 2014-12-29 19:47:41 -0800 | |
|---|---|---|
| committer | 2014-12-29 19:47:41 -0800 | |
| commit | 8ba9ac0f74abb0408a26207a76a0c1808bad8de0 (patch) | |
| tree | f1c7c3393fa726435b5b90bf335567c93e528ef1 /src/core/hle/svc.cpp | |
| parent | Add comment regarding __WIN32__ in SkyEye code (diff) | |
| parent | Merge pull request #367 from bunnei/usat_ssat (diff) | |
| download | yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.gz yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.xz yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.zip | |
Fix merge conflicts
Diffstat (limited to 'src/core/hle/svc.cpp')
| -rw-r--r-- | src/core/hle/svc.cpp | 126 |
1 files changed, 70 insertions, 56 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 87d768856..25944fc68 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | 1 | // Copyright 2014 Citra Emulator Project |
| 2 | // Licensed under GPLv2 | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <map> | 5 | #include <map> |
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "core/hle/kernel/address_arbiter.h" | 12 | #include "core/hle/kernel/address_arbiter.h" |
| 13 | #include "core/hle/kernel/event.h" | 13 | #include "core/hle/kernel/event.h" |
| 14 | #include "core/hle/kernel/mutex.h" | 14 | #include "core/hle/kernel/mutex.h" |
| 15 | #include "core/hle/kernel/semaphore.h" | ||
| 15 | #include "core/hle/kernel/shared_memory.h" | 16 | #include "core/hle/kernel/shared_memory.h" |
| 16 | #include "core/hle/kernel/thread.h" | 17 | #include "core/hle/kernel/thread.h" |
| 17 | 18 | ||
| @@ -31,7 +32,7 @@ enum ControlMemoryOperation { | |||
| 31 | 32 | ||
| 32 | /// Map application or GSP heap memory | 33 | /// Map application or GSP heap memory |
| 33 | static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { | 34 | static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { |
| 34 | DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", | 35 | LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", |
| 35 | operation, addr0, addr1, size, permissions); | 36 | operation, addr0, addr1, size, permissions); |
| 36 | 37 | ||
| 37 | switch (operation) { | 38 | switch (operation) { |
| @@ -43,19 +44,19 @@ static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, | |||
| 43 | 44 | ||
| 44 | // Map GSP heap memory | 45 | // Map GSP heap memory |
| 45 | case MEMORY_OPERATION_GSP_HEAP: | 46 | case MEMORY_OPERATION_GSP_HEAP: |
| 46 | *out_addr = Memory::MapBlock_HeapGSP(size, operation, permissions); | 47 | *out_addr = Memory::MapBlock_HeapLinear(size, operation, permissions); |
| 47 | break; | 48 | break; |
| 48 | 49 | ||
| 49 | // Unknown ControlMemory operation | 50 | // Unknown ControlMemory operation |
| 50 | default: | 51 | default: |
| 51 | ERROR_LOG(SVC, "unknown operation=0x%08X", operation); | 52 | LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation); |
| 52 | } | 53 | } |
| 53 | return 0; | 54 | return 0; |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | /// Maps a memory block to specified address | 57 | /// Maps a memory block to specified address |
| 57 | static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { | 58 | static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { |
| 58 | DEBUG_LOG(SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", | 59 | LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", |
| 59 | handle, addr, permissions, other_permissions); | 60 | handle, addr, permissions, other_permissions); |
| 60 | 61 | ||
| 61 | Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions); | 62 | Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions); |
| @@ -63,12 +64,16 @@ static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other | |||
| 63 | case Kernel::MemoryPermission::Read: | 64 | case Kernel::MemoryPermission::Read: |
| 64 | case Kernel::MemoryPermission::Write: | 65 | case Kernel::MemoryPermission::Write: |
| 65 | case Kernel::MemoryPermission::ReadWrite: | 66 | case Kernel::MemoryPermission::ReadWrite: |
| 67 | case Kernel::MemoryPermission::Execute: | ||
| 68 | case Kernel::MemoryPermission::ReadExecute: | ||
| 69 | case Kernel::MemoryPermission::WriteExecute: | ||
| 70 | case Kernel::MemoryPermission::ReadWriteExecute: | ||
| 66 | case Kernel::MemoryPermission::DontCare: | 71 | case Kernel::MemoryPermission::DontCare: |
| 67 | Kernel::MapSharedMemory(handle, addr, permissions_type, | 72 | Kernel::MapSharedMemory(handle, addr, permissions_type, |
| 68 | static_cast<Kernel::MemoryPermission>(other_permissions)); | 73 | static_cast<Kernel::MemoryPermission>(other_permissions)); |
| 69 | break; | 74 | break; |
| 70 | default: | 75 | default: |
| 71 | ERROR_LOG(OSHLE, "unknown permissions=0x%08X", permissions); | 76 | LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); |
| 72 | } | 77 | } |
| 73 | return 0; | 78 | return 0; |
| 74 | } | 79 | } |
| @@ -77,7 +82,7 @@ static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other | |||
| 77 | static Result ConnectToPort(Handle* out, const char* port_name) { | 82 | static Result ConnectToPort(Handle* out, const char* port_name) { |
| 78 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); | 83 | Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); |
| 79 | 84 | ||
| 80 | DEBUG_LOG(SVC, "called port_name=%s", port_name); | 85 | LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); |
| 81 | _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!"); | 86 | _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!"); |
| 82 | 87 | ||
| 83 | *out = service->GetHandle(); | 88 | *out = service->GetHandle(); |
| @@ -87,17 +92,14 @@ static Result ConnectToPort(Handle* out, const char* port_name) { | |||
| 87 | 92 | ||
| 88 | /// Synchronize to an OS service | 93 | /// Synchronize to an OS service |
| 89 | static Result SendSyncRequest(Handle handle) { | 94 | 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, | 95 | Kernel::Session* session = Kernel::g_handle_table.Get<Kernel::Session>(handle); |
| 91 | // so we are forced to use GetFast and manually verify the handle. | 96 | if (session == nullptr) { |
| 92 | if (!Kernel::g_object_pool.IsValid(handle)) { | ||
| 93 | return InvalidHandle(ErrorModule::Kernel).raw; | 97 | return InvalidHandle(ErrorModule::Kernel).raw; |
| 94 | } | 98 | } |
| 95 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); | ||
| 96 | 99 | ||
| 97 | _assert_msg_(KERNEL, (object != nullptr), "called, but kernel object is nullptr!"); | 100 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); |
| 98 | DEBUG_LOG(SVC, "called handle=0x%08X(%s)", handle, object->GetTypeName().c_str()); | ||
| 99 | 101 | ||
| 100 | ResultVal<bool> wait = object->SyncRequest(); | 102 | ResultVal<bool> wait = session->SyncRequest(); |
| 101 | if (wait.Succeeded() && *wait) { | 103 | if (wait.Succeeded() && *wait) { |
| 102 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? | 104 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? |
| 103 | } | 105 | } |
| @@ -108,7 +110,7 @@ static Result SendSyncRequest(Handle handle) { | |||
| 108 | /// Close a handle | 110 | /// Close a handle |
| 109 | static Result CloseHandle(Handle handle) { | 111 | static Result CloseHandle(Handle handle) { |
| 110 | // ImplementMe | 112 | // ImplementMe |
| 111 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); | 113 | LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); |
| 112 | return 0; | 114 | return 0; |
| 113 | } | 115 | } |
| 114 | 116 | ||
| @@ -117,13 +119,11 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { | |||
| 117 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this | 119 | // TODO(bunnei): Do something with nano_seconds, currently ignoring this |
| 118 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated | 120 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated |
| 119 | 121 | ||
| 120 | if (!Kernel::g_object_pool.IsValid(handle)) { | 122 | Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle); |
| 123 | if (object == nullptr) | ||
| 121 | return InvalidHandle(ErrorModule::Kernel).raw; | 124 | return InvalidHandle(ErrorModule::Kernel).raw; |
| 122 | } | ||
| 123 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handle); | ||
| 124 | _dbg_assert_(KERNEL, object != nullptr); | ||
| 125 | 125 | ||
| 126 | DEBUG_LOG(SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), | 126 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), |
| 127 | object->GetName().c_str(), nano_seconds); | 127 | object->GetName().c_str(), nano_seconds); |
| 128 | 128 | ||
| 129 | ResultVal<bool> wait = object->WaitSynchronization(); | 129 | ResultVal<bool> wait = object->WaitSynchronization(); |
| @@ -143,17 +143,16 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 143 | bool unlock_all = true; | 143 | bool unlock_all = true; |
| 144 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated | 144 | bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated |
| 145 | 145 | ||
| 146 | DEBUG_LOG(SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld", | 146 | LOG_TRACE(Kernel_SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld", |
| 147 | handle_count, (wait_all ? "true" : "false"), nano_seconds); | 147 | handle_count, (wait_all ? "true" : "false"), nano_seconds); |
| 148 | 148 | ||
| 149 | // Iterate through each handle, synchronize kernel object | 149 | // Iterate through each handle, synchronize kernel object |
| 150 | for (s32 i = 0; i < handle_count; i++) { | 150 | for (s32 i = 0; i < handle_count; i++) { |
| 151 | if (!Kernel::g_object_pool.IsValid(handles[i])) { | 151 | Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[i]); |
| 152 | if (object == nullptr) | ||
| 152 | return InvalidHandle(ErrorModule::Kernel).raw; | 153 | return InvalidHandle(ErrorModule::Kernel).raw; |
| 153 | } | ||
| 154 | Kernel::Object* object = Kernel::g_object_pool.GetFast<Kernel::Object>(handles[i]); | ||
| 155 | 154 | ||
| 156 | DEBUG_LOG(SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), | 155 | LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), |
| 157 | object->GetName().c_str()); | 156 | object->GetName().c_str()); |
| 158 | 157 | ||
| 159 | // TODO(yuriks): Verify how the real function behaves when an error happens here | 158 | // TODO(yuriks): Verify how the real function behaves when an error happens here |
| @@ -181,7 +180,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 181 | 180 | ||
| 182 | /// Create an address arbiter (to allocate access to shared resources) | 181 | /// Create an address arbiter (to allocate access to shared resources) |
| 183 | static Result CreateAddressArbiter(u32* arbiter) { | 182 | static Result CreateAddressArbiter(u32* arbiter) { |
| 184 | DEBUG_LOG(SVC, "called"); | 183 | LOG_TRACE(Kernel_SVC, "called"); |
| 185 | Handle handle = Kernel::CreateAddressArbiter(); | 184 | Handle handle = Kernel::CreateAddressArbiter(); |
| 186 | *arbiter = handle; | 185 | *arbiter = handle; |
| 187 | return 0; | 186 | return 0; |
| @@ -189,13 +188,15 @@ static Result CreateAddressArbiter(u32* arbiter) { | |||
| 189 | 188 | ||
| 190 | /// Arbitrate address | 189 | /// Arbitrate address |
| 191 | static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { | 190 | static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { |
| 191 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter, | ||
| 192 | address, type, value); | ||
| 192 | return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), | 193 | return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), |
| 193 | address, value).raw; | 194 | address, value).raw; |
| 194 | } | 195 | } |
| 195 | 196 | ||
| 196 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 197 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| 197 | static void OutputDebugString(const char* string) { | 198 | static void OutputDebugString(const char* string) { |
| 198 | OS_LOG(SVC, "%s", string); | 199 | LOG_DEBUG(Debug_Emulated, "%s", string); |
| 199 | } | 200 | } |
| 200 | 201 | ||
| 201 | /// Get resource limit | 202 | /// Get resource limit |
| @@ -204,14 +205,14 @@ static Result GetResourceLimit(Handle* resource_limit, Handle process) { | |||
| 204 | // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for | 205 | // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for |
| 205 | // the current KThread. | 206 | // the current KThread. |
| 206 | *resource_limit = 0xDEADBEEF; | 207 | *resource_limit = 0xDEADBEEF; |
| 207 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called process=0x%08X", process); | 208 | LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process); |
| 208 | return 0; | 209 | return 0; |
| 209 | } | 210 | } |
| 210 | 211 | ||
| 211 | /// Get resource limit current values | 212 | /// Get resource limit current values |
| 212 | static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, | 213 | static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, |
| 213 | s32 name_count) { | 214 | s32 name_count) { |
| 214 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", | 215 | LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", |
| 215 | resource_limit, names, name_count); | 216 | resource_limit, names, name_count); |
| 216 | Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now | 217 | Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now |
| 217 | return 0; | 218 | return 0; |
| @@ -232,7 +233,7 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top | |||
| 232 | 233 | ||
| 233 | Core::g_app_core->SetReg(1, thread); | 234 | Core::g_app_core->SetReg(1, thread); |
| 234 | 235 | ||
| 235 | DEBUG_LOG(SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | 236 | LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " |
| 236 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, | 237 | "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, |
| 237 | name.c_str(), arg, stack_top, priority, processor_id, thread); | 238 | name.c_str(), arg, stack_top, priority, processor_id, thread); |
| 238 | 239 | ||
| @@ -243,7 +244,7 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top | |||
| 243 | static u32 ExitThread() { | 244 | static u32 ExitThread() { |
| 244 | Handle thread = Kernel::GetCurrentThreadHandle(); | 245 | Handle thread = Kernel::GetCurrentThreadHandle(); |
| 245 | 246 | ||
| 246 | DEBUG_LOG(SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C | 247 | LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C |
| 247 | 248 | ||
| 248 | Kernel::StopThread(thread, __func__); | 249 | Kernel::StopThread(thread, __func__); |
| 249 | HLE::Reschedule(__func__); | 250 | HLE::Reschedule(__func__); |
| @@ -267,70 +268,83 @@ static Result SetThreadPriority(Handle handle, s32 priority) { | |||
| 267 | /// Create a mutex | 268 | /// Create a mutex |
| 268 | static Result CreateMutex(Handle* mutex, u32 initial_locked) { | 269 | static Result CreateMutex(Handle* mutex, u32 initial_locked) { |
| 269 | *mutex = Kernel::CreateMutex((initial_locked != 0)); | 270 | *mutex = Kernel::CreateMutex((initial_locked != 0)); |
| 270 | DEBUG_LOG(SVC, "called initial_locked=%s : created handle=0x%08X", | 271 | LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", |
| 271 | initial_locked ? "true" : "false", *mutex); | 272 | initial_locked ? "true" : "false", *mutex); |
| 272 | return 0; | 273 | return 0; |
| 273 | } | 274 | } |
| 274 | 275 | ||
| 275 | /// Release a mutex | 276 | /// Release a mutex |
| 276 | static Result ReleaseMutex(Handle handle) { | 277 | static Result ReleaseMutex(Handle handle) { |
| 277 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); | 278 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle); |
| 278 | ResultCode res = Kernel::ReleaseMutex(handle); | 279 | ResultCode res = Kernel::ReleaseMutex(handle); |
| 279 | return res.raw; | 280 | return res.raw; |
| 280 | } | 281 | } |
| 281 | 282 | ||
| 282 | /// Get current thread ID | 283 | /// Get the ID for the specified thread. |
| 283 | static Result GetThreadId(u32* thread_id, Handle thread) { | 284 | static Result GetThreadId(u32* thread_id, Handle handle) { |
| 284 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); | 285 | LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); |
| 285 | return 0; | 286 | ResultCode result = Kernel::GetThreadId(thread_id, handle); |
| 287 | return result.raw; | ||
| 288 | } | ||
| 289 | |||
| 290 | /// Creates a semaphore | ||
| 291 | static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { | ||
| 292 | ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); | ||
| 293 | LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", | ||
| 294 | initial_count, max_count, *semaphore); | ||
| 295 | return res.raw; | ||
| 296 | } | ||
| 297 | |||
| 298 | /// Releases a certain number of slots in a semaphore | ||
| 299 | static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { | ||
| 300 | LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); | ||
| 301 | ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); | ||
| 302 | return res.raw; | ||
| 286 | } | 303 | } |
| 287 | 304 | ||
| 288 | /// Query memory | 305 | /// Query memory |
| 289 | static Result QueryMemory(void* info, void* out, u32 addr) { | 306 | static Result QueryMemory(void* info, void* out, u32 addr) { |
| 290 | ERROR_LOG(SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); | 307 | LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); |
| 291 | return 0; | 308 | return 0; |
| 292 | } | 309 | } |
| 293 | 310 | ||
| 294 | /// Create an event | 311 | /// Create an event |
| 295 | static Result CreateEvent(Handle* evt, u32 reset_type) { | 312 | static Result CreateEvent(Handle* evt, u32 reset_type) { |
| 296 | *evt = Kernel::CreateEvent((ResetType)reset_type); | 313 | *evt = Kernel::CreateEvent((ResetType)reset_type); |
| 297 | DEBUG_LOG(SVC, "called reset_type=0x%08X : created handle=0x%08X", | 314 | LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", |
| 298 | reset_type, *evt); | 315 | reset_type, *evt); |
| 299 | return 0; | 316 | return 0; |
| 300 | } | 317 | } |
| 301 | 318 | ||
| 302 | /// Duplicates a kernel handle | 319 | /// Duplicates a kernel handle |
| 303 | static Result DuplicateHandle(Handle* out, Handle handle) { | 320 | static Result DuplicateHandle(Handle* out, Handle handle) { |
| 304 | DEBUG_LOG(SVC, "called handle=0x%08X", handle); | 321 | ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle); |
| 305 | 322 | if (out_h.Succeeded()) { | |
| 306 | // Translate kernel handles -> real handles | 323 | *out = *out_h; |
| 307 | if (handle == Kernel::CurrentThread) { | 324 | LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); |
| 308 | handle = Kernel::GetCurrentThreadHandle(); | ||
| 309 | } | 325 | } |
| 310 | _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), | 326 | return out_h.Code().raw; |
| 311 | "(UNIMPLEMENTED) process handle duplication!"); | ||
| 312 | |||
| 313 | // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate. | ||
| 314 | *out = handle; | ||
| 315 | |||
| 316 | return 0; | ||
| 317 | } | 327 | } |
| 318 | 328 | ||
| 319 | /// Signals an event | 329 | /// Signals an event |
| 320 | static Result SignalEvent(Handle evt) { | 330 | static Result SignalEvent(Handle evt) { |
| 321 | DEBUG_LOG(SVC, "called event=0x%08X", evt); | 331 | LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); |
| 322 | return Kernel::SignalEvent(evt).raw; | 332 | return Kernel::SignalEvent(evt).raw; |
| 323 | } | 333 | } |
| 324 | 334 | ||
| 325 | /// Clears an event | 335 | /// Clears an event |
| 326 | static Result ClearEvent(Handle evt) { | 336 | static Result ClearEvent(Handle evt) { |
| 327 | DEBUG_LOG(SVC, "called event=0x%08X", evt); | 337 | LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); |
| 328 | return Kernel::ClearEvent(evt).raw; | 338 | return Kernel::ClearEvent(evt).raw; |
| 329 | } | 339 | } |
| 330 | 340 | ||
| 331 | /// Sleep the current thread | 341 | /// Sleep the current thread |
| 332 | static void SleepThread(s64 nanoseconds) { | 342 | static void SleepThread(s64 nanoseconds) { |
| 333 | DEBUG_LOG(SVC, "called nanoseconds=%lld", nanoseconds); | 343 | LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); |
| 344 | |||
| 345 | // Sleep current thread and check for next thread to schedule | ||
| 346 | Kernel::WaitCurrentThread(WAITTYPE_SLEEP); | ||
| 347 | HLE::Reschedule(__func__); | ||
| 334 | } | 348 | } |
| 335 | 349 | ||
| 336 | /// This returns the total CPU ticks elapsed since the CPU was powered-on | 350 | /// This returns the total CPU ticks elapsed since the CPU was powered-on |
| @@ -360,8 +374,8 @@ const HLE::FunctionDef SVC_Table[] = { | |||
| 360 | {0x12, nullptr, "Run"}, | 374 | {0x12, nullptr, "Run"}, |
| 361 | {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, | 375 | {0x13, HLE::Wrap<CreateMutex>, "CreateMutex"}, |
| 362 | {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, | 376 | {0x14, HLE::Wrap<ReleaseMutex>, "ReleaseMutex"}, |
| 363 | {0x15, nullptr, "CreateSemaphore"}, | 377 | {0x15, HLE::Wrap<CreateSemaphore>, "CreateSemaphore"}, |
| 364 | {0x16, nullptr, "ReleaseSemaphore"}, | 378 | {0x16, HLE::Wrap<ReleaseSemaphore>, "ReleaseSemaphore"}, |
| 365 | {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, | 379 | {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, |
| 366 | {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, | 380 | {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, |
| 367 | {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, | 381 | {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, |