فهرست منبع

Kernel: Use separate Handle tables for CoreTiming userdata

This is to support the removal of GetHandle soon
Yuri Kunde Schlesner 11 سال پیش
والد
کامیت
a9b86db3cf
4فایلهای تغییر یافته به همراه25 افزوده شده و 18 حذف شده
  1. 11 11
      src/core/hle/kernel/thread.cpp
  2. 3 0
      src/core/hle/kernel/thread.h
  3. 8 7
      src/core/hle/kernel/timer.cpp
  4. 3 0
      src/core/hle/kernel/timer.h

+ 11 - 11
src/core/hle/kernel/thread.cpp

@@ -4,7 +4,6 @@
 
 #include <algorithm>
 #include <list>
-#include <map>
 #include <vector>
 
 #include "common/common.h"
@@ -228,13 +227,15 @@ void WaitCurrentThread_ArbitrateAddress(VAddr wait_address) {
 
 /// Event type for the thread wake up event
 static int ThreadWakeupEventType = -1;
+// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
+//               us to simply use a pool index or similar.
+static Kernel::HandleTable wakeup_callback_handle_table;
 
 /// Callback that will wake up the thread it was scheduled for
-static void ThreadWakeupCallback(u64 parameter, int cycles_late) {
-    Handle handle = static_cast<Handle>(parameter);
-    SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(handle);
+static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
+    SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle);
     if (thread == nullptr) {
-        LOG_ERROR(Kernel, "Thread doesn't exist %u", handle);
+        LOG_CRITICAL(Kernel, "Callback fired for invalid thread %08X", thread_handle);
         return;
     }
 
@@ -254,7 +255,7 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
         return;
 
     u64 microseconds = nanoseconds / 1000;
-    CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, GetHandle());
+    CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, callback_handle);
 }
 
 void Thread::ReleaseWaitObject(WaitObject* wait_object) {
@@ -301,7 +302,7 @@ void Thread::ReleaseWaitObject(WaitObject* wait_object) {
 
 void Thread::ResumeFromWait() {
     // Cancel any outstanding wakeup events
-    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, GetHandle());
+    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
 
     status &= ~THREADSTATUS_WAIT;
 
@@ -384,6 +385,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
     thread->wait_objects.clear();
     thread->wait_address = 0;
     thread->name = std::move(name);
+    thread->callback_handle = wakeup_callback_handle_table.Create(thread).MoveFrom();
 
     ResetThread(thread.get(), arg, 0);
     CallThread(thread.get());
@@ -419,10 +421,8 @@ void Thread::SetPriority(s32 priority) {
 
 SharedPtr<Thread> SetupIdleThread() {
     // We need to pass a few valid values to get around parameter checking in Thread::Create.
-    auto thread_res = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
-            THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE);
-    _dbg_assert_(Kernel, thread_res.Succeeded());
-    SharedPtr<Thread> thread = std::move(*thread_res);
+    auto thread = Thread::Create("idle", Memory::KERNEL_MEMORY_VADDR, THREADPRIO_LOWEST, 0,
+            THREADPROCESSORID_0, 0, Kernel::DEFAULT_STACK_SIZE).MoveFrom();
 
     thread->idle = true;
     CallThread(thread.get());

+ 3 - 0
src/core/hle/kernel/thread.h

@@ -122,6 +122,9 @@ public:
 
 private:
     Thread() = default;
+
+    /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
+    Handle callback_handle;
 };
 
 /// Sets up the primary application thread

+ 8 - 7
src/core/hle/kernel/timer.cpp

@@ -2,8 +2,6 @@
 // Licensed under GPLv2 or any later version
 // Refer to the license.txt file included.
 
-#include <set>
-
 #include "common/common.h"
 
 #include "core/core_timing.h"
@@ -15,6 +13,9 @@ namespace Kernel {
 
 /// The event type of the generic timer callback event
 static int timer_callback_event_type = -1;
+// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing
+//               us to simply use a pool index or similar.
+static Kernel::HandleTable timer_callback_handle_table;
 
 ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name) {
     SharedPtr<Timer> timer(new Timer);
@@ -26,6 +27,7 @@ ResultVal<SharedPtr<Timer>> Timer::Create(ResetType reset_type, std::string name
     timer->name = std::move(name);
     timer->initial_delay = 0;
     timer->interval_delay = 0;
+    timer->callback_handle = timer_callback_handle_table.Create(timer).MoveFrom();
     return MakeResult<SharedPtr<Timer>>(timer);
 }
 
@@ -45,13 +47,12 @@ void Timer::Set(s64 initial, s64 interval) {
     interval_delay = interval;
 
     u64 initial_microseconds = initial / 1000;
-    // TODO(yuriks): Figure out a replacement for GetHandle here
-    CoreTiming::ScheduleEvent(usToCycles(initial_microseconds), timer_callback_event_type,
-            GetHandle());
+    CoreTiming::ScheduleEvent(usToCycles(initial_microseconds),
+            timer_callback_event_type, callback_handle);
 }
 
 void Timer::Cancel() {
-    CoreTiming::UnscheduleEvent(timer_callback_event_type, GetHandle());
+    CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle);
 }
 
 void Timer::Clear() {
@@ -60,7 +61,7 @@ void Timer::Clear() {
 
 /// The timer callback event, called when a timer is fired
 static void TimerCallback(u64 timer_handle, int cycles_late) {
-    SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(timer_handle);
+    SharedPtr<Timer> timer = timer_callback_handle_table.Get<Timer>(timer_handle);
 
     if (timer == nullptr) {
         LOG_CRITICAL(Kernel, "Callback fired for invalid timer %08X", timer_handle);

+ 3 - 0
src/core/hle/kernel/timer.h

@@ -50,6 +50,9 @@ public:
 
 private:
     Timer() = default;
+
+    /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
+    Handle callback_handle;
 };
 
 /// Initializes the required variables for timers