Skip to content

Instantly share code, notes, and snippets.

@Subv
Created January 6, 2015 19:32
Show Gist options
  • Save Subv/ee7756fcd8d701a65a9b to your computer and use it in GitHub Desktop.
Save Subv/ee7756fcd8d701a65a9b to your computer and use it in GitHub Desktop.
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index ea89d6e..3026822 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -10,6 +10,8 @@
#include "core/arm/dyncom/arm_dyncom_interpreter.h"
#include "core/core_timing.h"
+#include "core/hle/kernel/thread.h"
+#include "core/hle/hle.h"
const static cpu_config_t s_arm11_cpu_info = {
"armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE
@@ -85,6 +87,14 @@ void ARM_DynCom::AddTicks(u64 ticks) {
}
void ARM_DynCom::ExecuteInstructions(int num_instructions) {
+ if (Kernel::IsIdleThread(Kernel::GetCurrentThreadHandle())) {
+ LOG_CRITICAL(Common, "Idling");
+ CoreTiming::Idle();
+ CoreTiming::Advance();
+ HLE::Reschedule(__func__);
+ return;
+ }
+
state->NumInstrsToExecute = num_instructions;
// Dyncom only breaks on instruction dispatch. This only happens on every instruction when
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 084fd03..8d6204d 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -127,6 +127,8 @@ bool LoadExec(u32 entry_point) {
// 0x30 is the typical main thread priority I've seen used so far
g_main_thread = Kernel::SetupMainThread(0x30);
+ Kernel::SetupIdleThread();
+
return true;
}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 872df2d..8775547 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -11,6 +11,7 @@
#include "common/thread_queue_list.h"
#include "core/core.h"
+#include "core/core_timing.h"
#include "core/hle/hle.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/thread.h"
@@ -34,6 +35,7 @@ public:
inline bool IsReady() const { return (status & THREADSTATUS_READY) != 0; }
inline bool IsWaiting() const { return (status & THREADSTATUS_WAIT) != 0; }
inline bool IsSuspended() const { return (status & THREADSTATUS_SUSPEND) != 0; }
+ inline bool IsIdle() const { return idle; }
ResultVal<bool> WaitSynchronization() override {
const bool wait = status != THREADSTATUS_DORMANT;
@@ -69,6 +71,8 @@ public:
std::vector<Handle> waiting_threads;
std::string name;
+
+ bool idle;
};
// Lists all thread ids that aren't deleted/etc.
@@ -358,6 +362,7 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
thread->wait_handle = 0;
thread->wait_address = 0;
thread->name = name;
+ thread->idle = false;
return thread;
}
@@ -444,7 +449,14 @@ ResultCode SetThreadPriority(Handle handle, s32 priority) {
return RESULT_SUCCESS;
}
-/// Sets up the primary application thread
+Handle SetupIdleThread() {
+ Handle handle;
+ Thread* thread = CreateThread(handle, "idle", 0, THREADPRIO_LOWEST, THREADPROCESSORID_0, 0, 0);
+ thread->idle = true;
+ CallThread(thread);
+ return handle;
+}
+
Handle SetupMainThread(s32 priority, int stack_size) {
Handle handle;
@@ -468,7 +480,6 @@ Handle SetupMainThread(s32 priority, int stack_size) {
return handle;
}
-
/// Reschedules to the next available thread (call after current thread is suspended)
void Reschedule() {
Thread* prev = GetCurrentThread();
@@ -517,4 +528,11 @@ void ThreadingInit() {
void ThreadingShutdown() {
}
+bool IsIdleThread(Handle handle) {
+ Thread* thread = g_handle_table.Get<Thread>(handle);
+ if (!thread)
+ return false;
+ return thread->IsIdle();
+}
+
} // namespace
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 81736a8..1224f89 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -55,6 +55,11 @@ Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s3
/// Sets up the primary application thread
Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE);
+/// Sets up the idle thread
+Handle SetupIdleThread();
+
+bool IsIdleThread(Handle thread);
+
/// Reschedules to the next available thread (call after current thread is suspended)
void Reschedule();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment