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