From e6a7723f2f4b62279cd4f6d4b48eb02a9b60ffb6 Mon Sep 17 00:00:00 2001 From: Subv Date: Sun, 1 Jan 2017 16:53:22 -0500 Subject: Kernel: Object ShouldWait and Acquire calls now take a thread as a parameter. This will be useful when implementing mutex priority inheritance. --- src/core/hle/kernel/thread.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/thread.h') diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index c77ac644d..f2bc1ec9c 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -72,8 +72,8 @@ public: return HANDLE_TYPE; } - bool ShouldWait() override; - void Acquire() override; + bool ShouldWait(Thread* thread) const override; + void Acquire(Thread* thread) override; /** * Gets the thread's current priority -- cgit v1.2.3 From d3ff5b91e14356912589f9bac47fccbe79e07279 Mon Sep 17 00:00:00 2001 From: Subv Date: Mon, 2 Jan 2017 19:38:08 -0500 Subject: Kernel/Mutex: Propagate thread priority changes to other threads inheriting the priority via mutexes --- src/core/hle/kernel/thread.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/core/hle/kernel/thread.h') diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index f2bc1ec9c..e2f0cc831 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -89,6 +89,12 @@ public: */ void SetPriority(s32 priority); + /** + * Boost's a thread's priority to the best priority among the thread's held mutexes. + * This prevents priority inversion via priority inheritance. + */ + void UpdatePriority(); + /** * Temporarily boosts the thread's priority until the next time it is scheduled * @param priority The new priority @@ -178,6 +184,9 @@ public: /// Mutexes currently held by this thread, which will be released when it exits. boost::container::flat_set> held_mutexes; + /// Mutexes that this thread is currently waiting for. + boost::container::flat_set> pending_mutexes; + SharedPtr owner_process; ///< Process that owns this thread /// Objects that the thread is waiting on. -- cgit v1.2.3 From cef5f45de2fd64f0728d4504d0ad7434cb8ac519 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 4 Jan 2017 10:44:38 -0500 Subject: Kernel: Use different thread statuses when a thread calls WaitSynchronization1 and WaitSynchronizationN with wait_all = true. This commit removes the overly general THREADSTATUS_WAIT_SYNCH and replaces it with two more granular statuses: THREADSTATUS_WAIT_SYNCH_ANY when a thread waits on objects via WaitSynchronization1 or WaitSynchronizationN with wait_all = false. THREADSTATUS_WAIT_SYNCH_ALL when a thread waits on objects via WaitSynchronizationN with wait_all = true. --- src/core/hle/kernel/thread.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src/core/hle/kernel/thread.h') diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index e2f0cc831..6cd8c20e2 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -31,13 +31,14 @@ enum ThreadProcessorId : s32 { }; enum ThreadStatus { - THREADSTATUS_RUNNING, ///< Currently running - THREADSTATUS_READY, ///< Ready to run - THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter - THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC - THREADSTATUS_WAIT_SYNCH, ///< Waiting due to a WaitSynchronization SVC - THREADSTATUS_DORMANT, ///< Created but not yet made ready - THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated + THREADSTATUS_RUNNING, ///< Currently running + THREADSTATUS_READY, ///< Ready to run + THREADSTATUS_WAIT_ARB, ///< Waiting on an address arbiter + THREADSTATUS_WAIT_SLEEP, ///< Waiting due to a SleepThread SVC + THREADSTATUS_WAIT_SYNCH_ANY, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false + THREADSTATUS_WAIT_SYNCH_ALL, ///< Waiting due to WaitSynchronizationN with wait_all = true + THREADSTATUS_DORMANT, ///< Created but not yet made ready + THREADSTATUS_DEAD ///< Run to completion, or forcefully terminated }; namespace Kernel { @@ -158,10 +159,10 @@ public: /** * Returns whether this thread is waiting for all the objects in * its wait list to become ready, as a result of a WaitSynchronizationN call - * with wait_all = true, or a ReplyAndReceive call. + * with wait_all = true. */ bool IsSleepingOnWaitAll() const { - return !wait_objects.empty(); + return status == THREADSTATUS_WAIT_SYNCH_ALL; } ARM_Interface::ThreadContext context; -- cgit v1.2.3 From fd95b6ee2606da4cd47c5f2916ad3b4f86c0e0f4 Mon Sep 17 00:00:00 2001 From: Subv Date: Wed, 4 Jan 2017 10:53:01 -0500 Subject: Kernel: Remove Thread::wait_objects_index and use wait_objects to hold all the objects that a thread is waiting on. --- src/core/hle/kernel/thread.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'src/core/hle/kernel/thread.h') diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 6cd8c20e2..af72b76ea 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -135,13 +135,14 @@ public: /** * Retrieves the index that this particular object occupies in the list of objects - * that the thread passed to WaitSynchronizationN. + * that the thread passed to WaitSynchronizationN, starting the search from the last element. * It is used to set the output value of WaitSynchronizationN when the thread is awakened. + * When a thread wakes up due to an object signal, the kernel will use the index of the last + * matching object in the wait objects list in case of having multiple instances of the same + * object in the list. * @param object Object to query the index of. */ - s32 GetWaitObjectIndex(const WaitObject* object) const { - return wait_objects_index.at(object->GetObjectId()); - } + s32 GetWaitObjectIndex(WaitObject* object) const; /** * Stops a thread, invalidating it from further use @@ -190,13 +191,10 @@ public: SharedPtr owner_process; ///< Process that owns this thread - /// Objects that the thread is waiting on. - /// This is only populated when the thread should wait for all the objects to become ready. + /// Objects that the thread is waiting on, in the same order as they were + // passed to WaitSynchronization1/N. std::vector> wait_objects; - /// Mapping of Object ids to their position in the last waitlist that this object waited on. - boost::container::flat_map wait_objects_index; - VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address /// True if the WaitSynchronizationN output parameter should be set on thread wakeup. -- cgit v1.2.3