summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Subv2015-01-07 10:10:58 -0500
committerGravatar Subv2015-01-07 20:31:31 -0500
commit60a373a7862a85b8b030ea1b18d01d364ddf8a8b (patch)
treee9e6288406b16f2a8dd10236c96567a895af3410 /src/core/hle/kernel
parentMerge pull request #404 from bunnei/more-frame-synch-fixes (diff)
downloadyuzu-60a373a7862a85b8b030ea1b18d01d364ddf8a8b.tar.gz
yuzu-60a373a7862a85b8b030ea1b18d01d364ddf8a8b.tar.xz
yuzu-60a373a7862a85b8b030ea1b18d01d364ddf8a8b.zip
Threads: Use a dummy idle thread when no other are ready.
This thread will not actually execute instructions, it will only advance the timing/events and try to yield immediately to the next ready thread, if there aren't any ready threads then it will be rescheduled and start its job again.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/thread.cpp23
-rw-r--r--src/core/hle/kernel/thread.h11
3 files changed, 35 insertions, 1 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index e59ed1b57..ae2c11a1c 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -124,6 +124,8 @@ bool LoadExec(u32 entry_point) {
124 124
125 // 0x30 is the typical main thread priority I've seen used so far 125 // 0x30 is the typical main thread priority I've seen used so far
126 g_main_thread = Kernel::SetupMainThread(0x30); 126 g_main_thread = Kernel::SetupMainThread(0x30);
127 // Setup the idle thread
128 Kernel::SetupIdleThread();
127 129
128 return true; 130 return true;
129} 131}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index d76451146..58fb62e89 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -11,6 +11,7 @@
11#include "common/thread_queue_list.h" 11#include "common/thread_queue_list.h"
12 12
13#include "core/core.h" 13#include "core/core.h"
14#include "core/core_timing.h"
14#include "core/hle/hle.h" 15#include "core/hle/hle.h"
15#include "core/hle/kernel/kernel.h" 16#include "core/hle/kernel/kernel.h"
16#include "core/hle/kernel/thread.h" 17#include "core/hle/kernel/thread.h"
@@ -34,6 +35,7 @@ public:
34 inline bool IsReady() const { return (status & THREADSTATUS_READY) != 0; } 35 inline bool IsReady() const { return (status & THREADSTATUS_READY) != 0; }
35 inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; } 36 inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; }
36 inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; } 37 inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; }
38 inline bool IsIdle() const { return idle; }
37 39
38 ResultVal<bool> WaitSynchronization() override { 40 ResultVal<bool> WaitSynchronization() override {
39 const bool wait = status != THREADSTATUS_DORMANT; 41 const bool wait = status != THREADSTATUS_DORMANT;
@@ -69,6 +71,9 @@ public:
69 std::vector<Handle> waiting_threads; 71 std::vector<Handle> waiting_threads;
70 72
71 std::string name; 73 std::string name;
74
75 /// Whether this thread is intended to never actually be executed, i.e. always idle
76 bool idle = false;
72}; 77};
73 78
74// Lists all thread ids that aren't deleted/etc. 79// Lists all thread ids that aren't deleted/etc.
@@ -444,7 +449,14 @@ ResultCode SetThreadPriority(Handle handle, s32 priority) {
444 return RESULT_SUCCESS; 449 return RESULT_SUCCESS;
445} 450}
446 451
447/// Sets up the primary application thread 452Handle SetupIdleThread() {
453 Handle handle;
454 Thread* thread = CreateThread(handle, "idle", 0, THREADPRIO_LOWEST, THREADPROCESSORID_0, 0, 0);
455 thread->idle = true;
456 CallThread(thread);
457 return handle;
458}
459
448Handle SetupMainThread(s32 priority, int stack_size) { 460Handle SetupMainThread(s32 priority, int stack_size) {
449 Handle handle; 461 Handle handle;
450 462
@@ -497,6 +509,15 @@ void Reschedule() {
497 ResumeThreadFromWait(prev->GetHandle()); 509 ResumeThreadFromWait(prev->GetHandle());
498} 510}
499 511
512bool IsIdleThread(Handle handle) {
513 Thread* thread = g_handle_table.Get<Thread>(handle);
514 if (!thread) {
515 LOG_ERROR(Kernel, "Thread not found %u", handle);
516 return false;
517 }
518 return thread->IsIdle();
519}
520
500ResultCode GetThreadId(u32* thread_id, Handle handle) { 521ResultCode GetThreadId(u32* thread_id, Handle handle) {
501 Thread* thread = g_handle_table.Get<Thread>(handle); 522 Thread* thread = g_handle_table.Get<Thread>(handle);
502 if (thread == nullptr) 523 if (thread == nullptr)
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 0e1397cd9..dfe92d162 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -104,6 +104,17 @@ ResultVal<u32> GetThreadPriority(const Handle handle);
104/// Set the priority of the thread specified by handle 104/// Set the priority of the thread specified by handle
105ResultCode SetThreadPriority(Handle handle, s32 priority); 105ResultCode SetThreadPriority(Handle handle, s32 priority);
106 106
107/**
108 * Sets up the idle thread, this is a thread that is intended to never execute instructions,
109 * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue
110 * and will try to yield on every call.
111 * @returns The handle of the idle thread
112 */
113Handle SetupIdleThread();
114
115/// Whether the current thread is an idle thread
116bool IsIdleThread(Handle thread);
117
107/// Initialize threading 118/// Initialize threading
108void ThreadingInit(); 119void ThreadingInit();
109 120