From 82c84883a5d10bd6c9a3516fe16b996c5333360e Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 3 Dec 2014 18:49:51 -0500 Subject: [PATCH] SVC: Implemented svcCreateSemaphore ToDo: Implement svcReleaseSemaphore * Some testing against hardware needed --- src/core/CMakeLists.txt | 2 + src/core/hle/function_wrappers.h | 7 +++ src/core/hle/kernel/semaphore.cpp | 76 +++++++++++++++++++++++++++++++ src/core/hle/kernel/semaphore.h | 22 +++++++++ src/core/hle/svc.cpp | 11 ++++- 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 src/core/hle/kernel/semaphore.cpp create mode 100644 src/core/hle/kernel/semaphore.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8f6792791c..567d7454e2 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -28,6 +28,7 @@ set(SRCS hle/kernel/event.cpp hle/kernel/kernel.cpp hle/kernel/mutex.cpp + hle/kernel/semaphore.cpp hle/kernel/shared_memory.cpp hle/kernel/thread.cpp hle/service/ac_u.cpp @@ -106,6 +107,7 @@ set(HEADERS hle/kernel/event.h hle/kernel/kernel.h hle/kernel/mutex.h + hle/kernel/semaphore.h hle/kernel/shared_memory.h hle/kernel/thread.h hle/service/ac_u.h diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 3dbe25037b..dc36686246 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -114,6 +114,13 @@ template void Wrap() { FuncReturn(retval); } +template void Wrap() { + u32 param_1 = 0; + u32 retval = func(¶m_1, PARAM(1), PARAM(2)); + Core::g_app_core->SetReg(1, param_1); + FuncReturn(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 0000000000..73ffbe3cff --- /dev/null +++ b/src/core/hle/kernel/semaphore.cpp @@ -0,0 +1,76 @@ +// 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/semaphore.h" +#include "core/hle/kernel/thread.h" + +namespace Kernel { + +class Semaphore : public Object { +public: + std::string GetTypeName() const override { return "Semaphore"; } + std::string GetName() const override { return name; } + + static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::Semaphore; } + Kernel::HandleType GetHandleType() const override { return Kernel::HandleType::Semaphore; } + + u32 initial_count; ///< Number of reserved entries + u32 max_count; ///< Maximum number of simultaneous holders the semaphore can have + u32 current_usage; ///< Number of currently used entries in the semaphore + std::vector waiting_threads; ///< Threads that are waiting for the semaphore + std::string name; ///< Name of semaphore (optional) + + ResultVal SyncRequest() override { + // TODO(Subv): ImplementMe + return MakeResult(false); + } + + ResultVal WaitSynchronization() override { + bool wait = current_usage == max_count; + + if (wait) { + Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle()); + waiting_threads.push_back(GetCurrentThreadHandle()); + } else { + ++current_usage; + } + + return MakeResult(wait); + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Creates a semaphore + * @param handle Reference to handle for the newly created semaphore + * @param initial_count initial amount of times the semaphore is held + * @param max_count maximum number of holders the semaphore can have + * @param name Optional name of semaphore + * @return Pointer to new Semaphore object + */ +Semaphore* CreateSemaphore(Handle& handle, u32 initial_count, u32 max_count, const std::string& name) { + Semaphore* semaphore = new Semaphore; + handle = Kernel::g_object_pool.Create(semaphore); + + semaphore->initial_count = semaphore->current_usage = initial_count; + semaphore->max_count = max_count; + semaphore->name = name; + + return semaphore; +} + +Handle CreateSemaphore(u32 initial_count, u32 max_count, const std::string& name) { + Handle handle; + Semaphore* semaphore = 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 0000000000..6a686db2e4 --- /dev/null +++ b/src/core/hle/kernel/semaphore.h @@ -0,0 +1,22 @@ +// 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 { + +/** + * Creates a semaphore + * @param initial_count number of reserved entries in the semaphore + * @param max_count maximum number of holders the semaphore can have + * @param name Optional name of semaphore + * @return Handle to newly created object + */ +Handle CreateSemaphore(u32 initial_count, u32 max_count, const std::string& name = "Unknown"); + +} // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index db0c42e74f..107d121560 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -12,6 +12,7 @@ #include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/mutex.h" +#include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/shared_memory.h" #include "core/hle/kernel/thread.h" @@ -288,6 +289,14 @@ static Result GetThreadId(u32* thread_id, Handle handle) { return result.raw; } +/// Creates a semaphore +static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { + *semaphore = Kernel::CreateSemaphore(initial_count, max_count); + DEBUG_LOG(SVC, "called initial_count=%d, max_count=%d, created handle=0x%08X", + initial_count, max_count, *semaphore); + return 0; +} + /// Query memory static Result QueryMemory(void* info, void* out, u32 addr) { LOG_ERROR(Kernel_SVC, "(UNIMPLEMENTED) called addr=0x%08X", addr); @@ -366,7 +375,7 @@ const HLE::FunctionDef SVC_Table[] = { {0x12, nullptr, "Run"}, {0x13, HLE::Wrap, "CreateMutex"}, {0x14, HLE::Wrap, "ReleaseMutex"}, - {0x15, nullptr, "CreateSemaphore"}, + {0x15, HLE::Wrap, "CreateSemaphore"}, {0x16, nullptr, "ReleaseSemaphore"}, {0x17, HLE::Wrap, "CreateEvent"}, {0x18, HLE::Wrap, "SignalEvent"},