diff options
| author | 2015-01-18 13:25:51 -0500 | |
|---|---|---|
| committer | 2015-01-21 20:47:38 -0500 | |
| commit | e5a9f1c64483e01b7856c581ae5685d0c5ad88dc (patch) | |
| tree | 6ab483afc7aa00bdcff51f0d6b7015b9edd5e5bf /src | |
| parent | WaitSynchronizationN: Improved comments (diff) | |
| download | yuzu-e5a9f1c64483e01b7856c581ae5685d0c5ad88dc.tar.gz yuzu-e5a9f1c64483e01b7856c581ae5685d0c5ad88dc.tar.xz yuzu-e5a9f1c64483e01b7856c581ae5685d0c5ad88dc.zip | |
Kernel: Get rid of WaitTypes and simplify lots of code, removing hacks.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/event.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/semaphore.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 65 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 41 | ||||
| -rw-r--r-- | src/core/hle/kernel/timer.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 30 |
9 files changed, 63 insertions, 122 deletions
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index ae9b06b84..399730cb1 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp | |||
| @@ -28,13 +28,8 @@ public: | |||
| 28 | bool signaled; ///< Whether the event has already been signaled | 28 | bool signaled; ///< Whether the event has already been signaled |
| 29 | std::string name; ///< Name of event (optional) | 29 | std::string name; ///< Name of event (optional) |
| 30 | 30 | ||
| 31 | ResultVal<bool> Wait(bool wait_thread) override { | 31 | ResultVal<bool> Wait() override { |
| 32 | bool wait = !signaled; | 32 | return MakeResult<bool>(!signaled); |
| 33 | if (wait && wait_thread) { | ||
| 34 | AddWaitingThread(GetCurrentThread()); | ||
| 35 | Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_EVENT, this); | ||
| 36 | } | ||
| 37 | return MakeResult<bool>(wait); | ||
| 38 | } | 33 | } |
| 39 | 34 | ||
| 40 | ResultVal<bool> Acquire() override { | 35 | ResultVal<bool> Acquire() override { |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index be3495412..57e0e8df7 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -42,13 +42,15 @@ Thread* WaitObject::ReleaseNextThread() { | |||
| 42 | return next_thread.get(); | 42 | return next_thread.get(); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | void WaitObject::ReleaseAllWaitingThreads() { | 45 | void WaitObject::WakeupAllWaitingThreads() { |
| 46 | auto waiting_threads_copy = waiting_threads; | 46 | auto waiting_threads_copy = waiting_threads; |
| 47 | 47 | ||
| 48 | // We use a copy because ReleaseWaitObject will remove the thread from this object's | ||
| 49 | // waiting_threads list | ||
| 48 | for (auto thread : waiting_threads_copy) | 50 | for (auto thread : waiting_threads_copy) |
| 49 | thread->ReleaseWaitObject(this); | 51 | thread->ReleaseWaitObject(this); |
| 50 | 52 | ||
| 51 | waiting_threads.clear(); | 53 | _assert_msg_(Kernel, waiting_threads.empty(), "failed to awaken all waiting threads!"); |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 54 | HandleTable::HandleTable() { | 56 | HandleTable::HandleTable() { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index cfaf0c901..5bf9a2bfc 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -65,11 +65,10 @@ public: | |||
| 65 | virtual Kernel::HandleType GetHandleType() const = 0; | 65 | virtual Kernel::HandleType GetHandleType() const = 0; |
| 66 | 66 | ||
| 67 | /** | 67 | /** |
| 68 | * Check if this object is available, (optionally) wait the current thread if not | 68 | * Check if this object is available |
| 69 | * @param wait_thread If true, wait the current thread if this object is unavailable | ||
| 70 | * @return True if the current thread should wait due to this object being unavailable | 69 | * @return True if the current thread should wait due to this object being unavailable |
| 71 | */ | 70 | */ |
| 72 | virtual ResultVal<bool> Wait(bool wait_thread) { | 71 | virtual ResultVal<bool> Wait() { |
| 73 | LOG_ERROR(Kernel, "(UNIMPLEMENTED)"); | 72 | LOG_ERROR(Kernel, "(UNIMPLEMENTED)"); |
| 74 | return UnimplementedFunction(ErrorModule::Kernel); | 73 | return UnimplementedFunction(ErrorModule::Kernel); |
| 75 | } | 74 | } |
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index f97c69a78..4a1eaca37 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp | |||
| @@ -26,7 +26,7 @@ public: | |||
| 26 | Handle lock_thread; ///< Handle to thread that currently has mutex | 26 | Handle lock_thread; ///< Handle to thread that currently has mutex |
| 27 | std::string name; ///< Name of mutex (optional) | 27 | std::string name; ///< Name of mutex (optional) |
| 28 | 28 | ||
| 29 | ResultVal<bool> Wait(bool wait_thread) override; | 29 | ResultVal<bool> Wait() override; |
| 30 | ResultVal<bool> Acquire() override; | 30 | ResultVal<bool> Acquire() override; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| @@ -156,12 +156,7 @@ Handle CreateMutex(bool initial_locked, const std::string& name) { | |||
| 156 | return handle; | 156 | return handle; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | ResultVal<bool> Mutex::Wait(bool wait_thread) { | 159 | ResultVal<bool> Mutex::Wait() { |
| 160 | if (locked && wait_thread) { | ||
| 161 | AddWaitingThread(GetCurrentThread()); | ||
| 162 | Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_MUTEX, this); | ||
| 163 | } | ||
| 164 | |||
| 165 | return MakeResult<bool>(locked); | 160 | return MakeResult<bool>(locked); |
| 166 | } | 161 | } |
| 167 | 162 | ||
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 42b5cf704..6ccdb2a8f 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp | |||
| @@ -32,15 +32,8 @@ public: | |||
| 32 | return available_count > 0; | 32 | return available_count > 0; |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | ResultVal<bool> Wait(bool wait_thread) override { | 35 | ResultVal<bool> Wait() override { |
| 36 | bool wait = !IsAvailable(); | 36 | return MakeResult<bool>(!IsAvailable()); |
| 37 | |||
| 38 | if (wait && wait_thread) { | ||
| 39 | Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_SEMA, this); | ||
| 40 | AddWaitingThread(GetCurrentThread()); | ||
| 41 | } | ||
| 42 | |||
| 43 | return MakeResult<bool>(wait); | ||
| 44 | } | 37 | } |
| 45 | 38 | ||
| 46 | ResultVal<bool> Acquire() override { | 39 | ResultVal<bool> Acquire() override { |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 62b85f56a..601e0eb20 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -22,14 +22,8 @@ | |||
| 22 | 22 | ||
| 23 | namespace Kernel { | 23 | namespace Kernel { |
| 24 | 24 | ||
| 25 | ResultVal<bool> Thread::Wait(bool wait_thread) { | 25 | ResultVal<bool> Thread::Wait() { |
| 26 | const bool wait = status != THREADSTATUS_DORMANT; | 26 | return MakeResult<bool>(status != THREADSTATUS_DORMANT); |
| 27 | if (wait && wait_thread) { | ||
| 28 | AddWaitingThread(GetCurrentThread()); | ||
| 29 | WaitCurrentThread_WaitSynchronization(WAITTYPE_THREADEND, this); | ||
| 30 | } | ||
| 31 | |||
| 32 | return MakeResult<bool>(wait); | ||
| 33 | } | 27 | } |
| 34 | 28 | ||
| 35 | ResultVal<bool> Thread::Acquire() { | 29 | ResultVal<bool> Thread::Acquire() { |
| @@ -68,7 +62,7 @@ static void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { | |||
| 68 | if (t->current_priority < lowest_priority) { | 62 | if (t->current_priority < lowest_priority) { |
| 69 | t->current_priority = t->initial_priority; | 63 | t->current_priority = t->initial_priority; |
| 70 | } | 64 | } |
| 71 | t->wait_type = WAITTYPE_NONE; | 65 | |
| 72 | t->wait_objects.clear(); | 66 | t->wait_objects.clear(); |
| 73 | t->wait_address = 0; | 67 | t->wait_address = 0; |
| 74 | } | 68 | } |
| @@ -89,23 +83,18 @@ static void ChangeReadyState(Thread* t, bool ready) { | |||
| 89 | } | 83 | } |
| 90 | } | 84 | } |
| 91 | 85 | ||
| 92 | /// Check if a thread is blocking on a specified wait type | 86 | /// Check if a thread is blocking on a the specified object |
| 93 | static bool CheckWaitType(const Thread* thread, WaitType type) { | 87 | static bool CheckWaitType(const Thread* thread, Object* wait_object) { |
| 94 | return (type == thread->wait_type) && (thread->IsWaiting()); | ||
| 95 | } | ||
| 96 | |||
| 97 | /// Check if a thread is blocking on a specified wait type with a specified handle | ||
| 98 | static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object) { | ||
| 99 | for (auto itr = thread->wait_objects.begin(); itr != thread->wait_objects.end(); ++itr) { | 88 | for (auto itr = thread->wait_objects.begin(); itr != thread->wait_objects.end(); ++itr) { |
| 100 | if (*itr == wait_object) | 89 | if (*itr == wait_object) |
| 101 | return CheckWaitType(thread, type); | 90 | return (thread->IsWaiting()); |
| 102 | } | 91 | } |
| 103 | return false; | 92 | return false; |
| 104 | } | 93 | } |
| 105 | 94 | ||
| 106 | /// Check if a thread is blocking on a specified wait type with a specified handle and address | 95 | /// Check if a thread is blocking on a the specified object and an address |
| 107 | static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object, VAddr wait_address) { | 96 | static bool CheckWaitType(const Thread* thread, Object* wait_object, VAddr wait_address) { |
| 108 | return CheckWaitType(thread, type, wait_object) && (wait_address == thread->wait_address); | 97 | return CheckWaitType(thread, wait_object) && (wait_address == thread->wait_address); |
| 109 | } | 98 | } |
| 110 | 99 | ||
| 111 | /// Stops the current thread | 100 | /// Stops the current thread |
| @@ -118,7 +107,6 @@ void Thread::Stop(const char* reason) { | |||
| 118 | ReleaseAllWaitingThreads(); | 107 | ReleaseAllWaitingThreads(); |
| 119 | 108 | ||
| 120 | // Stopped threads are never waiting. | 109 | // Stopped threads are never waiting. |
| 121 | wait_type = WAITTYPE_NONE; | ||
| 122 | wait_objects.clear(); | 110 | wait_objects.clear(); |
| 123 | wait_address = 0; | 111 | wait_address = 0; |
| 124 | } | 112 | } |
| @@ -130,12 +118,6 @@ static void ChangeThreadState(Thread* t, ThreadStatus new_status) { | |||
| 130 | } | 118 | } |
| 131 | ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); | 119 | ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); |
| 132 | t->status = new_status; | 120 | t->status = new_status; |
| 133 | |||
| 134 | if (new_status == THREADSTATUS_WAIT) { | ||
| 135 | if (t->wait_type == WAITTYPE_NONE) { | ||
| 136 | LOG_ERROR(Kernel, "Waittype none not allowed"); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | 121 | } |
| 140 | 122 | ||
| 141 | /// Arbitrate the highest priority thread that is waiting | 123 | /// Arbitrate the highest priority thread that is waiting |
| @@ -145,7 +127,7 @@ Thread* ArbitrateHighestPriorityThread(WaitObject* arbiter, u32 address) { | |||
| 145 | 127 | ||
| 146 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 128 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 147 | for (auto& thread : thread_list) { | 129 | for (auto& thread : thread_list) { |
| 148 | if (!CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address)) | 130 | if (!CheckWaitType(thread.get(), arbiter, address)) |
| 149 | continue; | 131 | continue; |
| 150 | 132 | ||
| 151 | if (thread == nullptr) | 133 | if (thread == nullptr) |
| @@ -170,7 +152,7 @@ void ArbitrateAllThreads(WaitObject* arbiter, u32 address) { | |||
| 170 | 152 | ||
| 171 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... | 153 | // Iterate through threads, find highest priority thread that is waiting to be arbitrated... |
| 172 | for (auto& thread : thread_list) { | 154 | for (auto& thread : thread_list) { |
| 173 | if (CheckWaitType(thread.get(), WAITTYPE_ARB, arbiter, address)) | 155 | if (CheckWaitType(thread.get(), arbiter, address)) |
| 174 | thread->ReleaseFromWait(arbiter); | 156 | thread->ReleaseFromWait(arbiter); |
| 175 | } | 157 | } |
| 176 | } | 158 | } |
| @@ -178,9 +160,6 @@ void ArbitrateAllThreads(WaitObject* arbiter, u32 address) { | |||
| 178 | /// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields) | 160 | /// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields) |
| 179 | static void CallThread(Thread* t) { | 161 | static void CallThread(Thread* t) { |
| 180 | // Stop waiting | 162 | // Stop waiting |
| 181 | if (t->wait_type != WAITTYPE_NONE) { | ||
| 182 | t->wait_type = WAITTYPE_NONE; | ||
| 183 | } | ||
| 184 | ChangeThreadState(t, THREADSTATUS_READY); | 163 | ChangeThreadState(t, THREADSTATUS_READY); |
| 185 | } | 164 | } |
| 186 | 165 | ||
| @@ -201,7 +180,6 @@ static void SwitchContext(Thread* t) { | |||
| 201 | current_thread = t; | 180 | current_thread = t; |
| 202 | ChangeReadyState(t, false); | 181 | ChangeReadyState(t, false); |
| 203 | t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; | 182 | t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; |
| 204 | t->wait_type = WAITTYPE_NONE; | ||
| 205 | Core::g_app_core->LoadContext(t->context); | 183 | Core::g_app_core->LoadContext(t->context); |
| 206 | } else { | 184 | } else { |
| 207 | current_thread = nullptr; | 185 | current_thread = nullptr; |
| @@ -224,23 +202,20 @@ static Thread* NextThread() { | |||
| 224 | return next; | 202 | return next; |
| 225 | } | 203 | } |
| 226 | 204 | ||
| 227 | void WaitCurrentThread(WaitType wait_type) { | 205 | void WaitCurrentThread() { |
| 228 | Thread* thread = GetCurrentThread(); | 206 | Thread* thread = GetCurrentThread(); |
| 229 | thread->wait_type = wait_type; | ||
| 230 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 207 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 231 | } | 208 | } |
| 232 | 209 | ||
| 233 | void WaitCurrentThread_WaitSynchronization(WaitType wait_type, WaitObject* wait_object, unsigned index) { | 210 | void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_all) { |
| 234 | Thread* thread = GetCurrentThread(); | 211 | Thread* thread = GetCurrentThread(); |
| 235 | thread->wait_type = wait_type; | 212 | thread->wait_all = wait_all; |
| 236 | |||
| 237 | thread->wait_objects.push_back(wait_object); | 213 | thread->wait_objects.push_back(wait_object); |
| 238 | |||
| 239 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); | 214 | ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND))); |
| 240 | } | 215 | } |
| 241 | 216 | ||
| 242 | void WaitCurrentThread_ArbitrateAddress(WaitObject* wait_object, VAddr wait_address) { | 217 | void WaitCurrentThread_ArbitrateAddress(WaitObject* wait_object, VAddr wait_address) { |
| 243 | WaitCurrentThread_WaitSynchronization(WaitType::WAITTYPE_ARB, wait_object, 0); | 218 | WaitCurrentThread_WaitSynchronization(wait_object); |
| 244 | GetCurrentThread()->wait_address = wait_address; | 219 | GetCurrentThread()->wait_address = wait_address; |
| 245 | } | 220 | } |
| 246 | 221 | ||
| @@ -287,7 +262,7 @@ void Thread::ReleaseFromWait(WaitObject* wait_object) { | |||
| 287 | 262 | ||
| 288 | // Iterate through all waiting objects to check availability... | 263 | // Iterate through all waiting objects to check availability... |
| 289 | for (auto itr = wait_objects.begin(); itr != wait_objects.end(); ++itr) { | 264 | for (auto itr = wait_objects.begin(); itr != wait_objects.end(); ++itr) { |
| 290 | auto res = (*itr)->Wait(false); | 265 | auto res = (*itr)->Wait(); |
| 291 | 266 | ||
| 292 | if (*res && res.Succeeded()) | 267 | if (*res && res.Succeeded()) |
| 293 | wait_all_failed = true; | 268 | wait_all_failed = true; |
| @@ -322,9 +297,8 @@ void Thread::ResumeFromWait() { | |||
| 322 | wait_object->RemoveWaitingThread(this); | 297 | wait_object->RemoveWaitingThread(this); |
| 323 | 298 | ||
| 324 | wait_objects.clear(); | 299 | wait_objects.clear(); |
| 325 | |||
| 326 | wait_type = WAITTYPE_NONE; | ||
| 327 | wait_all = false; | 300 | wait_all = false; |
| 301 | |||
| 328 | if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | 302 | if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { |
| 329 | ChangeReadyState(this, true); | 303 | ChangeReadyState(this, true); |
| 330 | } | 304 | } |
| @@ -390,7 +364,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 390 | thread->stack_size = stack_size; | 364 | thread->stack_size = stack_size; |
| 391 | thread->initial_priority = thread->current_priority = priority; | 365 | thread->initial_priority = thread->current_priority = priority; |
| 392 | thread->processor_id = processor_id; | 366 | thread->processor_id = processor_id; |
| 393 | thread->wait_type = WAITTYPE_NONE; | ||
| 394 | thread->wait_all = false; | 367 | thread->wait_all = false; |
| 395 | thread->wait_objects.clear(); | 368 | thread->wait_objects.clear(); |
| 396 | thread->wait_address = 0; | 369 | thread->wait_address = 0; |
| @@ -476,8 +449,8 @@ void Reschedule() { | |||
| 476 | LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); | 449 | LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); |
| 477 | 450 | ||
| 478 | for (auto& thread : thread_list) { | 451 | for (auto& thread : thread_list) { |
| 479 | LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X", | 452 | LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X", thread->GetHandle(), |
| 480 | thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type); | 453 | thread->current_priority, thread->status); |
| 481 | } | 454 | } |
| 482 | } | 455 | } |
| 483 | } | 456 | } |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index dff6bbaec..cb48fcadc 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -38,18 +38,6 @@ enum ThreadStatus { | |||
| 38 | THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND | 38 | THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND |
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | enum WaitType { | ||
| 42 | WAITTYPE_NONE, | ||
| 43 | WAITTYPE_SLEEP, | ||
| 44 | WAITTYPE_SEMA, | ||
| 45 | WAITTYPE_EVENT, | ||
| 46 | WAITTYPE_THREADEND, | ||
| 47 | WAITTYPE_MUTEX, | ||
| 48 | WAITTYPE_SYNCH, | ||
| 49 | WAITTYPE_ARB, | ||
| 50 | WAITTYPE_TIMER, | ||
| 51 | }; | ||
| 52 | |||
| 53 | namespace Kernel { | 41 | namespace Kernel { |
| 54 | 42 | ||
| 55 | class Thread : public WaitObject { | 43 | class Thread : public WaitObject { |
| @@ -70,7 +58,7 @@ public: | |||
| 70 | inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } | 58 | inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } |
| 71 | inline bool IsIdle() const { return idle; } | 59 | inline bool IsIdle() const { return idle; } |
| 72 | 60 | ||
| 73 | ResultVal<bool> Wait(bool wait_thread) override; | 61 | ResultVal<bool> Wait() override; |
| 74 | ResultVal<bool> Acquire() override; | 62 | ResultVal<bool> Acquire() override; |
| 75 | 63 | ||
| 76 | s32 GetPriority() const { return current_priority; } | 64 | s32 GetPriority() const { return current_priority; } |
| @@ -90,12 +78,6 @@ public: | |||
| 90 | void ResumeFromWait(); | 78 | void ResumeFromWait(); |
| 91 | 79 | ||
| 92 | /** | 80 | /** |
| 93 | * Sets the waiting mode of the thread | ||
| 94 | * @param wait_all If true, wait for all objects, otherwise just wait for the first one | ||
| 95 | */ | ||
| 96 | void SetWaitAll(bool wait_all) { this->wait_all = wait_all; } | ||
| 97 | |||
| 98 | /** | ||
| 99 | * Sets the output values after the thread awakens from WaitSynchronization | 81 | * Sets the output values after the thread awakens from WaitSynchronization |
| 100 | * @param return_val Value returned | 82 | * @param return_val Value returned |
| 101 | * @param out_val Value to set to the output parameter | 83 | * @param out_val Value to set to the output parameter |
| @@ -116,9 +98,10 @@ public: | |||
| 116 | 98 | ||
| 117 | s32 processor_id; | 99 | s32 processor_id; |
| 118 | 100 | ||
| 119 | WaitType wait_type; | 101 | std::vector<SharedPtr<WaitObject>> wait_objects; ///< Objects that the thread is waiting on |
| 120 | std::vector<SharedPtr<WaitObject>> wait_objects; | 102 | |
| 121 | VAddr wait_address; | 103 | VAddr wait_address; ///< If waiting on an AddressArbiter, this is the arbitration address |
| 104 | bool wait_all; ///< True if the thread is waiting on all objects before resuming | ||
| 122 | 105 | ||
| 123 | std::string name; | 106 | std::string name; |
| 124 | 107 | ||
| @@ -126,7 +109,6 @@ public: | |||
| 126 | bool idle = false; | 109 | bool idle = false; |
| 127 | 110 | ||
| 128 | private: | 111 | private: |
| 129 | bool wait_all = false; | ||
| 130 | 112 | ||
| 131 | Thread() = default; | 113 | Thread() = default; |
| 132 | }; | 114 | }; |
| @@ -146,19 +128,15 @@ void ArbitrateAllThreads(WaitObject* arbiter, u32 address); | |||
| 146 | /// Gets the current thread | 128 | /// Gets the current thread |
| 147 | Thread* GetCurrentThread(); | 129 | Thread* GetCurrentThread(); |
| 148 | 130 | ||
| 149 | /** | 131 | /// Waits the current thread |
| 150 | * Waits the current thread for the given type | 132 | void WaitCurrentThread(); |
| 151 | * @param wait_type Type of wait | ||
| 152 | */ | ||
| 153 | void WaitCurrentThread(WaitType wait_type); | ||
| 154 | 133 | ||
| 155 | /** | 134 | /** |
| 156 | * Waits the current thread from a WaitSynchronization call | 135 | * Waits the current thread from a WaitSynchronization call |
| 157 | * @param wait_type Type of wait | ||
| 158 | * @param wait_object Kernel object that we are waiting on | 136 | * @param wait_object Kernel object that we are waiting on |
| 159 | * @param index Index of calling object (for WaitSynchronizationN only) | 137 | * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only) |
| 160 | */ | 138 | */ |
| 161 | void WaitCurrentThread_WaitSynchronization(WaitType wait_type, WaitObject* wait_object, unsigned index=0); | 139 | void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_all=false); |
| 162 | 140 | ||
| 163 | /** | 141 | /** |
| 164 | * Waits the current thread from an ArbitrateAddress call | 142 | * Waits the current thread from an ArbitrateAddress call |
| @@ -181,6 +159,7 @@ void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds); | |||
| 181 | * @returns The handle of the idle thread | 159 | * @returns The handle of the idle thread |
| 182 | */ | 160 | */ |
| 183 | Handle SetupIdleThread(); | 161 | Handle SetupIdleThread(); |
| 162 | |||
| 184 | /// Initialize threading | 163 | /// Initialize threading |
| 185 | void ThreadingInit(); | 164 | void ThreadingInit(); |
| 186 | 165 | ||
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 9f0fbafe2..62bdf07c7 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp | |||
| @@ -29,13 +29,8 @@ public: | |||
| 29 | u64 initial_delay; ///< The delay until the timer fires for the first time | 29 | u64 initial_delay; ///< The delay until the timer fires for the first time |
| 30 | u64 interval_delay; ///< The delay until the timer fires after the first time | 30 | u64 interval_delay; ///< The delay until the timer fires after the first time |
| 31 | 31 | ||
| 32 | ResultVal<bool> Wait(bool wait_thread) override { | 32 | ResultVal<bool> Wait() override { |
| 33 | bool wait = !signaled; | 33 | return MakeResult<bool>(!signaled); |
| 34 | if (wait && wait_thread) { | ||
| 35 | AddWaitingThread(GetCurrentThread()); | ||
| 36 | Kernel::WaitCurrentThread_WaitSynchronization(WAITTYPE_TIMER, this); | ||
| 37 | } | ||
| 38 | return MakeResult<bool>(wait); | ||
| 39 | } | 34 | } |
| 40 | 35 | ||
| 41 | ResultVal<bool> Acquire() override { | 36 | ResultVal<bool> Acquire() override { |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 01b536084..2d5f41af6 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -105,7 +105,7 @@ static Result SendSyncRequest(Handle handle) { | |||
| 105 | 105 | ||
| 106 | ResultVal<bool> wait = session->SyncRequest(); | 106 | ResultVal<bool> wait = session->SyncRequest(); |
| 107 | if (wait.Succeeded() && *wait) { | 107 | if (wait.Succeeded() && *wait) { |
| 108 | Kernel::WaitCurrentThread(WAITTYPE_SYNCH); // TODO(bunnei): Is this correct? | 108 | Kernel::WaitCurrentThread(); // TODO(bunnei): Is this correct? |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | return wait.Code().raw; | 111 | return wait.Code().raw; |
| @@ -120,22 +120,24 @@ static Result CloseHandle(Handle handle) { | |||
| 120 | 120 | ||
| 121 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds | 121 | /// Wait for a handle to synchronize, timeout after the specified nanoseconds |
| 122 | static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { | 122 | static Result WaitSynchronization1(Handle handle, s64 nano_seconds) { |
| 123 | SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handle); | 123 | Kernel::WaitObject* object = static_cast<Kernel::WaitObject*>(Kernel::g_handle_table.GetGeneric(handle).get()); |
| 124 | if (object == nullptr) | 124 | if (object == nullptr) |
| 125 | return InvalidHandle(ErrorModule::Kernel).raw; | 125 | return InvalidHandle(ErrorModule::Kernel).raw; |
| 126 | 126 | ||
| 127 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, | 127 | LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, |
| 128 | object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); | 128 | object->GetTypeName().c_str(), object->GetName().c_str(), nano_seconds); |
| 129 | 129 | ||
| 130 | ResultVal<bool> wait = object->Wait(true); | 130 | ResultVal<bool> wait = object->Wait(); |
| 131 | 131 | ||
| 132 | // Check for next thread to schedule | 132 | // Check for next thread to schedule |
| 133 | if (wait.Succeeded() && *wait) { | 133 | if (wait.Succeeded() && *wait) { |
| 134 | |||
| 135 | object->AddWaitingThread(Kernel::GetCurrentThread()); | ||
| 136 | Kernel::WaitCurrentThread_WaitSynchronization(object); | ||
| 137 | |||
| 134 | // Create an event to wake the thread up after the specified nanosecond delay has passed | 138 | // Create an event to wake the thread up after the specified nanosecond delay has passed |
| 135 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); | 139 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); |
| 136 | 140 | ||
| 137 | Kernel::GetCurrentThread()->SetWaitAll(false); | ||
| 138 | |||
| 139 | HLE::Reschedule(__func__); | 141 | HLE::Reschedule(__func__); |
| 140 | } else { | 142 | } else { |
| 141 | object->Acquire(); | 143 | object->Acquire(); |
| @@ -166,14 +168,15 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 166 | if (handle_count != 0) { | 168 | if (handle_count != 0) { |
| 167 | bool selected = false; // True once an object has been selected | 169 | bool selected = false; // True once an object has been selected |
| 168 | for (int i = 0; i < handle_count; ++i) { | 170 | for (int i = 0; i < handle_count; ++i) { |
| 169 | SharedPtr<Kernel::Object> object = Kernel::g_handle_table.GetGeneric(handles[i]); | 171 | Kernel::WaitObject* object = static_cast<Kernel::WaitObject*>(Kernel::g_handle_table.GetGeneric(handles[i]).get()); |
| 170 | if (object == nullptr) | 172 | if (object == nullptr) |
| 171 | return InvalidHandle(ErrorModule::Kernel).raw; | 173 | return InvalidHandle(ErrorModule::Kernel).raw; |
| 172 | 174 | ||
| 173 | ResultVal<bool> wait = object->Wait(true); | 175 | ResultVal<bool> wait = object->Wait(); |
| 174 | 176 | ||
| 175 | // Check if the current thread should wait on this object... | 177 | // Check if the current thread should wait on this object... |
| 176 | if (wait.Succeeded() && *wait) { | 178 | if (wait.Succeeded() && *wait) { |
| 179 | |||
| 177 | // Check we are waiting on all objects... | 180 | // Check we are waiting on all objects... |
| 178 | if (wait_all) | 181 | if (wait_all) |
| 179 | // Wait the thread | 182 | // Wait the thread |
| @@ -193,15 +196,22 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count, | |||
| 193 | // NOTE: This should deadlock the current thread if no timeout was specified | 196 | // NOTE: This should deadlock the current thread if no timeout was specified |
| 194 | if (!wait_all) { | 197 | if (!wait_all) { |
| 195 | wait_thread = true; | 198 | wait_thread = true; |
| 196 | Kernel::WaitCurrentThread(WAITTYPE_SLEEP); | 199 | Kernel::WaitCurrentThread(); |
| 197 | } | 200 | } |
| 198 | } | 201 | } |
| 199 | 202 | ||
| 200 | // If thread should wait, then set its state to waiting and then reschedule... | 203 | // If thread should wait, then set its state to waiting and then reschedule... |
| 201 | if (wait_thread) { | 204 | if (wait_thread) { |
| 205 | |||
| 206 | // Actually wait the current thread on each object if we decided to wait... | ||
| 207 | for (int i = 0; i < handle_count; ++i) { | ||
| 208 | auto object = Kernel::g_handle_table.GetWaitObject(handles[i]); | ||
| 209 | object->AddWaitingThread(Kernel::GetCurrentThread()); | ||
| 210 | Kernel::WaitCurrentThread_WaitSynchronization(object, wait_all); | ||
| 211 | } | ||
| 212 | |||
| 202 | // Create an event to wake the thread up after the specified nanosecond delay has passed | 213 | // Create an event to wake the thread up after the specified nanosecond delay has passed |
| 203 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); | 214 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nano_seconds); |
| 204 | Kernel::GetCurrentThread()->SetWaitAll(wait_all); | ||
| 205 | 215 | ||
| 206 | HLE::Reschedule(__func__); | 216 | HLE::Reschedule(__func__); |
| 207 | 217 | ||
| @@ -440,7 +450,7 @@ static void SleepThread(s64 nanoseconds) { | |||
| 440 | LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); | 450 | LOG_TRACE(Kernel_SVC, "called nanoseconds=%lld", nanoseconds); |
| 441 | 451 | ||
| 442 | // Sleep current thread and check for next thread to schedule | 452 | // Sleep current thread and check for next thread to schedule |
| 443 | Kernel::WaitCurrentThread(WAITTYPE_SLEEP); | 453 | Kernel::WaitCurrentThread(); |
| 444 | 454 | ||
| 445 | // Create an event to wake the thread up after the specified nanosecond delay has passed | 455 | // Create an event to wake the thread up after the specified nanosecond delay has passed |
| 446 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds); | 456 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds); |