diff options
| author | Subv <subv2112@gmail.com> | 2014-12-04 11:40:36 -0500 | 
|---|---|---|
| committer | Subv <subv2112@gmail.com> | 2014-12-13 13:40:10 -0500 | 
| commit | 49b31badba5672bae3a5950abe3d45c883879c0d (patch) | |
| tree | 9e0b3da4ac87b39e58ea8d0f1c347b06a6e82169 /src/core/hle | |
| parent | 82c84883a5d10bd6c9a3516fe16b996c5333360e (diff) | |
SVC: Implemented ReleaseSemaphore.
This behavior was tested on hardware, however i'm still not sure what use the "initial_count" parameter has
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/function_wrappers.h | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/semaphore.cpp | 65 | ||||
| -rw-r--r-- | src/core/hle/kernel/semaphore.h | 15 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 13 | 
4 files changed, 81 insertions, 19 deletions
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index dc3668624..b44479b2f 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -121,6 +121,13 @@ template<s32 func(u32*, s32, s32)> void Wrap() {      FuncReturn(retval);  } +template<s32 func(s32*, u32, s32)> void Wrap() { +    s32 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 index 73ffbe3cf..674b727d5 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -2,8 +2,7 @@  // Licensed under GPLv2+  // Refer to the license.txt file included. -#include <map> -#include <vector> +#include <queue>  #include "common/common.h" @@ -21,12 +20,20 @@ public:      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 initial_count;                          ///< Number of reserved entries TODO(Subv): Make use of this      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<Handle> waiting_threads;        ///< Threads that are waiting for the semaphore +    std::queue<Handle> waiting_threads;         ///< Threads that are waiting for the semaphore      std::string name;                           ///< Name of semaphore (optional) +    /** +     * Tests whether a semaphore is at its peak capacity +     * @return Whether the semaphore is full +     */ +    bool IsFull() const { +        return current_usage == max_count; +    } +      ResultVal<bool> SyncRequest() override {          // TODO(Subv): ImplementMe          return MakeResult<bool>(false); @@ -37,7 +44,7 @@ public:          if (wait) {              Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle()); -            waiting_threads.push_back(GetCurrentThreadHandle()); +            waiting_threads.push(GetCurrentThreadHandle());          } else {              ++current_usage;          } @@ -56,21 +63,53 @@ public:   * @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* CreateSemaphore(Handle& handle, u32 initial_count,  +    u32 max_count, const std::string& name) { +      Semaphore* semaphore = new Semaphore; -    handle = Kernel::g_object_pool.Create(semaphore); +    handle = g_object_pool.Create(semaphore); -    semaphore->initial_count = semaphore->current_usage = initial_count; -    semaphore->max_count = max_count; +    semaphore->initial_count = initial_count; +    // When the semaphore is created, all slots are used by the creator thread +    semaphore->max_count = semaphore->current_usage = 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; +ResultCode CreateSemaphore(Handle* handle, u32 initial_count,  +    u32 max_count, const std::string& name) { + +    if (initial_count > max_count) +        return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, +                          ErrorSummary::WrongArgument, ErrorLevel::Permanent); +    Semaphore* semaphore = CreateSemaphore(*handle, initial_count, max_count, name); + +    return RESULT_SUCCESS; +} + +ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) { + +    Semaphore* semaphore = g_object_pool.Get<Semaphore>(handle); +    if (semaphore == nullptr) +        return InvalidHandle(ErrorModule::Kernel); + +    if (semaphore->current_usage < release_count) +        return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel,  +                          ErrorSummary::InvalidArgument, ErrorLevel::Permanent); + +    *count = semaphore->max_count - semaphore->current_usage; +    semaphore->current_usage = semaphore->current_usage - release_count; + +    // Notify some of the threads that the semaphore has been released +    // stop once the semaphore is full again or there are no more waiting threads +    while (!semaphore->waiting_threads.empty() && !semaphore->IsFull()) { +        Kernel::ResumeThreadFromWait(semaphore->waiting_threads.front()); +        semaphore->waiting_threads.pop(); +        semaphore->current_usage++; +    } + +    return RESULT_SUCCESS;  }  } // namespace diff --git a/src/core/hle/kernel/semaphore.h b/src/core/hle/kernel/semaphore.h index 6a686db2e..854831ecf 100644 --- a/src/core/hle/kernel/semaphore.h +++ b/src/core/hle/kernel/semaphore.h @@ -12,11 +12,20 @@ namespace Kernel {  /**   * Creates a semaphore + * @param handle Pointer to the handle of the newly created object   * @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 + * @param name Optional name of semaphore + * @return ResultCode of the error   */ -Handle CreateSemaphore(u32 initial_count, u32 max_count, const std::string& name = "Unknown"); +ResultCode CreateSemaphore(Handle* handle, u32 initial_count, u32 max_count, const std::string& name = "Unknown"); +/** + * Releases a certain number of slots from a semaphore + * @param count The number of free slots the semaphore had before this call + * @param handle The handle of the semaphore to release + * @param release_count The number of slots to release + * @return ResultCode of the error + */ +ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count);  } // namespace diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 107d12156..2846bb482 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -291,10 +291,17 @@ static Result GetThreadId(u32* thread_id, Handle handle) {  /// Creates a semaphore  static Result CreateSemaphore(Handle* semaphore, s32 initial_count, s32 max_count) { -    *semaphore = Kernel::CreateSemaphore(initial_count, max_count); +    ResultCode res = Kernel::CreateSemaphore(semaphore, 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; +    return res.raw; +} + +/// Releases a certain number of slots in a semaphore +static Result ReleaseSemaphore(s32* count, Handle semaphore, s32 release_count) { +    DEBUG_LOG(SVC, "called release_count=%d, handle=0x%08X", release_count, semaphore); +    ResultCode res = Kernel::ReleaseSemaphore(count, semaphore, release_count); +    return res.raw;  }  /// Query memory @@ -376,7 +383,7 @@ const HLE::FunctionDef SVC_Table[] = {      {0x13, HLE::Wrap<CreateMutex>,          "CreateMutex"},      {0x14, HLE::Wrap<ReleaseMutex>,         "ReleaseMutex"},      {0x15, HLE::Wrap<CreateSemaphore>,      "CreateSemaphore"}, -    {0x16, nullptr,                         "ReleaseSemaphore"}, +    {0x16, HLE::Wrap<ReleaseSemaphore>,     "ReleaseSemaphore"},      {0x17, HLE::Wrap<CreateEvent>,          "CreateEvent"},      {0x18, HLE::Wrap<SignalEvent>,          "SignalEvent"},      {0x19, HLE::Wrap<ClearEvent>,           "ClearEvent"},  | 
