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