mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	kernel: be more careful about kernel address keys
This commit is contained in:
		@@ -113,7 +113,7 @@ Result KConditionVariable::SignalToAddress(VAddr addr) {
 | 
			
		||||
        // Remove waiter thread.
 | 
			
		||||
        bool has_waiters{};
 | 
			
		||||
        KThread* const next_owner_thread =
 | 
			
		||||
            owner_thread->RemoveWaiterByKey(std::addressof(has_waiters), addr);
 | 
			
		||||
            owner_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr);
 | 
			
		||||
 | 
			
		||||
        // Determine the next tag.
 | 
			
		||||
        u32 next_value{};
 | 
			
		||||
@@ -283,7 +283,7 @@ Result KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout) {
 | 
			
		||||
            // Remove waiter thread.
 | 
			
		||||
            bool has_waiters{};
 | 
			
		||||
            KThread* next_owner_thread =
 | 
			
		||||
                cur_thread->RemoveWaiterByKey(std::addressof(has_waiters), addr);
 | 
			
		||||
                cur_thread->RemoveUserWaiterByKey(std::addressof(has_waiters), addr);
 | 
			
		||||
 | 
			
		||||
            // Update for the next owner thread.
 | 
			
		||||
            u32 next_value{};
 | 
			
		||||
 
 | 
			
		||||
@@ -91,7 +91,7 @@ void KLightLock::UnlockSlowPath(uintptr_t _cur_thread) {
 | 
			
		||||
 | 
			
		||||
        // Get the next owner.
 | 
			
		||||
        bool has_waiters;
 | 
			
		||||
        KThread* next_owner = owner_thread->RemoveWaiterByKey(
 | 
			
		||||
        KThread* next_owner = owner_thread->RemoveKernelWaiterByKey(
 | 
			
		||||
            std::addressof(has_waiters), reinterpret_cast<uintptr_t>(std::addressof(tag)));
 | 
			
		||||
 | 
			
		||||
        // Pass the lock to the next owner.
 | 
			
		||||
 
 | 
			
		||||
@@ -157,7 +157,7 @@ bool KProcess::ReleaseUserException(KThread* thread) {
 | 
			
		||||
 | 
			
		||||
        // Remove waiter thread.
 | 
			
		||||
        bool has_waiters{};
 | 
			
		||||
        if (KThread* next = thread->RemoveWaiterByKey(
 | 
			
		||||
        if (KThread* next = thread->RemoveKernelWaiterByKey(
 | 
			
		||||
                std::addressof(has_waiters),
 | 
			
		||||
                reinterpret_cast<uintptr_t>(std::addressof(exception_thread)));
 | 
			
		||||
            next != nullptr) {
 | 
			
		||||
 
 | 
			
		||||
@@ -933,12 +933,14 @@ void KThread::AddHeldLock(LockWithPriorityInheritanceInfo* lock_info) {
 | 
			
		||||
    held_lock_info_list.push_front(*lock_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(VAddr address_key_) {
 | 
			
		||||
KThread::LockWithPriorityInheritanceInfo* KThread::FindHeldLock(VAddr address_key_,
 | 
			
		||||
                                                                bool is_kernel_address_key_) {
 | 
			
		||||
    ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel));
 | 
			
		||||
 | 
			
		||||
    // Try to find an existing held lock.
 | 
			
		||||
    for (auto& held_lock : held_lock_info_list) {
 | 
			
		||||
        if (held_lock.GetAddressKey() == address_key_) {
 | 
			
		||||
        if (held_lock.GetAddressKey() == address_key_ &&
 | 
			
		||||
            held_lock.GetIsKernelAddressKey() == is_kernel_address_key_) {
 | 
			
		||||
            return std::addressof(held_lock);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -961,7 +963,7 @@ void KThread::AddWaiterImpl(KThread* thread) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get the relevant lock info.
 | 
			
		||||
    auto* lock_info = this->FindHeldLock(address_key_);
 | 
			
		||||
    auto* lock_info = this->FindHeldLock(address_key_, is_kernel_address_key_);
 | 
			
		||||
    if (lock_info == nullptr) {
 | 
			
		||||
        // Create a new lock for the address key.
 | 
			
		||||
        lock_info =
 | 
			
		||||
@@ -1067,11 +1069,11 @@ void KThread::RemoveWaiter(KThread* thread) {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, VAddr key) {
 | 
			
		||||
KThread* KThread::RemoveWaiterByKey(bool* out_has_waiters, VAddr key, bool is_kernel_address_key_) {
 | 
			
		||||
    ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel));
 | 
			
		||||
 | 
			
		||||
    // Get the relevant lock info.
 | 
			
		||||
    auto* lock_info = this->FindHeldLock(key);
 | 
			
		||||
    auto* lock_info = this->FindHeldLock(key, is_kernel_address_key_);
 | 
			
		||||
    if (lock_info == nullptr) {
 | 
			
		||||
        *out_has_waiters = false;
 | 
			
		||||
        return nullptr;
 | 
			
		||||
 
 | 
			
		||||
@@ -595,7 +595,13 @@ public:
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] Result GetThreadContext3(std::vector<u8>& out);
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] KThread* RemoveWaiterByKey(bool* out_has_waiters, VAddr key);
 | 
			
		||||
    [[nodiscard]] KThread* RemoveUserWaiterByKey(bool* out_has_waiters, VAddr key) {
 | 
			
		||||
        return this->RemoveWaiterByKey(out_has_waiters, key, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] KThread* RemoveKernelWaiterByKey(bool* out_has_waiters, VAddr key) {
 | 
			
		||||
        return this->RemoveWaiterByKey(out_has_waiters, key, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    [[nodiscard]] VAddr GetAddressKey() const {
 | 
			
		||||
        return address_key;
 | 
			
		||||
@@ -666,6 +672,9 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    [[nodiscard]] KThread* RemoveWaiterByKey(bool* out_has_waiters, VAddr key,
 | 
			
		||||
                                             bool is_kernel_address_key);
 | 
			
		||||
 | 
			
		||||
    static constexpr size_t PriorityInheritanceCountMax = 10;
 | 
			
		||||
    union SyncObjectBuffer {
 | 
			
		||||
        std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> sync_objects{};
 | 
			
		||||
@@ -850,7 +859,7 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void AddHeldLock(LockWithPriorityInheritanceInfo* lock_info);
 | 
			
		||||
    LockWithPriorityInheritanceInfo* FindHeldLock(VAddr address_key);
 | 
			
		||||
    LockWithPriorityInheritanceInfo* FindHeldLock(VAddr address_key, bool is_kernel_address_key);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    using LockWithPriorityInheritanceInfoList =
 | 
			
		||||
@@ -926,6 +935,7 @@ public:
 | 
			
		||||
        condvar_key = cv_key;
 | 
			
		||||
        address_key = address;
 | 
			
		||||
        address_key_value = value;
 | 
			
		||||
        is_kernel_address_key = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void ClearConditionVariable() {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user