diff options
Diffstat (limited to 'src/core/hle/svc.cpp')
| -rw-r--r-- | src/core/hle/svc.cpp | 480 |
1 files changed, 313 insertions, 167 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index d3b4483ca..34a27917f 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -26,16 +26,25 @@ // Namespace SVC using Kernel::SharedPtr; +using Kernel::ERR_INVALID_HANDLE; namespace SVC { +const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, + ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA +const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E0181E + +/// An invalid result code that is meant to be overwritten when a thread resumes from waiting +const ResultCode RESULT_INVALID(0xDEADC0DE); + enum ControlMemoryOperation { MEMORY_OPERATION_HEAP = 0x00000003, MEMORY_OPERATION_GSP_HEAP = 0x00010003, }; /// Map application or GSP heap memory -static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { +static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) { LOG_TRACE(Kernel_SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X", operation, addr0, addr1, size, permissions); @@ -55,147 +64,222 @@ static Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, default: LOG_ERROR(Kernel_SVC, "unknown operation=0x%08X", operation); } - return 0; + return RESULT_SUCCESS; } /// Maps a memory block to specified address -static Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { +static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) { + using Kernel::SharedMemory; + using Kernel::MemoryPermission; + LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", handle, addr, permissions, other_permissions); - Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions); + SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); + if (shared_memory == nullptr) + return ERR_INVALID_HANDLE; + + MemoryPermission permissions_type = static_cast<MemoryPermission>(permissions); switch (permissions_type) { - case Kernel::MemoryPermission::Read: - case Kernel::MemoryPermission::Write: - case Kernel::MemoryPermission::ReadWrite: - case Kernel::MemoryPermission::Execute: - case Kernel::MemoryPermission::ReadExecute: - case Kernel::MemoryPermission::WriteExecute: - case Kernel::MemoryPermission::ReadWriteExecute: - case Kernel::MemoryPermission::DontCare: - Kernel::MapSharedMemory(handle, addr, permissions_type, - static_cast<Kernel::MemoryPermission>(other_permissions)); + case MemoryPermission::Read: + case MemoryPermission::Write: + case MemoryPermission::ReadWrite: + case MemoryPermission::Execute: + case MemoryPermission::ReadExecute: + case MemoryPermission::WriteExecute: + case MemoryPermission::ReadWriteExecute: + case MemoryPermission::DontCare: + shared_memory->Map(addr, permissions_type, + static_cast<MemoryPermission>(other_permissions)); break; default: LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); } - return 0; + return RESULT_SUCCESS; } /// Connect to an OS service given the port name, returns the handle to the port to out -static Result ConnectToPort(Handle* out, const char* port_name) { - Service::Interface* service = Service::g_manager->FetchFromPortName(port_name); +static ResultCode ConnectToPort(Handle* out_handle, const char* port_name) { + if (port_name == nullptr) + return ERR_NOT_FOUND; + if (std::strlen(port_name) > 11) + return ERR_PORT_NAME_TOO_LONG; LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); - _assert_msg_(KERNEL, (service != nullptr), "called, but service is not implemented!"); - *out = service->GetHandle(); + auto it = Service::g_kernel_named_ports.find(port_name); + if (it == Service::g_kernel_named_ports.end()) { + LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name); + return ERR_NOT_FOUND; + } - return 0; + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(it->second)); + return RESULT_SUCCESS; } /// Synchronize to an OS service -static Result SendSyncRequest(Handle handle) { +static ResultCode SendSyncRequest(Handle handle) { SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle); if (session == nullptr) { - return InvalidHandle(ErrorModule::Kernel).raw; + return ERR_INVALID_HANDLE; } LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s)", handle, session->GetName().c_str()); - ResultVal<bool> wait = session->SyncRequest(); - if (wait.Succeeded() && *wait) { - Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? - } - - return wait.Code().raw; + return session->SyncRequest().Code(); } /// Close a handle -static Result CloseHandle(Handle handle) { - // ImplementMe - LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle); - return 0; +static ResultCode CloseHandle(Handle handle) { + LOG_TRACE(Kernel_SVC, "Closing handle 0x%08X", handle); + return Kernel::g_handle_table.Close(handle); } /// Wait for a handle to synchronize, timeout after the specified nanoseconds -static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { - // TODO(bunnei): Do something with nano_seconds, currently ignoring this - bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated - - SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handle); +static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) { + auto object = Kernel::g_handle_table.GetWaitObject(handle); if (object == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return ERR_INVALID_HANDLE; LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); - ResultVal<bool> wait = object->WaitSynchronization(); - // Check for next thread to schedule - if (wait.Succeeded() && *wait) { + if (object->ShouldWait()) { + + object->AddWaitingThread(Kernel::GetCurrentThread()); + Kernel::WaitCurrentThread_WaitSynchronization(object, false, false); + + // Create an event to wake the thread up after the specified nanosecond delay has passed + Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds); + HLE::Reschedule(__func__); + + // NOTE: output of this SVC will be set later depending on how the thread resumes + return RESULT_INVALID; } - return wait.Code().raw; + object->Acquire(); + + return RESULT_SUCCESS; } /// Wait for the given handles to synchronize, timeout after the specified nanoseconds -static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, - s64 nano_seconds) { - - // TODO(bunnei): Do something with nano_seconds, currently ignoring this - bool unlock_all = true; - bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated - - LOG_TRACE(Kernel_SVC, "called handle_count=%d, wait_all=%s, nanoseconds=%lld", - handle_count, (wait_all ? "true" : "false"), nano_seconds); - - // Iterate through each handle, synchronize kernel object - for (s32 i = 0; i < handle_count; i++) { - SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handles[i]); - if (object == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; - - LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], - object->GetTypeName().c_str(), object->GetName().c_str()); - - // TODO(yuriks): Verify how the real function behaves when an error happens here - ResultVal<bool> wait_result = object->WaitSynchronization(); - bool wait = wait_result.Succeeded() && *wait_result; - - if (!wait && !wait_all) { - *out = i; - return RESULT_SUCCESS.raw; - } else { - unlock_all = false; +static ResultCode WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, bool wait_all, s64 nano_seconds) { + bool wait_thread = !wait_all; + int handle_index = 0; + + // Check if 'handles' is invalid + if (handles == nullptr) + return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); + + // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If + // this happens, the running application will crash. + _assert_msg_(Kernel, out != nullptr, "invalid output pointer specified!"); + + // Check if 'handle_count' is invalid + if (handle_count < 0) + return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); + + // If 'handle_count' is non-zero, iterate through each handle and wait the current thread if + // necessary + if (handle_count != 0) { + bool selected = false; // True once an object has been selected + for (int i = 0; i < handle_count; ++i) { + auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); + if (object == nullptr) + return ERR_INVALID_HANDLE; + + // Check if the current thread should wait on this object... + if (object->ShouldWait()) { + + // Check we are waiting on all objects... + if (wait_all) + // Wait the thread + wait_thread = true; + } else { + // Do not wait on this object, check if this object should be selected... + if (!wait_all && !selected) { + // Do not wait the thread + wait_thread = false; + handle_index = i; + selected = true; + } + } + } + } else { + // If no handles were passed in, put the thread to sleep only when 'wait_all' is false + // NOTE: This should deadlock the current thread if no timeout was specified + if (!wait_all) { + wait_thread = true; + Kernel::WaitCurrentThread_WaitSynchronization(nullptr, true, wait_all); } } - if (wait_all && unlock_all) { - *out = handle_count; - return RESULT_SUCCESS.raw; + // If thread should wait, then set its state to waiting and then reschedule... + if (wait_thread) { + + // Actually wait the current thread on each object if we decided to wait... + for (int i = 0; i < handle_count; ++i) { + auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); + object->AddWaitingThread(Kernel::GetCurrentThread()); + Kernel::WaitCurrentThread_WaitSynchronization(object, true, wait_all); + } + + // Create an event to wake the thread up after the specified nanosecond delay has passed + Kernel::GetCurrentThread()->WakeAfterDelay(nano_seconds); + + HLE::Reschedule(__func__); + + // NOTE: output of this SVC will be set later depending on how the thread resumes + return RESULT_INVALID; } - // Check for next thread to schedule - HLE::Reschedule(__func__); + // Acquire objects if we did not wait... + for (int i = 0; i < handle_count; ++i) { + auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); + + // Acquire the object if it is not waiting... + if (!object->ShouldWait()) { + object->Acquire(); - return RESULT_SUCCESS.raw; + // If this was the first non-waiting object and 'wait_all' is false, don't acquire + // any other objects + if (!wait_all) + break; + } + } + + // TODO(bunnei): If 'wait_all' is true, this is probably wrong. However, real hardware does + // not seem to set it to any meaningful value. + *out = wait_all ? 0 : handle_index; + + return RESULT_SUCCESS; } /// Create an address arbiter (to allocate access to shared resources) -static Result CreateAddressArbiter(u32* arbiter) { - Handle handle = Kernel::CreateAddressArbiter(); - *arbiter = handle; - return 0; +static ResultCode CreateAddressArbiter(Handle* out_handle) { + using Kernel::AddressArbiter; + + SharedPtr<AddressArbiter> arbiter = AddressArbiter::Create(); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(arbiter))); + LOG_TRACE(Kernel_SVC, "returned handle=0x%08X", *out_handle); + return RESULT_SUCCESS; } /// Arbitrate address -static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, s64 nanoseconds) { - LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter, +static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 value, s64 nanoseconds) { + using Kernel::AddressArbiter; + + LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", handle, address, type, value); - return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), - address, value).raw; + + SharedPtr<AddressArbiter> arbiter = Kernel::g_handle_table.Get<AddressArbiter>(handle); + if (arbiter == nullptr) + return ERR_INVALID_HANDLE; + + return arbiter->ArbitrateAddress(static_cast<Kernel::ArbitrationType>(type), + address, value, nanoseconds); } /// Used to output a message on a debug hardware unit - does nothing on a retail unit @@ -204,26 +288,26 @@ static void OutputDebugString(const char* string) { } /// Get resource limit -static Result GetResourceLimit(Handle* resource_limit, Handle process) { +static ResultCode GetResourceLimit(Handle* resource_limit, Handle process) { // With regards to proceess values: // 0xFFFF8001 is a handle alias for the current KProcess, and 0xFFFF8000 is a handle alias for // the current KThread. *resource_limit = 0xDEADBEEF; LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called process=0x%08X", process); - return 0; + return RESULT_SUCCESS; } /// Get resource limit current values -static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, +static ResultCode GetResourceLimitCurrentValues(s64* values, Handle resource_limit, void* names, s32 name_count) { LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called resource_limit=%08X, names=%s, name_count=%d", resource_limit, names, name_count); Memory::Write32(Core::g_app_core->GetReg(0), 0); // Normmatt: Set used memory to 0 for now - return 0; + return RESULT_SUCCESS; } /// Creates a new thread -static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { +static ResultCode CreateThread(u32* out_handle, u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { using Kernel::Thread; std::string name; @@ -234,25 +318,20 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top name = Common::StringFromFormat("unknown-%08x", entry_point); } - ResultVal<SharedPtr<Thread>> thread_res = Kernel::Thread::Create( - name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE); - if (thread_res.Failed()) - return thread_res.Code().raw; - SharedPtr<Thread> thread = std::move(*thread_res); - - // TODO(yuriks): Create new handle instead of using built-in - Core::g_app_core->SetReg(1, thread->GetHandle()); + CASCADE_RESULT(SharedPtr<Thread> thread, Kernel::Thread::Create( + name, entry_point, priority, arg, processor_id, stack_top, Kernel::DEFAULT_STACK_SIZE)); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(thread))); LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, - name.c_str(), arg, stack_top, priority, processor_id, thread->GetHandle()); + name.c_str(), arg, stack_top, priority, processor_id, *out_handle); if (THREADPROCESSORID_1 == processor_id) { LOG_WARNING(Kernel_SVC, "thread designated for system CPU core (UNIMPLEMENTED) will be run with app core scheduling"); } - return 0; + return RESULT_SUCCESS; } /// Called when a thread exits @@ -264,127 +343,193 @@ static void ExitThread() { } /// Gets the priority for the specified thread -static Result GetThreadPriority(s32* priority, Handle handle) { +static ResultCode GetThreadPriority(s32* priority, Handle handle) { const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return ERR_INVALID_HANDLE; *priority = thread->GetPriority(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Sets the priority for the specified thread -static Result SetThreadPriority(Handle handle, s32 priority) { +static ResultCode SetThreadPriority(Handle handle, s32 priority) { SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return ERR_INVALID_HANDLE; thread->SetPriority(priority); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Create a mutex -static Result CreateMutex(Handle* mutex, u32 initial_locked) { - *mutex = Kernel::CreateMutex((initial_locked != 0)); +static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) { + using Kernel::Mutex; + + SharedPtr<Mutex> mutex = Mutex::Create(initial_locked != 0); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(mutex))); + LOG_TRACE(Kernel_SVC, "called initial_locked=%s : created handle=0x%08X", - initial_locked ? "true" : "false", *mutex); - return 0; + initial_locked ? "true" : "false", *out_handle); + return RESULT_SUCCESS; } /// Release a mutex -static Result ReleaseMutex(Handle handle) { +static ResultCode ReleaseMutex(Handle handle) { + using Kernel::Mutex; + LOG_TRACE(Kernel_SVC, "called handle=0x%08X", handle); - ResultCode res = Kernel::ReleaseMutex(handle); - return res.raw; + + SharedPtr<Mutex> mutex = Kernel::g_handle_table.Get<Mutex>(handle); + if (mutex == nullptr) + return ERR_INVALID_HANDLE; + + mutex->Release(); + return RESULT_SUCCESS; } /// Get the ID for the specified thread. -static Result GetThreadId(u32* thread_id, Handle handle) { +static ResultCode GetThreadId(u32* thread_id, Handle handle) { LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); if (thread == nullptr) - return InvalidHandle(ErrorModule::Kernel).raw; + return ERR_INVALID_HANDLE; *thread_id = thread->GetThreadId(); - return RESULT_SUCCESS.raw; + return RESULT_SUCCESS; } /// Creates a semaphore -static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { - ResultCode res = Kernel::CreateSemaphore(semaphore, initial_count, max_count); +static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) { + using Kernel::Semaphore; + + CASCADE_RESULT(SharedPtr<Semaphore> semaphore, Semaphore::Create(initial_count, max_count)); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(semaphore))); + LOG_TRACE(Kernel_SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", - initial_count, max_count, *semaphore); - return res.raw; + initial_count, max_count, *out_handle); + return RESULT_SUCCESS; } /// Releases a certain number of slots in a semaphore -static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { - LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); - ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); - return res.raw; +static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { + using Kernel::Semaphore; + + LOG_TRACE(Kernel_SVC, "called release_count=%d, handle=0x%08X", release_count, handle); + + SharedPtr<Semaphore> semaphore = Kernel::g_handle_table.Get<Semaphore>(handle); + if (semaphore == nullptr) + return ERR_INVALID_HANDLE; + + CASCADE_RESULT(*count, semaphore->Release(release_count)); + return RESULT_SUCCESS; } /// Query memory -static Result QueryMemory(void* info, void* out, u32 addr) { +static ResultCode QueryMemory(void* info, void* out, u32 addr) { LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); - return 0; + return RESULT_SUCCESS; } /// Create an event -static Result CreateEvent(Handle* evt, u32 reset_type) { - *evt = Kernel::CreateEvent((ResetType)reset_type); +static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) { + using Kernel::Event; + + SharedPtr<Event> evt = Kernel::Event::Create(static_cast<ResetType>(reset_type)); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(evt))); + LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", - reset_type, *evt); - return 0; + reset_type, *out_handle); + return RESULT_SUCCESS; } /// Duplicates a kernel handle -static Result DuplicateHandle(Handle* out, Handle handle) { - ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle); - if (out_h.Succeeded()) { - *out = *out_h; - LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); - } - return out_h.Code().raw; +static ResultCode DuplicateHandle(Handle* out, Handle handle) { + CASCADE_RESULT(*out, Kernel::g_handle_table.Duplicate(handle)); + LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out); + return RESULT_SUCCESS; } /// Signals an event -static Result SignalEvent(Handle evt) { - LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); - return Kernel::SignalEvent(evt).raw; +static ResultCode SignalEvent(Handle handle) { + using Kernel::Event; + LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); + + SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); + if (evt == nullptr) + return ERR_INVALID_HANDLE; + + evt->Signal(); + HLE::Reschedule(__func__); + return RESULT_SUCCESS; } /// Clears an event -static Result ClearEvent(Handle evt) { - LOG_TRACE(Kernel_SVC, "called event=0x%08X", evt); - return Kernel::ClearEvent(evt).raw; +static ResultCode ClearEvent(Handle handle) { + using Kernel::Event; + LOG_TRACE(Kernel_SVC, "called event=0x%08X", handle); + + SharedPtr<Event> evt = Kernel::g_handle_table.Get<Kernel::Event>(handle); + if (evt == nullptr) + return ERR_INVALID_HANDLE; + + evt->Clear(); + return RESULT_SUCCESS; } /// Creates a timer -static Result CreateTimer(Handle* handle, u32 reset_type) { - ResultCode res = Kernel::CreateTimer(handle, static_cast<ResetType>(reset_type)); +static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) { + using Kernel::Timer; + + SharedPtr<Timer> timer = Timer::Create(static_cast<ResetType>(reset_type)); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(timer))); + LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", - reset_type, *handle); - return res.raw; + reset_type, *out_handle); + return RESULT_SUCCESS; } /// Clears a timer -static Result ClearTimer(Handle handle) { +static ResultCode ClearTimer(Handle handle) { + using Kernel::Timer; + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); - return Kernel::ClearTimer(handle).raw; + + SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); + if (timer == nullptr) + return ERR_INVALID_HANDLE; + + timer->Clear(); + return RESULT_SUCCESS; } /// Starts a timer -static Result SetTimer(Handle handle, s64 initial, s64 interval) { +static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) { + using Kernel::Timer; + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); - return Kernel::SetTimer(handle, initial, interval).raw; + + SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); + if (timer == nullptr) + return ERR_INVALID_HANDLE; + + timer->Set(initial, interval); + return RESULT_SUCCESS; } /// Cancels a timer -static Result CancelTimer(Handle handle) { +static ResultCode CancelTimer(Handle handle) { + using Kernel::Timer; + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); - return Kernel::CancelTimer(handle).raw; + + SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); + if (timer == nullptr) + return ERR_INVALID_HANDLE; + + timer->Cancel(); + return RESULT_SUCCESS; } /// Sleep the current thread @@ -392,10 +537,10 @@ static void SleepThread(s64 nanoseconds) { LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); // Sleep current thread and check for next thread to schedule - Kernel::WaitCurrentThread(WAITTYPE_SLEEP); + Kernel::WaitCurrentThread_Sleep(); // Create an event to wake the thread up after the specified nanosecond delay has passed - Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds); + Kernel::GetCurrentThread()->WakeAfterDelay(nanoseconds); HLE::Reschedule(__func__); } @@ -406,15 +551,16 @@ static s64 GetSystemTick() { } /// Creates a memory block at the specified address with the specified permissions and size -static Result CreateMemoryBlock(Handle* memblock, u32 addr, u32 size, u32 my_permission, - u32 other_permission) { - +static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 my_permission, + u32 other_permission) { + using Kernel::SharedMemory; // TODO(Subv): Implement this function - Handle shared_memory = Kernel::CreateSharedMemory(); - *memblock = shared_memory; + SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(); + CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); + LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); - return 0; + return RESULT_SUCCESS; } const HLE::FunctionDef SVC_Table[] = { @@ -533,15 +679,15 @@ const HLE::FunctionDef SVC_Table[] = { {0x70, nullptr, "ControlProcessMemory"}, {0x71, nullptr, "MapProcessMemory"}, {0x72, nullptr, "UnmapProcessMemory"}, - {0x73, nullptr, "Unknown"}, - {0x74, nullptr, "Unknown"}, - {0x75, nullptr, "Unknown"}, + {0x73, nullptr, "CreateCodeSet"}, + {0x74, nullptr, "RandomStub"}, + {0x75, nullptr, "CreateProcess"}, {0x76, nullptr, "TerminateProcess"}, - {0x77, nullptr, "Unknown"}, + {0x77, nullptr, "SetProcessResourceLimits"}, {0x78, nullptr, "CreateResourceLimit"}, - {0x79, nullptr, "Unknown"}, - {0x7A, nullptr, "Unknown"}, - {0x7B, nullptr, "Unknown"}, + {0x79, nullptr, "SetResourceLimitValues"}, + {0x7A, nullptr, "AddCodeSegment"}, + {0x7B, nullptr, "Backdoor"}, {0x7C, nullptr, "KernelSetState"}, {0x7D, nullptr, "QueryProcessMemory"}, }; |
