summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2015-01-07 20:45:05 -0500
committerGravatar bunnei2015-01-07 20:45:05 -0500
commit91d96840ea698edaf5f2b6e8522d18f00bb18d9c (patch)
treee9e6288406b16f2a8dd10236c96567a895af3410 /src
parentMerge pull request #404 from bunnei/more-frame-synch-fixes (diff)
parentThreads: Use a dummy idle thread when no other are ready. (diff)
downloadyuzu-91d96840ea698edaf5f2b6e8522d18f00bb18d9c.tar.gz
yuzu-91d96840ea698edaf5f2b6e8522d18f00bb18d9c.tar.xz
yuzu-91d96840ea698edaf5f2b6e8522d18f00bb18d9c.zip
Merge pull request #439 from Subv/idle_thread_m
Threads: Use a dummy idle thread when no other are ready.
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp13
-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
4 files changed, 47 insertions, 2 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 8ac4481cc..98f8a7dff 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -5,6 +5,7 @@
5#include "common/common_types.h" 5#include "common/common_types.h"
6 6
7#include "core/core.h" 7#include "core/core.h"
8#include "core/core_timing.h"
8 9
9#include "core/settings.h" 10#include "core/settings.h"
10#include "core/arm/disassembler/arm_disasm.h" 11#include "core/arm/disassembler/arm_disasm.h"
@@ -23,7 +24,17 @@ ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core
23 24
24/// Run the core CPU loop 25/// Run the core CPU loop
25void RunLoop(int tight_loop) { 26void RunLoop(int tight_loop) {
26 g_app_core->Run(tight_loop); 27 // If the current thread is an idle thread, then don't execute instructions,
28 // instead advance to the next event and try to yield to the next thread
29 if (Kernel::IsIdleThread(Kernel::GetCurrentThreadHandle())) {
30 LOG_TRACE(Core_ARM11, "Idling");
31 CoreTiming::Idle();
32 CoreTiming::Advance();
33 HLE::Reschedule(__func__);
34 } else {
35 g_app_core->Run(tight_loop);
36 }
37
27 HW::Update(); 38 HW::Update();
28 if (HLE::g_reschedule) { 39 if (HLE::g_reschedule) {
29 Kernel::Reschedule(); 40 Kernel::Reschedule();
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