diff options
25 files changed, 330 insertions, 374 deletions
| diff --git a/src/citra_qt/debugger/disassembler.cpp b/src/citra_qt/debugger/disassembler.cpp index 8db73752f..da084ab24 100644 --- a/src/citra_qt/debugger/disassembler.cpp +++ b/src/citra_qt/debugger/disassembler.cpp @@ -13,6 +13,7 @@  #include "core/core.h"  #include "common/break_points.h"  #include "common/symbols.h" +#include "core/arm/arm_interface.h"  #include "core/arm/skyeye_common/armdefs.h"  #include "core/arm/disassembler/arm_disasm.h" diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index d3bd4a9a3..e612f7439 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -7,7 +7,9 @@  #include "common/common.h"  #include "common/common_types.h" -#include "core/hle/svc.h" +namespace Core { +    struct ThreadContext; +}  /// Generic ARM11 CPU interface  class ARM_Interface : NonCopyable { @@ -87,13 +89,13 @@ public:       * Saves the current CPU context       * @param ctx Thread context to save       */ -    virtual void SaveContext(ThreadContext& ctx) = 0; +    virtual void SaveContext(Core::ThreadContext& ctx) = 0;      /**       * Loads a CPU context       * @param ctx Thread context to load       */ -    virtual void LoadContext(const ThreadContext& ctx) = 0; +    virtual void LoadContext(const Core::ThreadContext& ctx) = 0;      /// Prepare core for thread reschedule (if needed to correctly handle state)      virtual void PrepareReschedule() = 0; diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index 31eb879a2..9c4cc90f2 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -9,6 +9,7 @@  #include "core/arm/dyncom/arm_dyncom.h"  #include "core/arm/dyncom/arm_dyncom_interpreter.h" +#include "core/core.h"  #include "core/core_timing.h"  const static cpu_config_t s_arm11_cpu_info = { @@ -94,7 +95,7 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {      AddTicks(ticks_executed);  } -void ARM_DynCom::SaveContext(ThreadContext& ctx) { +void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {      memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));      memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); @@ -110,7 +111,7 @@ void ARM_DynCom::SaveContext(ThreadContext& ctx) {      ctx.mode = state->NextInstr;  } -void ARM_DynCom::LoadContext(const ThreadContext& ctx) { +void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {      memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));      memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 9e102a46e..f16fb070c 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -71,13 +71,13 @@ public:       * Saves the current CPU context       * @param ctx Thread context to save       */ -    void SaveContext(ThreadContext& ctx) override; +    void SaveContext(Core::ThreadContext& ctx) override;      /**       * Loads a CPU context       * @param ctx Thread context to load       */ -    void LoadContext(const ThreadContext& ctx) override; +    void LoadContext(const Core::ThreadContext& ctx) override;      /// Prepare core for thread reschedule (if needed to correctly handle state)      void PrepareReschedule() override; diff --git a/src/core/arm/interpreter/arm_interpreter.cpp b/src/core/arm/interpreter/arm_interpreter.cpp index 80ebc359e..c76d371a2 100644 --- a/src/core/arm/interpreter/arm_interpreter.cpp +++ b/src/core/arm/interpreter/arm_interpreter.cpp @@ -4,6 +4,8 @@  #include "core/arm/interpreter/arm_interpreter.h" +#include "core/core.h" +  const static cpu_config_t arm11_cpu_info = {      "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE  }; @@ -75,7 +77,7 @@ void ARM_Interpreter::ExecuteInstructions(int num_instructions) {      ARMul_Emulate32(state);  } -void ARM_Interpreter::SaveContext(ThreadContext& ctx) { +void ARM_Interpreter::SaveContext(Core::ThreadContext& ctx) {      memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers));      memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); @@ -91,7 +93,7 @@ void ARM_Interpreter::SaveContext(ThreadContext& ctx) {      ctx.mode = state->NextInstr;  } -void ARM_Interpreter::LoadContext(const ThreadContext& ctx) { +void ARM_Interpreter::LoadContext(const Core::ThreadContext& ctx) {      memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers));      memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); diff --git a/src/core/arm/interpreter/arm_interpreter.h b/src/core/arm/interpreter/arm_interpreter.h index 019dad5df..e5ecc69c2 100644 --- a/src/core/arm/interpreter/arm_interpreter.h +++ b/src/core/arm/interpreter/arm_interpreter.h @@ -70,13 +70,13 @@ public:       * Saves the current CPU context       * @param ctx Thread context to save       */ -    void SaveContext(ThreadContext& ctx) override; +    void SaveContext(Core::ThreadContext& ctx) override;      /**       * Loads a CPU context       * @param ctx Thread context to load       */ -    void LoadContext(const ThreadContext& ctx) override; +    void LoadContext(const Core::ThreadContext& ctx) override;      /// Prepare core for thread reschedule (if needed to correctly handle state)      void PrepareReschedule() override; diff --git a/src/core/core.cpp b/src/core/core.cpp index ff506d67d..e9e5c35cc 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -8,6 +8,7 @@  #include "core/core_timing.h"  #include "core/settings.h" +#include "core/arm/arm_interface.h"  #include "core/arm/disassembler/arm_disasm.h"  #include "core/arm/interpreter/arm_interpreter.h"  #include "core/arm/dyncom/arm_dyncom.h" @@ -24,7 +25,7 @@ ARM_Interface*     g_sys_core = nullptr;  ///< ARM11 system (OS) core  void RunLoop(int tight_loop) {      // If the current thread is an idle thread, then don't execute instructions,      // instead advance to the next event and try to yield to the next thread -    if (Kernel::IsIdleThread(Kernel::GetCurrentThreadHandle())) { +    if (Kernel::GetCurrentThread()->IsIdle()) {          LOG_TRACE(Core_ARM11, "Idling");          CoreTiming::Idle();          CoreTiming::Advance(); diff --git a/src/core/core.h b/src/core/core.h index ecd58a73a..2f5e8bc6b 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -4,8 +4,9 @@  #pragma once -#include "core/arm/arm_interface.h" -#include "core/arm/skyeye_common/armdefs.h" +#include "common/common_types.h" + +class ARM_Interface;  //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -16,6 +17,21 @@ enum CPUCore {      CPU_OldInterpreter,  }; +struct ThreadContext { +    u32 cpu_registers[13]; +    u32 sp; +    u32 lr; +    u32 pc; +    u32 cpsr; +    u32 fpu_registers[32]; +    u32 fpscr; +    u32 fpexc; + +    // These are not part of native ThreadContext, but needed by emu +    u32 reg_15; +    u32 mode; +}; +  extern ARM_Interface*   g_app_core;     ///< ARM11 application core  extern ARM_Interface*   g_sys_core;     ///< ARM11 system (OS) core diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 833199680..ec9d52a08 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -9,6 +9,8 @@  #include "common/chunk_file.h"  #include "common/log.h" + +#include "core/arm/arm_interface.h"  #include "core/core.h"  #include "core/core_timing.h" diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 8eb4f252b..a2f51b41b 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -5,6 +5,8 @@  #pragma once  #include "common/common_types.h" + +#include "core/arm/arm_interface.h"  #include "core/mem_map.h"  #include "core/hle/hle.h" diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp index 33ac12507..5d77a1458 100644 --- a/src/core/hle/hle.cpp +++ b/src/core/hle/hle.cpp @@ -4,6 +4,7 @@  #include <vector> +#include "core/arm/arm_interface.h"  #include "core/mem_map.h"  #include "core/hle/hle.h"  #include "core/hle/kernel/thread.h" diff --git a/src/core/hle/hle.h b/src/core/hle/hle.h index 59b770f02..3f6f9a4b5 100644 --- a/src/core/hle/hle.h +++ b/src/core/hle/hle.h @@ -4,6 +4,8 @@  #pragma once +#include <string> +  #include "common/common_types.h"  #include "core/core.h" diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 736bbc36a..28adc5500 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -30,24 +30,28 @@ public:  /// Arbitrate an address  ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) { +    Object* object = Kernel::g_handle_table.GetGeneric(handle); +    if (object == nullptr) +        return InvalidHandle(ErrorModule::Kernel); +      switch (type) {      // Signal thread(s) waiting for arbitrate address...      case ArbitrationType::Signal:          // Negative value means resume all threads          if (value < 0) { -            ArbitrateAllThreads(handle, address); +            ArbitrateAllThreads(object, address);          } else {              // Resume first N threads              for(int i = 0; i < value; i++) -                ArbitrateHighestPriorityThread(handle, address); +                ArbitrateHighestPriorityThread(object, address);          }          break;      // Wait current thread (acquire the arbiter)...      case ArbitrationType::WaitIfLessThan:          if ((s32)Memory::Read32(address) <= value) { -            Kernel::WaitCurrentThread(WAITTYPE_ARB, handle, address); +            Kernel::WaitCurrentThread(WAITTYPE_ARB, object, address);              HLE::Reschedule(__func__);          }          break; @@ -57,7 +61,7 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3          s32 memory_value = Memory::Read32(address) - 1;          Memory::Write32(address, memory_value);          if (memory_value <= value) { -            Kernel::WaitCurrentThread(WAITTYPE_ARB, handle, address); +            Kernel::WaitCurrentThread(WAITTYPE_ARB, object, address);              HLE::Reschedule(__func__);          }          break; diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index e43c3ee4e..697e08681 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -33,11 +33,11 @@ public:      ResultVal<bool> WaitSynchronization() override {          bool wait = locked;          if (locked) { -            Handle thread = GetCurrentThreadHandle(); +            Handle thread = GetCurrentThread()->GetHandle();              if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {                  waiting_threads.push_back(thread);              } -            Kernel::WaitCurrentThread(WAITTYPE_EVENT, GetHandle()); +            Kernel::WaitCurrentThread(WAITTYPE_EVENT, this);          }          if (reset_type != RESETTYPE_STICKY && !permanent_locked) {              locked = true; @@ -88,7 +88,9 @@ ResultCode SignalEvent(const Handle handle) {      // Resume threads waiting for event to signal      bool event_caught = false;      for (size_t i = 0; i < evt->waiting_threads.size(); ++i) { -        ResumeThreadFromWait( evt->waiting_threads[i]); +        Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]); +        if (thread != nullptr) +            thread->ResumeFromWait();          // If any thread is signalled awake by this event, assume the event was "caught" and reset          // the event. This will result in the next thread waiting on the event to block. Otherwise, diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 391e833c0..a1bc6c5d8 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -6,6 +6,7 @@  #include "common/common.h" +#include "core/arm/arm_interface.h"  #include "core/core.h"  #include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/thread.h" @@ -13,7 +14,7 @@  namespace Kernel { -Handle g_main_thread = 0; +Thread* g_main_thread = nullptr;  HandleTable g_handle_table;  u64 g_program_id = 0; @@ -80,8 +81,7 @@ bool HandleTable::IsValid(Handle handle) const {  Object* HandleTable::GetGeneric(Handle handle) const {      if (handle == CurrentThread) { -        // TODO(yuriks) Directly return the pointer once this is possible. -        handle = GetCurrentThreadHandle(); +        return GetCurrentThread();      } else if (handle == CurrentProcess) {          LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);          return nullptr; diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3e381d776..31d80c7ac 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -16,6 +16,8 @@ const Handle INVALID_HANDLE = 0;  namespace Kernel { +class Thread; +  // TODO: Verify code  const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,          ErrorSummary::OutOfResource, ErrorLevel::Temporary); @@ -190,7 +192,7 @@ private:  };  extern HandleTable g_handle_table; -extern Handle g_main_thread; +extern Thread* g_main_thread;  /// The ID code of the currently running game  /// TODO(Subv): This variable should not be here,  diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 3dfeffc9b..7d008f6cc 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -40,14 +40,21 @@ static MutexMap g_mutex_held_locks;   * @param mutex Mutex that is to be acquired   * @param thread Thread that will acquired   */ -void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThreadHandle()) { +void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandle()) {      g_mutex_held_locks.insert(std::make_pair(thread, mutex->GetHandle()));      mutex->lock_thread = thread;  } -bool ReleaseMutexForThread(Mutex* mutex, Handle thread) { -    MutexAcquireLock(mutex, thread); -    Kernel::ResumeThreadFromWait(thread); +bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) { +    MutexAcquireLock(mutex, thread_handle); + +    Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle); +    if (thread == nullptr) { +        LOG_ERROR(Kernel, "Called with invalid handle: %08X", thread_handle); +        return false; +    } + +    thread->ResumeFromWait();      return true;  } @@ -168,8 +175,8 @@ Handle CreateMutex(bool initial_locked, const std::string& name) {  ResultVal<bool> Mutex::WaitSynchronization() {      bool wait = locked;      if (locked) { -        waiting_threads.push_back(GetCurrentThreadHandle()); -        Kernel::WaitCurrentThread(WAITTYPE_MUTEX, GetHandle()); +        waiting_threads.push_back(GetCurrentThread()->GetHandle()); +        Kernel::WaitCurrentThread(WAITTYPE_MUTEX, this);      } else {          // Lock the mutex when the first thread accesses it          locked = true; diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 6bc8066a6..d7eeaa3da 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -37,8 +37,8 @@ public:          bool wait = !IsAvailable();          if (wait) { -            Kernel::WaitCurrentThread(WAITTYPE_SEMA, GetHandle()); -            waiting_threads.push(GetCurrentThreadHandle()); +            Kernel::WaitCurrentThread(WAITTYPE_SEMA, this); +            waiting_threads.push(GetCurrentThread()->GetHandle());          } else {              --available_count;          } @@ -84,7 +84,9 @@ ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {      // Notify some of the threads that the semaphore has been released      // stop once the semaphore is full again or there are no more waiting threads      while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) { -        Kernel::ResumeThreadFromWait(semaphore->waiting_threads.front()); +        Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()); +        if (thread != nullptr) +            thread->ResumeFromWait();          semaphore->waiting_threads.pop();          --semaphore->available_count;      } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 954bd09a0..0ae1a21df 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -10,6 +10,7 @@  #include "common/common.h"  #include "common/thread_queue_list.h" +#include "core/arm/arm_interface.h"  #include "core/core.h"  #include "core/core_timing.h"  #include "core/hle/hle.h" @@ -21,68 +22,25 @@  namespace Kernel { -class Thread : public Kernel::Object { -public: - -    std::string GetName() const override { return name; } -    std::string GetTypeName() const override { return "Thread"; } - -    static const HandleType HANDLE_TYPE = HandleType::Thread; -    HandleType GetHandleType() const override { return HANDLE_TYPE; } - -    inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } -    inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } -    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; -        if (wait) { -            Handle thread = GetCurrentThreadHandle(); -            if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { -                waiting_threads.push_back(thread); -            } -            WaitCurrentThread(WAITTYPE_THREADEND, this->GetHandle()); +ResultVal<bool> Thread::WaitSynchronization() { +    const bool wait = status != THREADSTATUS_DORMANT; +    if (wait) { +        Thread* thread = GetCurrentThread(); +        if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) { +            waiting_threads.push_back(thread);          } - -        return MakeResult<bool>(wait); +        WaitCurrentThread(WAITTYPE_THREADEND, this);      } -    ThreadContext context; - -    u32 thread_id; - -    u32 status; -    u32 entry_point; -    u32 stack_top; -    u32 stack_size; - -    s32 initial_priority; -    s32 current_priority; - -    s32 processor_id; - -    WaitType wait_type; -    Handle wait_handle; -    VAddr wait_address; - -    std::vector<Handle> waiting_threads; - -    std::string name; - -    /// Whether this thread is intended to never actually be executed, i.e. always idle -    bool idle = false; -}; +    return MakeResult<bool>(wait); +}  // Lists all thread ids that aren't deleted/etc. -static std::vector<Handle> thread_queue; +static std::vector<Thread*> thread_list; // TODO(yuriks): Owned  // Lists only ready thread ids. -static Common::ThreadQueueList<Handle, THREADPRIO_LOWEST+1> thread_ready_queue; +static Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST+1> thread_ready_queue; -static Handle current_thread_handle;  static Thread* current_thread;  static const u32 INITIAL_THREAD_ID = 1; ///< The first available thread id at startup @@ -92,30 +50,9 @@ Thread* GetCurrentThread() {      return current_thread;  } -/// Gets the current thread handle -Handle GetCurrentThreadHandle() { -    return GetCurrentThread()->GetHandle(); -} - -/// Sets the current thread -inline void SetCurrentThread(Thread* t) { -    current_thread = t; -    current_thread_handle = t->GetHandle(); -} - -/// Saves the current CPU context -void SaveContext(ThreadContext& ctx) { -    Core::g_app_core->SaveContext(ctx); -} - -/// Loads a CPU context -void LoadContext(ThreadContext& ctx) { -    Core::g_app_core->LoadContext(ctx); -} -  /// Resets a thread -void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { -    memset(&t->context, 0, sizeof(ThreadContext)); +static void ResetThread(Thread* t, u32 arg, s32 lowest_priority) { +    memset(&t->context, 0, sizeof(Core::ThreadContext));      t->context.cpu_registers[0] = arg;      t->context.pc = t->context.reg_15 = t->entry_point; @@ -131,22 +68,21 @@ void ResetThread(Thread* t, u32 arg, s32 lowest_priority) {          t->current_priority = t->initial_priority;      }      t->wait_type = WAITTYPE_NONE; -    t->wait_handle = 0; +    t->wait_object = nullptr;      t->wait_address = 0;  }  /// Change a thread to "ready" state -void ChangeReadyState(Thread* t, bool ready) { -    Handle handle = t->GetHandle(); +static void ChangeReadyState(Thread* t, bool ready) {      if (t->IsReady()) {          if (!ready) { -            thread_ready_queue.remove(t->current_priority, handle); +            thread_ready_queue.remove(t->current_priority, t);          }      }  else if (ready) {          if (t->IsRunning()) { -            thread_ready_queue.push_front(t->current_priority, handle); +            thread_ready_queue.push_front(t->current_priority, t);          } else { -            thread_ready_queue.push_back(t->current_priority, handle); +            thread_ready_queue.push_back(t->current_priority, t);          }          t->status = THREADSTATUS_READY;      } @@ -158,43 +94,36 @@ static bool CheckWaitType(const Thread* thread, WaitType type) {  }  /// Check if a thread is blocking on a specified wait type with a specified handle -static bool CheckWaitType(const Thread* thread, WaitType type, Handle wait_handle) { -    return CheckWaitType(thread, type) && (wait_handle == thread->wait_handle); +static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object) { +    return CheckWaitType(thread, type) && wait_object == thread->wait_object;  }  /// Check if a thread is blocking on a specified wait type with a specified handle and address -static bool CheckWaitType(const Thread* thread, WaitType type, Handle wait_handle, VAddr wait_address) { -    return CheckWaitType(thread, type, wait_handle) && (wait_address == thread->wait_address); +static bool CheckWaitType(const Thread* thread, WaitType type, Object* wait_object, VAddr wait_address) { +    return CheckWaitType(thread, type, wait_object) && (wait_address == thread->wait_address);  }  /// Stops the current thread -ResultCode StopThread(Handle handle, const char* reason) { -    Thread* thread = g_handle_table.Get<Thread>(handle); -    if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); - +void Thread::Stop(const char* reason) {      // Release all the mutexes that this thread holds -    ReleaseThreadMutexes(handle); - -    ChangeReadyState(thread, false); -    thread->status = THREADSTATUS_DORMANT; -    for (Handle waiting_handle : thread->waiting_threads) { -        Thread* waiting_thread = g_handle_table.Get<Thread>(waiting_handle); +    ReleaseThreadMutexes(GetHandle()); -        if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, handle)) -            ResumeThreadFromWait(waiting_handle); +    ChangeReadyState(this, false); +    status = THREADSTATUS_DORMANT; +    for (Thread* waiting_thread : waiting_threads) { +        if (CheckWaitType(waiting_thread, WAITTYPE_THREADEND, this)) +            waiting_thread->ResumeFromWait();      } -    thread->waiting_threads.clear(); +    waiting_threads.clear();      // Stopped threads are never waiting. -    thread->wait_type = WAITTYPE_NONE; -    thread->wait_handle = 0; -    thread->wait_address = 0; - -    return RESULT_SUCCESS; +    wait_type = WAITTYPE_NONE; +    wait_object = nullptr; +    wait_address = 0;  }  /// Changes a threads state -void ChangeThreadState(Thread* t, ThreadStatus new_status) { +static void ChangeThreadState(Thread* t, ThreadStatus new_status) {      if (!t || t->status == new_status) {          return;      } @@ -209,14 +138,12 @@ void ChangeThreadState(Thread* t, ThreadStatus new_status) {  }  /// Arbitrate the highest priority thread that is waiting -Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) { -    Handle highest_priority_thread = 0; +Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address) { +    Thread* highest_priority_thread = nullptr;      s32 priority = THREADPRIO_LOWEST;      // Iterate through threads, find highest priority thread that is waiting to be arbitrated... -    for (Handle handle : thread_queue) { -        Thread* thread = g_handle_table.Get<Thread>(handle); - +    for (Thread* thread : thread_list) {          if (!CheckWaitType(thread, WAITTYPE_ARB, arbiter, address))              continue; @@ -224,31 +151,31 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address) {              continue; // TODO(yuriks): Thread handle will hang around forever. Should clean up.          if(thread->current_priority <= priority) { -            highest_priority_thread = handle; +            highest_priority_thread = thread;              priority = thread->current_priority;          }      } +      // If a thread was arbitrated, resume it -    if (0 != highest_priority_thread) -        ResumeThreadFromWait(highest_priority_thread); +    if (nullptr != highest_priority_thread) { +        highest_priority_thread->ResumeFromWait(); +    }      return highest_priority_thread;  }  /// Arbitrate all threads currently waiting -void ArbitrateAllThreads(u32 arbiter, u32 address) { +void ArbitrateAllThreads(Object* arbiter, u32 address) {      // Iterate through threads, find highest priority thread that is waiting to be arbitrated... -    for (Handle handle : thread_queue) { -        Thread* thread = g_handle_table.Get<Thread>(handle); - +    for (Thread* thread : thread_list) {          if (CheckWaitType(thread, WAITTYPE_ARB, arbiter, address)) -            ResumeThreadFromWait(handle); +            thread->ResumeFromWait();      }  }  /// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields) -void CallThread(Thread* t) { +static void CallThread(Thread* t) {      // Stop waiting      if (t->wait_type != WAITTYPE_NONE) {          t->wait_type = WAITTYPE_NONE; @@ -257,12 +184,12 @@ void CallThread(Thread* t) {  }  /// Switches CPU context to that of the specified thread -void SwitchContext(Thread* t) { +static void SwitchContext(Thread* t) {      Thread* cur = GetCurrentThread();      // Save context for current thread      if (cur) { -        SaveContext(cur->context); +        Core::g_app_core->SaveContext(cur->context);          if (cur->IsRunning()) {              ChangeReadyState(cur, true); @@ -270,19 +197,19 @@ void SwitchContext(Thread* t) {      }      // Load context of new thread      if (t) { -        SetCurrentThread(t); +        current_thread = t;          ChangeReadyState(t, false);          t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY;          t->wait_type = WAITTYPE_NONE; -        LoadContext(t->context); +        Core::g_app_core->LoadContext(t->context);      } else { -        SetCurrentThread(nullptr); +        current_thread = nullptr;      }  }  /// Gets the next thread that is ready to be run by priority -Thread* NextThread() { -    Handle next; +static Thread* NextThread() { +    Thread* next;      Thread* cur = GetCurrentThread();      if (cur && cur->IsRunning()) { @@ -293,18 +220,18 @@ Thread* NextThread() {      if (next == 0) {          return nullptr;      } -    return Kernel::g_handle_table.Get<Thread>(next); +    return next;  } -void WaitCurrentThread(WaitType wait_type, Handle wait_handle) { +void WaitCurrentThread(WaitType wait_type, Object* wait_object) {      Thread* thread = GetCurrentThread();      thread->wait_type = wait_type; -    thread->wait_handle = wait_handle; +    thread->wait_object = wait_object;      ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));  } -void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_address) { -    WaitCurrentThread(wait_type, wait_handle); +void WaitCurrentThread(WaitType wait_type, Object* wait_object, VAddr wait_address) { +    WaitCurrentThread(wait_type, wait_object);      GetCurrentThread()->wait_address = wait_address;  } @@ -320,67 +247,84 @@ static void ThreadWakeupCallback(u64 parameter, int cycles_late) {          return;      } -    Kernel::ResumeThreadFromWait(handle); +    thread->ResumeFromWait();  } -void WakeThreadAfterDelay(Handle handle, s64 nanoseconds) { +void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds) {      // Don't schedule a wakeup if the thread wants to wait forever      if (nanoseconds == -1)          return; - -    Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); -    if (thread == nullptr) { -        LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); -        return; -    } +    _dbg_assert_(Kernel, thread != nullptr);      u64 microseconds = nanoseconds / 1000; -    CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, handle); +    CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, thread->GetHandle());  }  /// Resumes a thread from waiting by marking it as "ready" -void ResumeThreadFromWait(Handle handle) { -    Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); -    if (thread) { -        thread->status &= ~THREADSTATUS_WAIT; -        thread->wait_handle = 0; -        thread->wait_type = WAITTYPE_NONE; -        if (!(thread->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { -            ChangeReadyState(thread, true); -        } +void Thread::ResumeFromWait() { +    status &= ~THREADSTATUS_WAIT; +    wait_object = nullptr; +    wait_type = WAITTYPE_NONE; +    if (!(status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { +        ChangeReadyState(this, true);      }  }  /// Prints the thread queue for debugging purposes -void DebugThreadQueue() { +static void DebugThreadQueue() {      Thread* thread = GetCurrentThread();      if (!thread) {          return;      } -    LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThreadHandle()); -    for (u32 i = 0; i < thread_queue.size(); i++) { -        Handle handle = thread_queue[i]; -        s32 priority = thread_ready_queue.contains(handle); +    LOG_DEBUG(Kernel, "0x%02X 0x%08X (current)", thread->current_priority, GetCurrentThread()->GetHandle()); +    for (Thread* t : thread_list) { +        s32 priority = thread_ready_queue.contains(t);          if (priority != -1) { -            LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, handle); +            LOG_DEBUG(Kernel, "0x%02X 0x%08X", priority, t->GetHandle());          }      }  } -/// Creates a new thread -Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, -    s32 processor_id, u32 stack_top, int stack_size) { +ResultVal<Thread*> Thread::Create(const char* name, u32 entry_point, s32 priority, u32 arg, +        s32 processor_id, u32 stack_top, int stack_size) { +    _dbg_assert_(Kernel, name != nullptr); + +    if ((u32)stack_size < 0x200) { +        LOG_ERROR(Kernel, "(name=%s): invalid stack_size=0x%08X", name, stack_size); +        // TODO: Verify error +        return ResultCode(ErrorDescription::InvalidSize, ErrorModule::Kernel, +                ErrorSummary::InvalidArgument, ErrorLevel::Permanent); +    } + +    if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { +        s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); +        LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", +            name, priority, new_priority); +        // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm +        // validity of this +        priority = new_priority; +    } -    _assert_msg_(KERNEL, (priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST), -        "priority=%d, outside of allowable range!", priority) +    if (!Memory::GetPointer(entry_point)) { +        LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name, entry_point); +        // TODO: Verify error +        return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, +                ErrorSummary::InvalidArgument, ErrorLevel::Permanent); +    }      Thread* thread = new Thread; -    // TOOD(yuriks): Fix error reporting -    handle = Kernel::g_handle_table.Create(thread).ValueOr(INVALID_HANDLE); +    // TODO(yuriks): Thread requires a handle to be inserted into the various scheduling queues for +    //               the time being. Create a handle here, it will be copied to the handle field in +    //               the object and use by the rest of the code. This should be removed when other +    //               code doesn't rely on the handle anymore. +    ResultVal<Handle> handle = Kernel::g_handle_table.Create(thread); +    // TODO(yuriks): Plug memory leak +    if (handle.Failed()) +        return handle.Code(); -    thread_queue.push_back(handle); +    thread_list.push_back(thread);      thread_ready_queue.prepare(priority);      thread->thread_id = next_thread_id++; @@ -391,69 +335,18 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio      thread->initial_priority = thread->current_priority = priority;      thread->processor_id = processor_id;      thread->wait_type = WAITTYPE_NONE; -    thread->wait_handle = 0; +    thread->wait_object = nullptr;      thread->wait_address = 0;      thread->name = name; -    return thread; -} - -/// Creates a new thread - wrapper for external user -Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id, -    u32 stack_top, int stack_size) { - -    if (name == nullptr) { -        LOG_ERROR(Kernel_SVC, "nullptr name"); -        return -1; -    } -    if ((u32)stack_size < 0x200) { -        LOG_ERROR(Kernel_SVC, "(name=%s): invalid stack_size=0x%08X", name, -            stack_size); -        return -1; -    } -    if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { -        s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); -        LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", -            name, priority, new_priority); -        // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm -        // validity of this -        priority = new_priority; -    } -    if (!Memory::GetPointer(entry_point)) { -        LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name, entry_point); -        return -1; -    } -    Handle handle; -    Thread* thread = CreateThread(handle, name, entry_point, priority, processor_id, stack_top, -        stack_size); -      ResetThread(thread, arg, 0);      CallThread(thread); -    return handle; -} - -/// Get the priority of the thread specified by handle -ResultVal<u32> GetThreadPriority(const Handle handle) { -    Thread* thread = g_handle_table.Get<Thread>(handle); -    if (thread == nullptr) return InvalidHandle(ErrorModule::Kernel); - -    return MakeResult<u32>(thread->current_priority); +    return MakeResult<Thread*>(thread);  }  /// Set the priority of the thread specified by handle -ResultCode SetThreadPriority(Handle handle, s32 priority) { -    Thread* thread = nullptr; -    if (!handle) { -        thread = GetCurrentThread(); // TODO(bunnei): Is this correct behavior? -    } else { -        thread = g_handle_table.Get<Thread>(handle); -        if (thread == nullptr) { -            return InvalidHandle(ErrorModule::Kernel); -        } -    } -    _assert_msg_(KERNEL, (thread != nullptr), "called, but thread is nullptr!"); - +void Thread::SetPriority(s32 priority) {      // If priority is invalid, clamp to valid range      if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {          s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); @@ -464,38 +357,39 @@ ResultCode SetThreadPriority(Handle handle, s32 priority) {      }      // Change thread priority -    s32 old = thread->current_priority; -    thread_ready_queue.remove(old, handle); -    thread->current_priority = priority; -    thread_ready_queue.prepare(thread->current_priority); +    s32 old = current_priority; +    thread_ready_queue.remove(old, this); +    current_priority = priority; +    thread_ready_queue.prepare(current_priority);      // Change thread status to "ready" and push to ready queue -    if (thread->IsRunning()) { -        thread->status = (thread->status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY; +    if (IsRunning()) { +        status = (status & ~THREADSTATUS_RUNNING) | THREADSTATUS_READY;      } -    if (thread->IsReady()) { -        thread_ready_queue.push_back(thread->current_priority, handle); +    if (IsReady()) { +        thread_ready_queue.push_back(current_priority, this);      } - -    return RESULT_SUCCESS;  }  Handle SetupIdleThread() { -    Handle handle; -    Thread* thread = CreateThread(handle, "idle", 0, THREADPRIO_LOWEST, THREADPROCESSORID_0, 0, 0); +    // 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()); +    Thread* thread = *thread_res; +      thread->idle = true;      CallThread(thread); -    return handle; +    return thread->GetHandle();  } -Handle SetupMainThread(s32 priority, int stack_size) { -    Handle handle; - +Thread* SetupMainThread(s32 priority, int stack_size) {      // Initialize new "main" thread -    Thread* thread = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority, +    ResultVal<Thread*> thread_res = Thread::Create("main", Core::g_app_core->GetPC(), priority, 0,          THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); - -    ResetThread(thread, 0, 0); +    // TODO(yuriks): Propagate error +    _dbg_assert_(Kernel, thread_res.Succeeded()); +    Thread* thread = *thread_res;      // If running another thread already, set it to "ready" state      Thread* cur = GetCurrentThread(); @@ -504,11 +398,11 @@ Handle SetupMainThread(s32 priority, int stack_size) {      }      // Run new "main" thread -    SetCurrentThread(thread); +    current_thread = thread;      thread->status = THREADSTATUS_RUNNING; -    LoadContext(thread->context); +    Core::g_app_core->LoadContext(thread->context); -    return handle; +    return thread;  } @@ -524,34 +418,14 @@ void Reschedule() {      } else {          LOG_TRACE(Kernel, "cannot context switch from 0x%08X, no higher priority thread!", prev->GetHandle()); -        for (Handle handle : thread_queue) { -            Thread* thread = g_handle_table.Get<Thread>(handle); +        for (Thread* thread : thread_list) {              LOG_TRACE(Kernel, "\thandle=0x%08X prio=0x%02X, status=0x%08X wait_type=0x%08X wait_handle=0x%08X", -                thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle); +                thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, +                (thread->wait_object ? thread->wait_object->GetHandle() : INVALID_HANDLE));          }      }  } -bool IsIdleThread(Handle handle) { -    Thread* thread = g_handle_table.Get<Thread>(handle); -    if (!thread) { -        LOG_ERROR(Kernel, "Thread not found %u", handle); -        return false; -    } -    return thread->IsIdle(); -} - -ResultCode GetThreadId(u32* thread_id, Handle handle) { -    Thread* thread = g_handle_table.Get<Thread>(handle); -    if (thread == nullptr) -        return ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS,  -                          ErrorSummary::WrongArgument, ErrorLevel::Permanent); - -    *thread_id = thread->thread_id; - -    return RESULT_SUCCESS; -} -  ////////////////////////////////////////////////////////////////////////////////////////////////////  void ThreadingInit() { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 58bd85ac6..24450379c 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -4,8 +4,12 @@  #pragma once +#include <string> +#include <vector> +  #include "common/common_types.h" +#include "core/core.h"  #include "core/mem_map.h"  #include "core/hle/kernel/kernel.h" @@ -48,69 +52,102 @@ enum WaitType {  namespace Kernel { -/// Creates a new thread - wrapper for external user -Handle CreateThread(const char* name, u32 entry_point, s32 priority, u32 arg, s32 processor_id, -    u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE); +class Thread : public Kernel::Object { +public: +    static ResultVal<Thread*> Create(const char* name, u32 entry_point, s32 priority, u32 arg, +        s32 processor_id, u32 stack_top, int stack_size = Kernel::DEFAULT_STACK_SIZE); -/// Sets up the primary application thread -Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); +    std::string GetName() const override { return name; } +    std::string GetTypeName() const override { return "Thread"; } -/// Reschedules to the next available thread (call after current thread is suspended) -void Reschedule(); +    static const HandleType HANDLE_TYPE = HandleType::Thread; +    HandleType GetHandleType() const override { return HANDLE_TYPE; } -/// Stops the current thread -ResultCode StopThread(Handle thread, const char* reason); +    inline bool IsRunning() const { return (status & THREADSTATUS_RUNNING) != 0; } +    inline bool IsStopped() const { return (status & THREADSTATUS_DORMANT) != 0; } +    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; } -/** - * Retrieves the ID of the specified thread handle - * @param thread_id Will contain the output thread id - * @param handle Handle to the thread we want - * @return Whether the function was successful or not - */ -ResultCode GetThreadId(u32* thread_id, Handle handle); +    ResultVal<bool> WaitSynchronization() override; + +    s32 GetPriority() const { return current_priority; } +    void SetPriority(s32 priority); + +    u32 GetThreadId() const { return thread_id; } + +    void Stop(const char* reason); +    /// Resumes a thread from waiting by marking it as "ready". +    void ResumeFromWait(); + +    Core::ThreadContext context; + +    u32 thread_id; + +    u32 status; +    u32 entry_point; +    u32 stack_top; +    u32 stack_size; + +    s32 initial_priority; +    s32 current_priority; + +    s32 processor_id; -/// Resumes a thread from waiting by marking it as "ready" -void ResumeThreadFromWait(Handle handle); +    WaitType wait_type; +    Object* wait_object; +    VAddr wait_address; + +    std::vector<Thread*> waiting_threads; // TODO(yuriks): Owned + +    std::string name; + +    /// Whether this thread is intended to never actually be executed, i.e. always idle +    bool idle = false; + +private: +    Thread() = default; +}; + +/// Sets up the primary application thread +Thread* SetupMainThread(s32 priority, int stack_size = Kernel::DEFAULT_STACK_SIZE); + +/// Reschedules to the next available thread (call after current thread is suspended) +void Reschedule();  /// Arbitrate the highest priority thread that is waiting -Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address); +Thread* ArbitrateHighestPriorityThread(Object* arbiter, u32 address);  /// Arbitrate all threads currently waiting... -void ArbitrateAllThreads(u32 arbiter, u32 address); +void ArbitrateAllThreads(Object* arbiter, u32 address); -/// Gets the current thread handle -Handle GetCurrentThreadHandle(); +/// Gets the current thread +Thread* GetCurrentThread();  /**   * Puts the current thread in the wait state for the given type   * @param wait_type Type of wait - * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread + * @param wait_object Kernel object that we are waiting on, defaults to current thread   */ -void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle()); +void WaitCurrentThread(WaitType wait_type, Object* wait_object = GetCurrentThread());  /**   * Schedules an event to wake up the specified thread after the specified delay.   * @param handle The thread handle.   * @param nanoseconds The time this thread will be allowed to sleep for.   */ -void WakeThreadAfterDelay(Handle handle, s64 nanoseconds); +void WakeThreadAfterDelay(Thread* thread, s64 nanoseconds);  /**   * Puts the current thread in the wait state for the given type   * @param wait_type Type of wait - * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread + * @param wait_object Kernel object that we are waiting on   * @param wait_address Arbitration address used to resume from wait   */ -void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_address); +void WaitCurrentThread(WaitType wait_type, Object* wait_object, VAddr wait_address); -/// Put current thread in a wait state - on WaitSynchronization -void WaitThread_Synchronization(); -/// Get the priority of the thread specified by handle -ResultVal<u32> GetThreadPriority(const Handle handle); - -/// Set the priority of the thread specified by handle -ResultCode SetThreadPriority(Handle handle, s32 priority);  /**   * Sets up the idle thread, this is a thread that is intended to never execute instructions, @@ -119,10 +156,6 @@ ResultCode SetThreadPriority(Handle handle, s32 priority);   * @returns The handle of the idle thread   */  Handle SetupIdleThread(); - -/// Whether the current thread is an idle thread -bool IsIdleThread(Handle thread); -  /// Initialize threading  void ThreadingInit(); diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 7ac669e31..685a202c0 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -33,8 +33,8 @@ public:      ResultVal<bool> WaitSynchronization() override {          bool wait = !signaled;          if (wait) { -            waiting_threads.insert(GetCurrentThreadHandle()); -            Kernel::WaitCurrentThread(WAITTYPE_TIMER, GetHandle()); +            waiting_threads.insert(GetCurrentThread()->GetHandle()); +            Kernel::WaitCurrentThread(WAITTYPE_TIMER, this);          }          return MakeResult<bool>(wait);      } @@ -92,8 +92,10 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {      timer->signaled = true;      // Resume all waiting threads -    for (Handle thread : timer->waiting_threads) -        ResumeThreadFromWait(thread); +    for (Handle thread_handle : timer->waiting_threads) { +        if (Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle)) +            thread->ResumeFromWait(); +    }      timer->waiting_threads.clear(); diff --git a/src/core/hle/service/hid_user.cpp b/src/core/hle/service/hid_user.cpp index 99b0ea5a0..8ef9af9d2 100644 --- a/src/core/hle/service/hid_user.cpp +++ b/src/core/hle/service/hid_user.cpp @@ -4,6 +4,7 @@  #include "common/log.h" +#include "core/arm/arm_interface.h"  #include "core/hle/hle.h"  #include "core/hle/kernel/event.h"  #include "core/hle/kernel/shared_memory.h" diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 051f2d2c6..8ac1c7350 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -7,6 +7,7 @@  #include "common/string_util.h"  #include "common/symbols.h" +#include "core/arm/arm_interface.h"  #include "core/mem_map.h"  #include "core/hle/kernel/address_arbiter.h" @@ -230,14 +231,17 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top          name = Common::StringFromFormat("unknown-%08x", entry_point);      } -    Handle thread = Kernel::CreateThread(name.c_str(), entry_point, priority, arg, processor_id, -        stack_top); +    ResultVal<Kernel::Thread*> thread_res = Kernel::Thread::Create(name.c_str(), entry_point, priority, arg, +            processor_id, stack_top); +    if (thread_res.Failed()) +        return thread_res.Code().raw; +    Kernel::Thread* thread = *thread_res; -    Core::g_app_core->SetReg(1, thread); +    Core::g_app_core->SetReg(1, thread->GetHandle());      LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "          "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", entry_point, -        name.c_str(), arg, stack_top, priority, processor_id, thread); +        name.c_str(), arg, stack_top, priority, processor_id, thread->GetHandle());      if (THREADPROCESSORID_1 == processor_id) {          LOG_WARNING(Kernel_SVC, @@ -248,28 +252,31 @@ static Result CreateThread(u32 priority, u32 entry_point, u32 arg, u32 stack_top  }  /// Called when a thread exits -static u32 ExitThread() { -    Handle thread = Kernel::GetCurrentThreadHandle(); +static void ExitThread() { +    LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); -    LOG_TRACE(Kernel_SVC, "called, pc=0x%08X", Core::g_app_core->GetPC()); // PC = 0x0010545C - -    Kernel::StopThread(thread, __func__); +    Kernel::GetCurrentThread()->Stop(__func__);      HLE::Reschedule(__func__); -    return 0;  }  /// Gets the priority for the specified thread  static Result GetThreadPriority(s32* priority, Handle handle) { -    ResultVal<u32> priority_result = Kernel::GetThreadPriority(handle); -    if (priority_result.Succeeded()) { -        *priority = *priority_result; -    } -    return priority_result.Code().raw; +    const Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); +    if (thread == nullptr) +        return InvalidHandle(ErrorModule::Kernel).raw; + +    *priority = thread->GetPriority(); +    return RESULT_SUCCESS.raw;  }  /// Sets the priority for the specified thread  static Result SetThreadPriority(Handle handle, s32 priority) { -    return Kernel::SetThreadPriority(handle, priority).raw; +    Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); +    if (thread == nullptr) +        return InvalidHandle(ErrorModule::Kernel).raw; + +    thread->SetPriority(priority); +    return RESULT_SUCCESS.raw;  }  /// Create a mutex @@ -290,8 +297,13 @@ static Result ReleaseMutex(Handle handle) {  /// Get the ID for the specified thread.  static Result GetThreadId(u32* thread_id, Handle handle) {      LOG_TRACE(Kernel_SVC, "called thread=0x%08X", handle); -    ResultCode result = Kernel::GetThreadId(thread_id, handle); -    return result.raw; + +    const Kernel::Thread* thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); +    if (thread == nullptr) +        return InvalidHandle(ErrorModule::Kernel).raw; + +    *thread_id = thread->GetThreadId(); +    return RESULT_SUCCESS.raw;  }  /// Creates a semaphore @@ -379,7 +391,7 @@ static void SleepThread(s64 nanoseconds) {      Kernel::WaitCurrentThread(WAITTYPE_SLEEP);      // Create an event to wake the thread up after the specified nanosecond delay has passed -    Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThreadHandle(), nanoseconds); +    Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThread(), nanoseconds);      HLE::Reschedule(__func__);  } @@ -411,7 +423,7 @@ const HLE::FunctionDef SVC_Table[] = {      {0x06, nullptr,                         "GetProcessIdealProcessor"},      {0x07, nullptr,                         "SetProcessIdealProcessor"},      {0x08, HLE::Wrap<CreateThread>,         "CreateThread"}, -    {0x09, HLE::Wrap<ExitThread>,           "ExitThread"}, +    {0x09, ExitThread,                      "ExitThread"},      {0x0A, HLE::Wrap<SleepThread>,          "SleepThread"},      {0x0B, HLE::Wrap<GetThreadPriority>,    "GetThreadPriority"},      {0x0C, HLE::Wrap<SetThreadPriority>,    "SetThreadPriority"}, diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h index ad780818e..5d020a5ba 100644 --- a/src/core/hle/svc.h +++ b/src/core/hle/svc.h @@ -20,21 +20,6 @@ struct PageInfo {      u32 flags;  }; -struct ThreadContext { -    u32 cpu_registers[13]; -    u32 sp; -    u32 lr; -    u32 pc; -    u32 cpsr; -    u32 fpu_registers[32]; -    u32 fpscr; -    u32 fpexc; - -    // These are not part of native ThreadContext, but needed by emu -    u32 reg_15; -    u32 mode; -}; -  enum ResetType {      RESETTYPE_ONESHOT,      RESETTYPE_STICKY, diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index e346e0ad6..3b730a0de 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -4,6 +4,8 @@  #include "common/common_types.h" +#include "core/arm/arm_interface.h" +  #include "core/settings.h"  #include "core/core.h"  #include "core/mem_map.h" | 
