KConditionVariable/KAddressArbiter: no need for global compare thread

This commit is contained in:
Michael Scire
2020-12-01 16:19:39 -08:00
parent 4f00303daf
commit 25e1d34017
6 changed files with 124 additions and 23 deletions

View File

@@ -20,8 +20,6 @@
namespace ams::kern {
extern KThread g_cv_arbiter_compare_thread;
class KConditionVariable {
public:
using ThreadTree = typename KThread::ConditionVariableThreadTreeType;

View File

@@ -124,7 +124,21 @@ namespace ams::kern {
static_assert(sizeof(SyncObjectBuffer::sync_objects) == sizeof(SyncObjectBuffer::handles));
struct ConditionVariableComparator {
static constexpr ALWAYS_INLINE int Compare(const KThread &lhs, const KThread &rhs) {
struct LightCompareType {
uintptr_t cv_key;
s32 priority;
constexpr ALWAYS_INLINE uintptr_t GetConditionVariableKey() const {
return this->cv_key;
}
constexpr ALWAYS_INLINE s32 GetPriority() const {
return this->priority;
}
};
template<typename T> requires (std::same_as<T, KThread> || std::same_as<T, LightCompareType>)
static constexpr ALWAYS_INLINE int Compare(const T &lhs, const KThread &rhs) {
const uintptr_t l_key = lhs.GetConditionVariableKey();
const uintptr_t r_key = rhs.GetConditionVariableKey();
@@ -139,6 +153,8 @@ namespace ams::kern {
}
}
};
static_assert(ams::util::HasLightCompareType<ConditionVariableComparator>);
static_assert(std::same_as<ams::util::LightCompareType<ConditionVariableComparator, void>, ConditionVariableComparator::LightCompareType>);
private:
static inline std::atomic<u64> s_next_thread_id = 0;
private:

View File

@@ -50,9 +50,8 @@ namespace ams::kern {
s32 num_waiters = 0;
{
KScopedSchedulerLock sl;
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
auto it = this->tree.nfind_light({ addr, -1 });
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
KThread *target_thread = std::addressof(*it);
target_thread->SetSyncedObject(nullptr, ResultSuccess());
@@ -79,10 +78,7 @@ namespace ams::kern {
R_UNLESS(UpdateIfEqual(std::addressof(user_value), addr, value, value + 1), svc::ResultInvalidCurrentMemory());
R_UNLESS(user_value == value, svc::ResultInvalidState());
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
auto it = this->tree.nfind_light({ addr, -1 });
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetAddressArbiterKey() == addr)) {
KThread *target_thread = std::addressof(*it);
target_thread->SetSyncedObject(nullptr, ResultSuccess());
@@ -103,10 +99,8 @@ namespace ams::kern {
s32 num_waiters = 0;
{
KScopedSchedulerLock sl;
g_cv_arbiter_compare_thread.SetupForAddressArbiterCompare(addr, -1);
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
auto it = this->tree.nfind_light({ addr, -1 });
/* Determine the updated value. */
s32 new_value;
if (GetTargetFirmware() >= TargetFirmware_7_0_0) {

View File

@@ -17,8 +17,6 @@
namespace ams::kern {
constinit KThread g_cv_arbiter_compare_thread;
namespace {
ALWAYS_INLINE bool ReadFromUser(u32 *out, KProcessAddress address) {
@@ -179,9 +177,8 @@ namespace ams::kern {
int num_waiters = 0;
{
KScopedSchedulerLock sl;
g_cv_arbiter_compare_thread.SetupForConditionVariableCompare(cv_key, -1);
auto it = this->tree.nfind(g_cv_arbiter_compare_thread);
auto it = this->tree.nfind_light({ cv_key, -1 });
while ((it != this->tree.end()) && (count <= 0 || num_waiters < count) && (it->GetConditionVariableKey() == cv_key)) {
KThread *target_thread = std::addressof(*it);