5 changed files with 0 additions and 199 deletions
-
2src/core/CMakeLists.txt
-
91src/core/hle/kernel/address_arbiter.cpp
-
60src/core/hle/kernel/address_arbiter.h
-
34src/core/hle/kernel/thread.cpp
-
12src/core/hle/kernel/thread.h
@ -1,91 +0,0 @@ |
|||
// Copyright 2014 Citra Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "common/common_types.h"
|
|||
#include "common/logging/log.h"
|
|||
#include "core/hle/kernel/address_arbiter.h"
|
|||
#include "core/hle/kernel/errors.h"
|
|||
#include "core/hle/kernel/thread.h"
|
|||
#include "core/memory.h"
|
|||
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
// Kernel namespace
|
|||
|
|||
namespace Kernel { |
|||
|
|||
AddressArbiter::AddressArbiter() {} |
|||
AddressArbiter::~AddressArbiter() {} |
|||
|
|||
SharedPtr<AddressArbiter> AddressArbiter::Create(std::string name) { |
|||
SharedPtr<AddressArbiter> address_arbiter(new AddressArbiter); |
|||
|
|||
address_arbiter->name = std::move(name); |
|||
|
|||
return address_arbiter; |
|||
} |
|||
|
|||
ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, |
|||
u64 nanoseconds) { |
|||
switch (type) { |
|||
|
|||
// Signal thread(s) waiting for arbitrate address...
|
|||
case ArbitrationType::Signal: |
|||
// Negative value means resume all threads
|
|||
if (value < 0) { |
|||
ArbitrateAllThreads(address); |
|||
} else { |
|||
// Resume first N threads
|
|||
for (int i = 0; i < value; i++) |
|||
ArbitrateHighestPriorityThread(address); |
|||
} |
|||
break; |
|||
|
|||
// Wait current thread (acquire the arbiter)...
|
|||
case ArbitrationType::WaitIfLessThan: |
|||
if ((s32)Memory::Read32(address) < value) { |
|||
Kernel::WaitCurrentThread_ArbitrateAddress(address); |
|||
} |
|||
break; |
|||
case ArbitrationType::WaitIfLessThanWithTimeout: |
|||
if ((s32)Memory::Read32(address) < value) { |
|||
Kernel::WaitCurrentThread_ArbitrateAddress(address); |
|||
GetCurrentThread()->WakeAfterDelay(nanoseconds); |
|||
} |
|||
break; |
|||
case ArbitrationType::DecrementAndWaitIfLessThan: { |
|||
s32 memory_value = Memory::Read32(address); |
|||
if (memory_value < value) { |
|||
// Only change the memory value if the thread should wait
|
|||
Memory::Write32(address, (s32)memory_value - 1); |
|||
Kernel::WaitCurrentThread_ArbitrateAddress(address); |
|||
} |
|||
break; |
|||
} |
|||
case ArbitrationType::DecrementAndWaitIfLessThanWithTimeout: { |
|||
s32 memory_value = Memory::Read32(address); |
|||
if (memory_value < value) { |
|||
// Only change the memory value if the thread should wait
|
|||
Memory::Write32(address, (s32)memory_value - 1); |
|||
Kernel::WaitCurrentThread_ArbitrateAddress(address); |
|||
GetCurrentThread()->WakeAfterDelay(nanoseconds); |
|||
} |
|||
break; |
|||
} |
|||
|
|||
default: |
|||
LOG_ERROR(Kernel, "unknown type=%d", type); |
|||
return ERR_INVALID_ENUM_VALUE_FND; |
|||
} |
|||
|
|||
// The calls that use a timeout seem to always return a Timeout error even if they did not put
|
|||
// the thread to sleep
|
|||
if (type == ArbitrationType::WaitIfLessThanWithTimeout || |
|||
type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { |
|||
|
|||
return RESULT_TIMEOUT; |
|||
} |
|||
return RESULT_SUCCESS; |
|||
} |
|||
|
|||
} // namespace Kernel
|
|||
@ -1,60 +0,0 @@ |
|||
// Copyright 2014 Citra Emulator Project |
|||
// Licensed under GPLv2 or any later version |
|||
// Refer to the license.txt file included. |
|||
|
|||
#pragma once |
|||
|
|||
#include "common/common_types.h" |
|||
#include "core/hle/kernel/kernel.h" |
|||
#include "core/hle/result.h" |
|||
|
|||
// Address arbiters are an underlying kernel synchronization object that can be created/used via |
|||
// supervisor calls (SVCs). They function as sort of a global lock. Typically, games/other CTR |
|||
// applications use them as an underlying mechanism to implement thread-safe barriers, events, and |
|||
// semphores. |
|||
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// Kernel namespace |
|||
|
|||
namespace Kernel { |
|||
|
|||
enum class ArbitrationType : u32 { |
|||
Signal, |
|||
WaitIfLessThan, |
|||
DecrementAndWaitIfLessThan, |
|||
WaitIfLessThanWithTimeout, |
|||
DecrementAndWaitIfLessThanWithTimeout, |
|||
}; |
|||
|
|||
class AddressArbiter final : public Object { |
|||
public: |
|||
/** |
|||
* Creates an address arbiter. |
|||
* |
|||
* @param name Optional name used for debugging. |
|||
* @returns The created AddressArbiter. |
|||
*/ |
|||
static SharedPtr<AddressArbiter> Create(std::string name = "Unknown"); |
|||
|
|||
std::string GetTypeName() const override { |
|||
return "Arbiter"; |
|||
} |
|||
std::string GetName() const override { |
|||
return name; |
|||
} |
|||
|
|||
static const HandleType HANDLE_TYPE = HandleType::AddressArbiter; |
|||
HandleType GetHandleType() const override { |
|||
return HANDLE_TYPE; |
|||
} |
|||
|
|||
std::string name; ///< Name of address arbiter object (optional) |
|||
|
|||
ResultCode ArbitrateAddress(ArbitrationType type, VAddr address, s32 value, u64 nanoseconds); |
|||
|
|||
private: |
|||
AddressArbiter(); |
|||
~AddressArbiter() override; |
|||
}; |
|||
|
|||
} // namespace Kernel |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue