diff options
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r-- | src/core/hle/svc.cpp | 122 |
1 files changed, 87 insertions, 35 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index c25409a9f..a487f757c 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -7,6 +7,7 @@ #include "common/string_util.h" #include "common/symbols.h" +#include "core/arm/arm_interface.h" #include "core/mem_map.h" #include "core/hle/kernel/address_arbiter.h" @@ -15,6 +16,7 @@ #include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/thread.h" +#include "core/hle/kernel/timer.h" #include "core/hle/function_wrappers.h" #include "core/hle/result.h" @@ -23,6 +25,8 @@ //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace SVC +using Kernel::SharedPtr; + namespace SVC { enum ControlMemoryOperation { @@ -92,7 +96,7 @@ static Result ConnectToPort(Handle* out, const char* port_name) { /// Synchronize to an OS service static Result SendSyncRequest(Handle handle) { - Kernel::Session* session = Kernel::g_handle_table.Get<Kernel::Session>(handle); + SharedPtr<Kernel::Session> session = Kernel::g_handle_table.Get<Kernel::Session>(handle); if (session == nullptr) { return InvalidHandle(ErrorModule::Kernel).raw; } @@ -116,20 +120,19 @@ static Result CloseHandle(Handle 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 - - Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle); + SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handle); if (object == nullptr) return InvalidHandle(ErrorModule::Kernel).raw; - LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), - object->GetName().c_str(), nano_seconds); + 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) { + // Create an event to wake the thread up after the specified nanosecond delay has passed + Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); HLE::Reschedule(__func__); } @@ -139,6 +142,7 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { /// 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 @@ -148,12 +152,12 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, // Iterate through each handle, synchronize kernel object for (s32 i = 0; i < handle_count; i++) { - Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[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()); + 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(); @@ -180,7 +184,6 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, /// Create an address arbiter (to allocate access to shared resources) static Result CreateAddressArbiter(u32* arbiter) { - LOG_TRACE(Kernel_SVC, "called"); Handle handle = Kernel::CreateAddressArbiter(); *arbiter = handle; return 0; @@ -191,7 +194,7 @@ static Result ArbitrateAddress(Handle arbiter, u32 address, u32 type, u32 value, LOG_TRACE(Kernel_SVC, "called handle=0x%08X, address=0x%08X, type=0x%08X, value=0x%08X", arbiter, address, type, value); return Kernel::ArbitrateAddress(arbiter, static_cast<Kernel::ArbitrationType>(type), - address, value).raw; + address, value, nanoseconds).raw; } /// Used to output a message on a debug hardware unit - does nothing on a retail unit @@ -220,6 +223,8 @@ static Result GetResourceLimitCurrentValues(s64* values, Handle resource_limit, /// Creates a new thread static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top, u32 processor_id) { + using Kernel::Thread; + std::string name; if (Symbols::HasSymbol(entry_point)) { TSymbol symbol = Symbols::GetSymbol(entry_point); @@ -228,41 +233,53 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top name = Common::StringFromFormat("unknown-%08x", entry_point); } - Handle thread = Kernel::CreateThread(name.c_str(), entry_point, priority, arg, processor_id, - stack_top); + 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); - Core::g_app_core->SetReg(1, thread); + // TODO(yuriks): Create new handle instead of using built-in + Core::g_app_core->SetReg(1, thread->GetHandle()); 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); + name.c_str(), arg, stack_top, priority, processor_id, thread->GetHandle()); + + 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; } /// Called when a thread exits -static u32 ExitThread() { - Handle thread = Kernel::GetCurrentThreadHandle(); - - LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C +static void ExitThread() { + LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); - Kernel::StopThread(thread, __func__); + Kernel::GetCurrentThread()->Stop(__func__); HLE::Reschedule(__func__); - return 0; } /// Gets the priority for the specified thread static Result GetThreadPriority(s32* priority, Handle handle) { - ResultVal<u32> priority_result = Kernel::GetThreadPriority(handle); - if (priority_result.Succeeded()) { - *priority = *priority_result; - } - return priority_result.Code().raw; + const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); + if (thread == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + *priority = thread->GetPriority(); + return RESULT_SUCCESS.raw; } /// Sets the priority for the specified thread static Result SetThreadPriority(Handle handle, s32 priority) { - return Kernel::SetThreadPriority(handle, priority).raw; + SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); + if (thread == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + thread->SetPriority(priority); + return RESULT_SUCCESS.raw; } /// Create a mutex @@ -283,8 +300,13 @@ static Result ReleaseMutex(Handle handle) { /// Get the ID for the specified thread. static Result GetThreadId(u32* thread_id, Handle handle) { LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); - ResultCode result = Kernel::GetThreadId(thread_id, handle); - return result.raw; + + const SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); + if (thread == nullptr) + return InvalidHandle(ErrorModule::Kernel).raw; + + *thread_id = thread->GetThreadId(); + return RESULT_SUCCESS.raw; } /// Creates a semaphore @@ -338,12 +360,42 @@ static Result ClearEvent(Handle evt) { return Kernel::ClearEvent(evt).raw; } +/// Creates a timer +static Result CreateTimer(Handle* handle, u32 reset_type) { + ResultCode res = Kernel::CreateTimer(handle, static_cast<ResetType>(reset_type)); + LOG_TRACE(Kernel_SVC, "called reset_type=0x%08X : created handle=0x%08X", + reset_type, *handle); + return res.raw; +} + +/// Clears a timer +static Result ClearTimer(Handle handle) { + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); + return Kernel::ClearTimer(handle).raw; +} + +/// Starts a timer +static Result SetTimer(Handle handle, s64 initial, s64 interval) { + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); + return Kernel::SetTimer(handle, initial, interval).raw; +} + +/// Cancels a timer +static Result CancelTimer(Handle handle) { + LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); + return Kernel::CancelTimer(handle).raw; +} + /// Sleep the current thread 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); + + // Create an event to wake the thread up after the specified nanosecond delay has passed + Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds); + HLE::Reschedule(__func__); } @@ -374,7 +426,7 @@ const HLE::FunctionDef SVC_Table[] = { {0x06, nullptr, "GetProcessIdealProcessor"}, {0x07, nullptr, "SetProcessIdealProcessor"}, {0x08, HLE::Wrap<CreateThread>, "CreateThread"}, - {0x09, HLE::Wrap<ExitThread>, "ExitThread"}, + {0x09, ExitThread, "ExitThread"}, {0x0A, HLE::Wrap<SleepThread>, "SleepThread"}, {0x0B, HLE::Wrap<GetThreadPriority>, "GetThreadPriority"}, {0x0C, HLE::Wrap<SetThreadPriority>, "SetThreadPriority"}, @@ -391,10 +443,10 @@ const HLE::FunctionDef SVC_Table[] = { {0x17, HLE::Wrap<CreateEvent>, "CreateEvent"}, {0x18, HLE::Wrap<SignalEvent>, "SignalEvent"}, {0x19, HLE::Wrap<ClearEvent>, "ClearEvent"}, - {0x1A, nullptr, "CreateTimer"}, - {0x1B, nullptr, "SetTimer"}, - {0x1C, nullptr, "CancelTimer"}, - {0x1D, nullptr, "ClearTimer"}, + {0x1A, HLE::Wrap<CreateTimer>, "CreateTimer"}, + {0x1B, HLE::Wrap<SetTimer>, "SetTimer"}, + {0x1C, HLE::Wrap<CancelTimer>, "CancelTimer"}, + {0x1D, HLE::Wrap<ClearTimer>, "ClearTimer"}, {0x1E, HLE::Wrap<CreateMemoryBlock>, "CreateMemoryBlock"}, {0x1F, HLE::Wrap<MapMemoryBlock>, "MapMemoryBlock"}, {0x20, nullptr, "UnmapMemoryBlock"}, |