11 changed files with 180 additions and 171 deletions
-
15src/citra_qt/debugger/wait_tree.cpp
-
6src/citra_qt/debugger/wait_tree.h
-
4src/core/CMakeLists.txt
-
65src/core/hle/kernel/condition_variable.cpp
-
65src/core/hle/kernel/condition_variable.h
-
4src/core/hle/kernel/kernel.h
-
64src/core/hle/kernel/semaphore.cpp
-
66src/core/hle/kernel/semaphore.h
-
58src/core/hle/kernel/svc.cpp
-
2src/core/hle/kernel/svc.h
-
2src/core/hle/kernel/svc_wrap.h
@ -0,0 +1,65 @@ |
|||
// Copyright 2018 Yuzu Emulator Team
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/assert.h"
|
|||
#include "core/hle/kernel/condition_variable.h"
|
|||
#include "core/hle/kernel/errors.h"
|
|||
#include "core/hle/kernel/kernel.h"
|
|||
#include "core/hle/kernel/object_address_table.h"
|
|||
#include "core/hle/kernel/thread.h"
|
|||
|
|||
namespace Kernel { |
|||
|
|||
ConditionVariable::ConditionVariable() {} |
|||
ConditionVariable::~ConditionVariable() {} |
|||
|
|||
ResultVal<SharedPtr<ConditionVariable>> ConditionVariable::Create(VAddr guest_addr, |
|||
VAddr mutex_addr, |
|||
std::string name) { |
|||
SharedPtr<ConditionVariable> condition_variable(new ConditionVariable); |
|||
|
|||
condition_variable->name = std::move(name); |
|||
condition_variable->guest_addr = guest_addr; |
|||
condition_variable->mutex_addr = mutex_addr; |
|||
|
|||
// Condition variables are referenced by guest address, so track this in the kernel
|
|||
g_object_address_table.Insert(guest_addr, condition_variable); |
|||
|
|||
return MakeResult<SharedPtr<ConditionVariable>>(std::move(condition_variable)); |
|||
} |
|||
|
|||
bool ConditionVariable::ShouldWait(Thread* thread) const { |
|||
return GetAvailableCount() <= 0; |
|||
} |
|||
|
|||
void ConditionVariable::Acquire(Thread* thread) { |
|||
if (GetAvailableCount() <= 0) |
|||
return; |
|||
|
|||
SetAvailableCount(GetAvailableCount() - 1); |
|||
} |
|||
|
|||
ResultCode ConditionVariable::Release(s32 target) { |
|||
if (target == -1) { |
|||
// When -1, wake up all waiting threads
|
|||
SetAvailableCount(GetWaitingThreads().size()); |
|||
WakeupAllWaitingThreads(); |
|||
} else { |
|||
// Otherwise, wake up just a single thread
|
|||
SetAvailableCount(target); |
|||
WakeupWaitingThread(GetHighestPriorityReadyThread()); |
|||
} |
|||
|
|||
return RESULT_SUCCESS; |
|||
} |
|||
|
|||
s32 ConditionVariable::GetAvailableCount() const { |
|||
return Memory::Read32(guest_addr); |
|||
} |
|||
|
|||
void ConditionVariable::SetAvailableCount(s32 value) const { |
|||
Memory::Write32(guest_addr, value); |
|||
} |
|||
|
|||
} // namespace Kernel
|
|||
@ -0,0 +1,65 @@ |
|||
// Copyright 2018 Yuzu Emulator Team |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <queue> |
|||
#include <string> |
|||
#include "common/common_types.h" |
|||
#include "core/hle/kernel/kernel.h" |
|||
#include "core/hle/kernel/wait_object.h" |
|||
#include "core/hle/result.h" |
|||
|
|||
namespace Kernel { |
|||
|
|||
class ConditionVariable final : public WaitObject { |
|||
public: |
|||
/** |
|||
* Creates a condition variable. |
|||
* @param guest_addr Address of the object tracking the condition variable in guest memory. If |
|||
* specified, this condition variable will update the guest object when its state changes. |
|||
* @param mutex_addr Optional address of a guest mutex associated with this condition variable, |
|||
* used by the OS for implementing events. |
|||
* @param name Optional name of condition variable. |
|||
* @return The created condition variable. |
|||
*/ |
|||
static ResultVal<SharedPtr<ConditionVariable>> Create(VAddr guest_addr, VAddr mutex_addr = 0, |
|||
std::string name = "Unknown"); |
|||
|
|||
std::string GetTypeName() const override { |
|||
return "ConditionVariable"; |
|||
} |
|||
std::string GetName() const override { |
|||
return name; |
|||
} |
|||
|
|||
static const HandleType HANDLE_TYPE = HandleType::ConditionVariable; |
|||
HandleType GetHandleType() const override { |
|||
return HANDLE_TYPE; |
|||
} |
|||
|
|||
s32 GetAvailableCount() const; |
|||
void SetAvailableCount(s32 value) const; |
|||
|
|||
std::string name; ///< Name of condition variable (optional) |
|||
VAddr guest_addr; ///< Address of the guest condition variable value |
|||
VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this condition |
|||
///< variable, used for implementing events |
|||
|
|||
bool ShouldWait(Thread* thread) const override; |
|||
void Acquire(Thread* thread) override; |
|||
|
|||
/** |
|||
* Releases a slot from a condition variable. |
|||
* @param target The number of threads to wakeup, -1 is all. |
|||
* @return ResultCode indicating if the operation succeeded. |
|||
*/ |
|||
ResultCode Release(s32 target); |
|||
|
|||
private: |
|||
ConditionVariable(); |
|||
~ConditionVariable() override; |
|||
}; |
|||
|
|||
} // namespace Kernel |
|||
@ -1,64 +0,0 @@ |
|||
// Copyright 2014 Citra Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/assert.h"
|
|||
#include "core/hle/kernel/errors.h"
|
|||
#include "core/hle/kernel/kernel.h"
|
|||
#include "core/hle/kernel/object_address_table.h"
|
|||
#include "core/hle/kernel/semaphore.h"
|
|||
#include "core/hle/kernel/thread.h"
|
|||
|
|||
namespace Kernel { |
|||
|
|||
Semaphore::Semaphore() {} |
|||
Semaphore::~Semaphore() {} |
|||
|
|||
ResultVal<SharedPtr<Semaphore>> Semaphore::Create(VAddr guest_addr, VAddr mutex_addr, |
|||
std::string name) { |
|||
SharedPtr<Semaphore> semaphore(new Semaphore); |
|||
|
|||
semaphore->name = std::move(name); |
|||
semaphore->guest_addr = guest_addr; |
|||
semaphore->mutex_addr = mutex_addr; |
|||
|
|||
// Semaphores are referenced by guest address, so track this in the kernel
|
|||
g_object_address_table.Insert(guest_addr, semaphore); |
|||
|
|||
return MakeResult<SharedPtr<Semaphore>>(std::move(semaphore)); |
|||
} |
|||
|
|||
bool Semaphore::ShouldWait(Thread* thread) const { |
|||
return GetAvailableCount() <= 0; |
|||
} |
|||
|
|||
void Semaphore::Acquire(Thread* thread) { |
|||
if (GetAvailableCount() <= 0) |
|||
return; |
|||
|
|||
SetAvailableCount(GetAvailableCount() - 1); |
|||
} |
|||
|
|||
ResultCode Semaphore::Release(s32 target) { |
|||
if (target == -1) { |
|||
// When -1, wake up all waiting threads
|
|||
SetAvailableCount(GetWaitingThreads().size()); |
|||
WakeupAllWaitingThreads(); |
|||
} else { |
|||
// Otherwise, wake up just a single thread
|
|||
SetAvailableCount(target); |
|||
WakeupWaitingThread(GetHighestPriorityReadyThread()); |
|||
} |
|||
|
|||
return RESULT_SUCCESS; |
|||
} |
|||
|
|||
s32 Semaphore::GetAvailableCount() const { |
|||
return Memory::Read32(guest_addr); |
|||
} |
|||
|
|||
void Semaphore::SetAvailableCount(s32 value) const { |
|||
Memory::Write32(guest_addr, value); |
|||
} |
|||
|
|||
} // namespace Kernel
|
|||
@ -1,66 +0,0 @@ |
|||
// Copyright 2014 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include <queue> |
|||
#include <string> |
|||
#include "common/common_types.h" |
|||
#include "core/hle/kernel/kernel.h" |
|||
#include "core/hle/kernel/wait_object.h" |
|||
#include "core/hle/result.h" |
|||
|
|||
namespace Kernel { |
|||
|
|||
// TODO(Subv): This is actually a Condition Variable. |
|||
class Semaphore final : public WaitObject { |
|||
public: |
|||
/** |
|||
* Creates a semaphore. |
|||
* @param guest_addr Address of the object tracking the semaphore in guest memory. If specified, |
|||
* this semaphore will update the guest object when its state changes. |
|||
* @param mutex_addr Optional address of a guest mutex associated with this semaphore, used by |
|||
* the OS for implementing events. |
|||
* @param name Optional name of semaphore. |
|||
* @return The created semaphore. |
|||
*/ |
|||
static ResultVal<SharedPtr<Semaphore>> Create(VAddr guest_addr, VAddr mutex_addr = 0, |
|||
std::string name = "Unknown"); |
|||
|
|||
std::string GetTypeName() const override { |
|||
return "Semaphore"; |
|||
} |
|||
std::string GetName() const override { |
|||
return name; |
|||
} |
|||
|
|||
static const HandleType HANDLE_TYPE = HandleType::Semaphore; |
|||
HandleType GetHandleType() const override { |
|||
return HANDLE_TYPE; |
|||
} |
|||
|
|||
s32 GetAvailableCount() const; |
|||
void SetAvailableCount(s32 value) const; |
|||
|
|||
std::string name; ///< Name of semaphore (optional) |
|||
VAddr guest_addr; ///< Address of the guest semaphore value |
|||
VAddr mutex_addr; ///< (optional) Address of guest mutex value associated with this semaphore, |
|||
///< used for implementing events |
|||
|
|||
bool ShouldWait(Thread* thread) const override; |
|||
void Acquire(Thread* thread) override; |
|||
|
|||
/** |
|||
* Releases a slot from a semaphore. |
|||
* @param target The number of threads to wakeup, -1 is all. |
|||
* @return ResultCode indicating if the operation succeeded. |
|||
*/ |
|||
ResultCode Release(s32 target); |
|||
|
|||
private: |
|||
Semaphore(); |
|||
~Semaphore() override; |
|||
}; |
|||
|
|||
} // namespace Kernel |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue