1
0
Fork 0
forked from suyu/suyu

kernel: Rename Semaphore to ConditionVariable.

This commit is contained in:
bunnei 2018-01-08 21:41:37 -05:00
parent 9fcd2bf672
commit 4236799832
11 changed files with 180 additions and 171 deletions

View file

@ -5,9 +5,9 @@
#include "citra_qt/debugger/wait_tree.h"
#include "citra_qt/util/util.h"
#include "core/hle/kernel/condition_variable.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/semaphore.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
#include "core/hle/kernel/wait_object.h"
@ -85,8 +85,9 @@ std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitO
return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::Event&>(object));
case Kernel::HandleType::Mutex:
return std::make_unique<WaitTreeMutex>(static_cast<const Kernel::Mutex&>(object));
case Kernel::HandleType::Semaphore:
return std::make_unique<WaitTreeSemaphore>(static_cast<const Kernel::Semaphore&>(object));
case Kernel::HandleType::ConditionVariable:
return std::make_unique<WaitTreeConditionVariable>(
static_cast<const Kernel::ConditionVariable&>(object));
case Kernel::HandleType::Timer:
return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object));
case Kernel::HandleType::Thread:
@ -266,15 +267,15 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutex::GetChildren() const {
return list;
}
WaitTreeSemaphore::WaitTreeSemaphore(const Kernel::Semaphore& object)
WaitTreeConditionVariable::WaitTreeConditionVariable(const Kernel::ConditionVariable& object)
: WaitTreeWaitObject(object) {}
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeSemaphore::GetChildren() const {
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeConditionVariable::GetChildren() const {
std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
const auto& semaphore = static_cast<const Kernel::Semaphore&>(object);
const auto& condition_variable = static_cast<const Kernel::ConditionVariable&>(object);
list.push_back(std::make_unique<WaitTreeText>(
tr("available count = %1").arg(semaphore.GetAvailableCount())));
tr("available count = %1").arg(condition_variable.GetAvailableCount())));
return list;
}

View file

@ -17,7 +17,7 @@ namespace Kernel {
class WaitObject;
class Event;
class Mutex;
class Semaphore;
class ConditionVariable;
class Thread;
class Timer;
}
@ -111,10 +111,10 @@ public:
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
};
class WaitTreeSemaphore : public WaitTreeWaitObject {
class WaitTreeConditionVariable : public WaitTreeWaitObject {
Q_OBJECT
public:
explicit WaitTreeSemaphore(const Kernel::Semaphore& object);
explicit WaitTreeConditionVariable(const Kernel::ConditionVariable& object);
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
};

View file

@ -16,6 +16,7 @@ set(SRCS
hle/kernel/address_arbiter.cpp
hle/kernel/client_port.cpp
hle/kernel/client_session.cpp
hle/kernel/condition_variable.cpp
hle/kernel/domain.cpp
hle/kernel/event.cpp
hle/kernel/handle_table.cpp
@ -26,7 +27,6 @@ set(SRCS
hle/kernel/object_address_table.cpp
hle/kernel/process.cpp
hle/kernel/resource_limit.cpp
hle/kernel/semaphore.cpp
hle/kernel/server_port.cpp
hle/kernel/server_session.cpp
hle/kernel/shared_memory.cpp
@ -94,6 +94,7 @@ set(HEADERS
hle/kernel/address_arbiter.h
hle/kernel/client_port.h
hle/kernel/client_session.h
hle/kernel/condition_variable.h
hle/kernel/domain.h
hle/kernel/errors.h
hle/kernel/event.h
@ -105,7 +106,6 @@ set(HEADERS
hle/kernel/object_address_table.h
hle/kernel/process.h
hle/kernel/resource_limit.h
hle/kernel/semaphore.h
hle/kernel/server_port.h
hle/kernel/server_session.h
hle/kernel/session.h

View file

@ -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

View file

@ -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

View file

@ -23,7 +23,7 @@ enum class HandleType : u32 {
Thread,
Process,
AddressArbiter,
Semaphore,
ConditionVariable,
Timer,
ResourceLimit,
CodeSet,
@ -70,7 +70,7 @@ public:
case HandleType::Event:
case HandleType::Mutex:
case HandleType::Thread:
case HandleType::Semaphore:
case HandleType::ConditionVariable:
case HandleType::Timer:
case HandleType::ServerPort:
case HandleType::ServerSession:

View file

@ -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

View file

@ -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

View file

@ -1,4 +1,4 @@
// Copyright 2014 Citra Emulator Project
// Copyright 2018 Yuzu Emulator Team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@ -8,12 +8,12 @@
#include "core/core_timing.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/condition_variable.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/mutex.h"
#include "core/hle/kernel/object_address_table.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/semaphore.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_wrap.h"
#include "core/hle/kernel/sync_object.h"
@ -476,11 +476,12 @@ static void SleepThread(s64 nanoseconds) {
}
/// Signal process wide key atomic
static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_addr,
static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_variable_addr,
Handle thread_handle, s64 nano_seconds) {
LOG_TRACE(Kernel_SVC,
"called mutex_addr=%llx, semaphore_addr=%llx, thread_handle=0x%08X, timeout=%d",
mutex_addr, semaphore_addr, thread_handle, nano_seconds);
LOG_TRACE(
Kernel_SVC,
"called mutex_addr=%llx, condition_variable_addr=%llx, thread_handle=0x%08X, timeout=%d",
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
ASSERT(thread);
@ -494,15 +495,18 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_add
ASSERT(mutex->GetOwnerHandle() == thread_handle);
SharedPtr<Semaphore> semaphore = g_object_address_table.Get<Semaphore>(semaphore_addr);
if (!semaphore) {
// Create a new semaphore for the specified address if one does not already exist
semaphore = Semaphore::Create(semaphore_addr, mutex_addr).Unwrap();
semaphore->name = Common::StringFromFormat("semaphore-%llx", semaphore_addr);
SharedPtr<ConditionVariable> condition_variable =
g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
if (!condition_variable) {
// Create a new condition_variable for the specified address if one does not already exist
condition_variable =
ConditionVariable::Create(condition_variable_addr, mutex_addr).Unwrap();
condition_variable->name =
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
}
ASSERT(semaphore->GetAvailableCount() == 0);
ASSERT(semaphore->mutex_addr == mutex_addr);
ASSERT(condition_variable->GetAvailableCount() == 0);
ASSERT(condition_variable->mutex_addr == mutex_addr);
auto wakeup_callback = [mutex, nano_seconds](ThreadWakeupReason reason,
SharedPtr<Thread> thread,
@ -541,7 +545,8 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_add
return false;
};
CASCADE_CODE(WaitSynchronization1(semaphore, thread.get(), nano_seconds, wakeup_callback));
CASCADE_CODE(
WaitSynchronization1(condition_variable, thread.get(), nano_seconds, wakeup_callback));
mutex->Release(thread.get());
@ -549,24 +554,27 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr semaphore_add
}
/// Signal process wide key
static ResultCode SignalProcessWideKey(VAddr semaphore_addr, s32 target) {
LOG_TRACE(Kernel_SVC, "called, semaphore_addr=0x%llx, target=0x%08x", semaphore_addr, target);
static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target) {
LOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x%llx, target=0x%08x",
condition_variable_addr, target);
// Wakeup all or one thread - Any other value is unimplemented
ASSERT(target == -1 || target == 1);
SharedPtr<Semaphore> semaphore = g_object_address_table.Get<Semaphore>(semaphore_addr);
if (!semaphore) {
// Create a new semaphore for the specified address if one does not already exist
semaphore = Semaphore::Create(semaphore_addr).Unwrap();
semaphore->name = Common::StringFromFormat("semaphore-%llx", semaphore_addr);
SharedPtr<ConditionVariable> condition_variable =
g_object_address_table.Get<ConditionVariable>(condition_variable_addr);
if (!condition_variable) {
// Create a new condition_variable for the specified address if one does not already exist
condition_variable = ConditionVariable::Create(condition_variable_addr).Unwrap();
condition_variable->name =
Common::StringFromFormat("condition-variable-%llx", condition_variable_addr);
}
CASCADE_CODE(semaphore->Release(target));
CASCADE_CODE(condition_variable->Release(target));
if (semaphore->mutex_addr) {
// If a mutex was created for this semaphore, wait the current thread on it
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(semaphore->mutex_addr);
if (condition_variable->mutex_addr) {
// If a mutex was created for this condition_variable, wait the current thread on it
SharedPtr<Mutex> mutex = g_object_address_table.Get<Mutex>(condition_variable->mutex_addr);
return WaitSynchronization1(mutex, GetCurrentThread());
}

View file

@ -1,4 +1,4 @@
// Copyright 2018 Citra Emulator Project
// Copyright 2018 Yuzu Emulator Team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

View file

@ -1,4 +1,4 @@
// Copyright 2018 Citra Emulator Project
// Copyright 2018 Yuzu Emulator Team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.