diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f8ee3c8cd..576ec39dd 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -37,6 +37,7 @@ set(SRCS core.cpp hle/kernel/event.cpp hle/kernel/kernel.cpp hle/kernel/mutex.cpp + hle/kernel/semaphore.cpp hle/kernel/thread.cpp hle/kernel/shared_memory.cpp hle/service/apt.cpp @@ -85,6 +86,7 @@ set(HEADERS core.h hle/svc.h hle/kernel/kernel.h hle/kernel/mutex.h + hle/kernel/semaphore.h hle/kernel/shared_memory.h hle/kernel/thread.h hle/function_wrappers.h diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj index 8f3561653..176102592 100644 --- a/src/core/core.vcxproj +++ b/src/core/core.vcxproj @@ -181,6 +181,7 @@ + @@ -234,6 +235,7 @@ + diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters index 33b00ab90..999d7698d 100644 --- a/src/core/core.vcxproj.filters +++ b/src/core/core.vcxproj.filters @@ -52,6 +52,7 @@ + @@ -104,6 +105,7 @@ + diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index f9a64c0a5..a8aab9e21 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -90,6 +90,20 @@ template void Wrap() { RETURN(retval); } +template void Wrap() { + u32 param_1 = 0; + u32 retval = func(¶m_1, (s32)PARAM(1), (s32)PARAM(2)); + Core::g_app_core->SetReg(1, param_1); + RETURN(retval); +} + +template void Wrap() { + s32 param_0 = 0; + u32 retval = func(¶m_0, PARAM(1), (s32)PARAM(2)); + Core::g_app_core->SetReg(1, param_0); + RETURN(retval); +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // Function wrappers that return type u32 diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp new file mode 100644 index 000000000..49ab5fbd3 --- /dev/null +++ b/src/core/hle/kernel/semaphore.cpp @@ -0,0 +1,100 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include +#include + +#include "common/common.h" + +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/mutex.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +class Semaphore : public Object { +public: + const char* GetTypeName() const { return "Semaphore"; } + const char* GetName() const { return name.c_str(); } + + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; } + Kernel::HandleType GetHandleType() const { return Kernel::HandleType::Semaphore; } + + s32 initial_count; ///< Initial count state when semaphore was created + s32 count; ///< Current count state + s32 max_count; ///< Max count state + Handle lock_thread; ///< Handle to thread that currently has semaphore + std::string name; + + /** + * Synchronize kernel object + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result SyncRequest(bool* wait) { + // TODO(bravia): ImplementMe + return 0; + } + + /** + * Wait for kernel object to synchronize + * @param wait Boolean wait set if current thread should wait as a result of sync operation + * @return Result of operation, 0 on success, otherwise error code + */ + Result WaitSynchronization(bool* wait) { + // TODO(bravia): ImplementMe + return 0; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Releases a semaphore + * @param unknown + * @param handle Handle to mutex to release + * @param unknown + */ +Result ReleaseSemaphore(s32 * count, Handle handle, s32 release_count) { + Semaphore* sem = Kernel::g_object_pool.GetFast(handle); + + _assert_msg_(KERNEL, (sem != nullptr), "ReleaseSemaphore tried to release a nullptr sem!"); + + //TODO(bravia): ImplementMe + return 0; +} + +/** + * Creates a semaphore + * @param handle Reference to handle for the newly created semaphore + * @param initial_count Specifies if the semaphore is initialized with a count + * @param max_count Specifies the max count of the semaphore + * @param name Optional name of semaphore + * @return Pointer to new Semaphore object + */ +Semaphore* CreateSemaphore(Handle& handle, s32 initial_count, s32 max_count, const std::string& name) { + Semaphore* sem = new Semaphore; + handle = Kernel::g_object_pool.Create(sem); + + sem->initial_count = sem->count = initial_count; + sem->name = name; + + return sem; +} + +/** +* Creates a semaphore +* @param handle Reference to handle for the newly created semaphore +* @param initial_count Specifies if the semaphore is initialized with a count +* @param max_count Specifies the max count of the semaphore +* @param name Optional name of semaphore +* @return Handle to new Semaphore object +*/ +Handle CreateSemaphore(s32 initial_count, s32 max_count, const std::string& name) { + Handle handle; + Semaphore* sem = CreateSemaphore(handle, initial_count, max_count, name); + return handle; +} + +} // namespace diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h new file mode 100644 index 000000000..07c9559bf --- /dev/null +++ b/src/core/hle/kernel/semaphore.h @@ -0,0 +1,31 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#include "core/hle/kernel/kernel.h" + +namespace Kernel { + +/** +* Releases a semaphore +* @param unknown +* @param handle Handle to mutex to release +* @param unknown +*/ +Result ReleaseSemaphore(s32 * count, Handle handle, s32 release_count); + +/** +* Creates a semaphore +* @param handle Reference to handle for the newly created semaphore +* @param initial_count Specifies if the semaphore is initialized with a count +* @param max_count Specifies the max count of the semaphore +* @param name Optional name of semaphore +* @return Handle to new Semaphore object +*/ +Handle CreateSemaphore(s32 initial_count, s32 max_count, const std::string& name = "Unknown"); + +} // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 875ea2873..b20dec748 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -12,6 +12,7 @@ #include "core/hle/kernel/event.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/mutex.h" +#include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/thread.h" #include "core/hle/function_wrappers.h" @@ -275,6 +276,22 @@ Result ReleaseMutex(Handle handle) { return 0; } +/// Create a semaphore +Result CreateSemaphore(Handle* sem, s32 initial_count, s32 max_count) { + *sem = Kernel::CreateSemaphore(initial_count, max_count); + DEBUG_LOG(SVC, "called initial_count=%d , max_count=%d : created handle=0x%08X", + initial_count, max_count, *sem); + return 0; +} + +/// Release a mutex +Result ReleaseSemaphore(s32* count, Handle handle, s32 releaseCount) { + DEBUG_LOG(SVC, "called handle=0x%08X", handle); + _assert_msg_(KERNEL, (handle != 0), "called, but handle is nullptr!"); + Kernel::ReleaseSemaphore(count, handle, releaseCount); + return 0; +} + /// Get current thread ID Result GetThreadId(u32* thread_id, Handle thread) { ERROR_LOG(SVC, "(UNIMPLEMENTED) called thread=0x%08X", thread); @@ -359,8 +376,8 @@ const HLE::FunctionDef SVC_Table[] = { {0x12, nullptr, "Run"}, {0x13, HLE::Wrap, "CreateMutex"}, {0x14, HLE::Wrap, "ReleaseMutex"}, - {0x15, nullptr, "CreateSemaphore"}, - {0x16, nullptr, "ReleaseSemaphore"}, + {0x15, HLE::Wrap, "CreateSemaphore" }, + {0x16, HLE::Wrap, "ReleaseSemaphore"}, {0x17, HLE::Wrap, "CreateEvent"}, {0x18, HLE::Wrap, "SignalEvent"}, {0x19, HLE::Wrap, "ClearEvent"},