summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2019-04-25 04:56:08 +0200
committerGitHub <noreply@github.com>2019-04-25 04:56:08 +0200
commit78574e7a470a29e7ef0c1cc062d334d133c60830 (patch)
tree9027d3466f0f588c5f14af0e23c7f7b128c79330 /src/core/hle
parentMerge pull request #2424 from FernandoS27/compat (diff)
parentkernel/thread: Unify wait synchronization types (diff)
downloadyuzu-78574e7a470a29e7ef0c1cc062d334d133c60830.tar
yuzu-78574e7a470a29e7ef0c1cc062d334d133c60830.tar.gz
yuzu-78574e7a470a29e7ef0c1cc062d334d133c60830.tar.bz2
yuzu-78574e7a470a29e7ef0c1cc062d334d133c60830.tar.lz
yuzu-78574e7a470a29e7ef0c1cc062d334d133c60830.tar.xz
yuzu-78574e7a470a29e7ef0c1cc062d334d133c60830.tar.zst
yuzu-78574e7a470a29e7ef0c1cc062d334d133c60830.zip
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/kernel.cpp3
-rw-r--r--src/core/hle/kernel/process.cpp3
-rw-r--r--src/core/hle/kernel/svc.cpp10
-rw-r--r--src/core/hle/kernel/thread.cpp9
-rw-r--r--src/core/hle/kernel/thread.h40
-rw-r--r--src/core/hle/kernel/wait_object.cpp29
6 files changed, 50 insertions, 44 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8539fabe4..757e5f21f 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -46,8 +46,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
bool resume = true;
- if (thread->GetStatus() == ThreadStatus::WaitSynchAny ||
- thread->GetStatus() == ThreadStatus::WaitSynchAll ||
+ if (thread->GetStatus() == ThreadStatus::WaitSynch ||
thread->GetStatus() == ThreadStatus::WaitHLEEvent) {
// Remove the thread from each of its waiting objects' waitlists
for (const auto& object : thread->GetWaitObjects()) {
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 6d7a7e754..20d01fc88 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -147,8 +147,7 @@ void Process::PrepareForTermination() {
continue;
// TODO(Subv): When are the other running/ready threads terminated?
- ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynchAny ||
- thread->GetStatus() == ThreadStatus::WaitSynchAll,
+ ASSERT_MSG(thread->GetStatus() == ThreadStatus::WaitSynch,
"Exiting processes with non-waiting threads is currently unimplemented");
thread->Stop();
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 4c763b288..2dcf174c5 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -424,7 +424,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han
/// Default thread wakeup callback for WaitSynchronization
static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thread> thread,
SharedPtr<WaitObject> object, std::size_t index) {
- ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny);
+ ASSERT(thread->GetStatus() == ThreadStatus::WaitSynch);
if (reason == ThreadWakeupReason::Timeout) {
thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
@@ -502,7 +502,7 @@ static ResultCode WaitSynchronization(Core::System& system, Handle* index, VAddr
}
thread->SetWaitObjects(std::move(objects));
- thread->SetStatus(ThreadStatus::WaitSynchAny);
+ thread->SetStatus(ThreadStatus::WaitSynch);
// Create an event to wake the thread up after the specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
@@ -518,16 +518,14 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
- const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
+ SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
thread_handle);
return ERR_INVALID_HANDLE;
}
- ASSERT(thread->GetStatus() == ThreadStatus::WaitSynchAny);
- thread->SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
- thread->ResumeFromWait();
+ thread->CancelWait();
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index ca52267b2..2abf9efca 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -101,8 +101,7 @@ void Thread::ResumeFromWait() {
ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
switch (status) {
- case ThreadStatus::WaitSynchAll:
- case ThreadStatus::WaitSynchAny:
+ case ThreadStatus::WaitSynch:
case ThreadStatus::WaitHLEEvent:
case ThreadStatus::WaitSleep:
case ThreadStatus::WaitIPC:
@@ -142,6 +141,12 @@ void Thread::ResumeFromWait() {
ChangeScheduler();
}
+void Thread::CancelWait() {
+ ASSERT(GetStatus() == ThreadStatus::WaitSynch);
+ SetWaitSynchronizationResult(ERR_SYNCHRONIZATION_CANCELED);
+ ResumeFromWait();
+}
+
/**
* Resets a thread context, making it ready to be scheduled and run by the CPU
* @param context Thread context to reset
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 411a73b49..f07332f02 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -49,8 +49,7 @@ enum class ThreadStatus {
WaitHLEEvent, ///< Waiting for hle event to finish
WaitSleep, ///< Waiting due to a SleepThread SVC
WaitIPC, ///< Waiting for the reply from an IPC request
- WaitSynchAny, ///< Waiting due to WaitSynch1 or WaitSynchN with wait_all = false
- WaitSynchAll, ///< Waiting due to WaitSynchronizationN with wait_all = true
+ WaitSynch, ///< Waiting due to WaitSynchronization
WaitMutex, ///< Waiting due to an ArbitrateLock svc
WaitCondVar, ///< Waiting due to an WaitProcessWideKey svc
WaitArb, ///< Waiting due to a SignalToAddress/WaitForAddress svc
@@ -169,11 +168,17 @@ public:
return tls_memory;
}
- /**
- * Resumes a thread from waiting
- */
+ /// Resumes a thread from waiting
void ResumeFromWait();
+ /// Cancels a waiting operation that this thread may or may not be within.
+ ///
+ /// When the thread is within a waiting state, this will set the thread's
+ /// waiting result to signal a canceled wait. The function will then resume
+ /// this thread.
+ ///
+ void CancelWait();
+
/**
* Schedules an event to wake up the specified thread after the specified delay
* @param nanoseconds The time this thread will be allowed to sleep for
@@ -184,24 +189,27 @@ public:
void CancelWakeupTimer();
/**
- * Sets the result after the thread awakens (from either WaitSynchronization SVC)
+ * Sets the result after the thread awakens (from svcWaitSynchronization)
* @param result Value to set to the returned result
*/
void SetWaitSynchronizationResult(ResultCode result);
/**
- * Sets the output parameter value after the thread awakens (from WaitSynchronizationN SVC only)
+ * Sets the output parameter value after the thread awakens (from svcWaitSynchronization)
* @param output Value to set to the output parameter
*/
void SetWaitSynchronizationOutput(s32 output);
/**
* Retrieves the index that this particular object occupies in the list of objects
- * 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.
+ * that the thread passed to WaitSynchronization, starting the search from the last element.
+ *
+ * It is used to set the output index of WaitSynchronization 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;
@@ -238,13 +246,9 @@ public:
*/
VAddr GetCommandBufferAddress() const;
- /**
- * 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.
- */
- bool IsSleepingOnWaitAll() const {
- return status == ThreadStatus::WaitSynchAll;
+ /// Returns whether this thread is waiting on objects from a WaitSynchronization call.
+ bool IsSleepingOnWait() const {
+ return status == ThreadStatus::WaitSynch;
}
ThreadContext& GetContext() {
@@ -418,7 +422,7 @@ private:
Process* owner_process;
/// Objects that the thread is waiting on, in the same order as they were
- /// passed to WaitSynchronization1/N.
+ /// passed to WaitSynchronization.
ThreadWaitObjects wait_objects;
/// List of threads that are waiting for a mutex that is held by this thread.
@@ -441,7 +445,7 @@ private:
Handle callback_handle = 0;
/// Callback that will be invoked when the thread is resumed from a waiting state. If the thread
- /// was waiting via WaitSynchronizationN then the object will be the last object that became
+ /// was waiting via WaitSynchronization then the object will be the last object that became
/// available. In case of a timeout, the object will be nullptr.
WakeupCallback wakeup_callback;
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index c8eaf9488..0e96ba872 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -38,8 +38,7 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() const {
const ThreadStatus thread_status = thread->GetStatus();
// The list of waiting threads must not contain threads that are not waiting to be awakened.
- ASSERT_MSG(thread_status == ThreadStatus::WaitSynchAny ||
- thread_status == ThreadStatus::WaitSynchAll ||
+ ASSERT_MSG(thread_status == ThreadStatus::WaitSynch ||
thread_status == ThreadStatus::WaitHLEEvent,
"Inconsistent thread statuses in waiting_threads");
@@ -49,10 +48,10 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() const {
if (ShouldWait(thread.get()))
continue;
- // A thread is ready to run if it's either in ThreadStatus::WaitSynchAny or
- // in ThreadStatus::WaitSynchAll and the rest of the objects it is waiting on are ready.
+ // A thread is ready to run if it's either in ThreadStatus::WaitSynch
+ // and the rest of the objects it is waiting on are ready.
bool ready_to_run = true;
- if (thread_status == ThreadStatus::WaitSynchAll) {
+ if (thread_status == ThreadStatus::WaitSynch) {
ready_to_run = thread->AllWaitObjectsReady();
}
@@ -68,33 +67,35 @@ SharedPtr<Thread> WaitObject::GetHighestPriorityReadyThread() const {
void WaitObject::WakeupWaitingThread(SharedPtr<Thread> thread) {
ASSERT(!ShouldWait(thread.get()));
- if (!thread)
+ if (!thread) {
return;
+ }
- if (!thread->IsSleepingOnWaitAll()) {
- Acquire(thread.get());
- } else {
+ if (thread->IsSleepingOnWait()) {
for (const auto& object : thread->GetWaitObjects()) {
ASSERT(!object->ShouldWait(thread.get()));
object->Acquire(thread.get());
}
+ } else {
+ Acquire(thread.get());
}
const std::size_t index = thread->GetWaitObjectIndex(this);
- for (const auto& object : thread->GetWaitObjects())
+ for (const auto& object : thread->GetWaitObjects()) {
object->RemoveWaitingThread(thread.get());
+ }
thread->ClearWaitObjects();
thread->CancelWakeupTimer();
bool resume = true;
-
- if (thread->HasWakeupCallback())
+ if (thread->HasWakeupCallback()) {
resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Signal, thread, this, index);
-
- if (resume)
+ }
+ if (resume) {
thread->ResumeFromWait();
+ }
}
void WaitObject::WakeupAllWaitingThreads() {