diff options
| author | bunnei <bunneidev@gmail.com> | 2018-05-02 22:36:51 -0400 | 
|---|---|---|
| committer | bunnei <bunneidev@gmail.com> | 2018-05-10 19:34:46 -0400 | 
| commit | a434fdcb102e96ddf564dc0973d7073d49bf19fc (patch) | |
| tree | de758b0cc5ebcb67146397a74474fb898c0be51a /src/core/hle | |
| parent | 9776ff91797423a9cf19571faafe4648fb5a1d1d (diff) | |
core: Implement multicore support.
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 43 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 24 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 23 | 
5 files changed, 65 insertions, 45 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 72b5c05f2..520510b61 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -485,22 +485,28 @@ static void ExitProcess() {      Core::CurrentProcess()->status = ProcessStatus::Exited; -    // Stop all the process threads that are currently waiting for objects. -    auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); -    for (auto& thread : thread_list) { -        if (thread->owner_process != Core::CurrentProcess()) -            continue; +    auto stop_threads = [](const std::vector<SharedPtr<Thread>>& thread_list) { +        for (auto& thread : thread_list) { +            if (thread->owner_process != Core::CurrentProcess()) +                continue; -        if (thread == GetCurrentThread()) -            continue; +            if (thread == GetCurrentThread()) +                continue; -        // TODO(Subv): When are the other running/ready threads terminated? -        ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || -                       thread->status == THREADSTATUS_WAIT_SYNCH_ALL, -                   "Exiting processes with non-waiting threads is currently unimplemented"); +            // TODO(Subv): When are the other running/ready threads terminated? +            ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || +                           thread->status == THREADSTATUS_WAIT_SYNCH_ALL, +                       "Exiting processes with non-waiting threads is currently unimplemented"); -        thread->Stop(); -    } +            thread->Stop(); +        } +    }; + +    auto& system = Core::System::GetInstance(); +    stop_threads(system.Scheduler(0)->GetThreadList()); +    stop_threads(system.Scheduler(1)->GetThreadList()); +    stop_threads(system.Scheduler(2)->GetThreadList()); +    stop_threads(system.Scheduler(3)->GetThreadList());      // Kill the current thread      GetCurrentThread()->Stop(); @@ -530,14 +536,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V      switch (processor_id) {      case THREADPROCESSORID_0: -        break;      case THREADPROCESSORID_1:      case THREADPROCESSORID_2:      case THREADPROCESSORID_3: -        // TODO(bunnei): Implement support for other processor IDs -        NGLOG_ERROR(Kernel_SVC, -                    "Newly created thread must run in another thread ({}), unimplemented.", -                    processor_id);          break;      default:          ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id); @@ -576,7 +577,7 @@ static ResultCode StartThread(Handle thread_handle) {  /// Called when a thread exits  static void ExitThread() { -    NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CPU().GetPC()); +    NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CurrentArmInterface().GetPC());      ExitCurrentThread();      Core::System::GetInstance().PrepareReschedule(); @@ -588,7 +589,7 @@ static void SleepThread(s64 nanoseconds) {      // Don't attempt to yield execution if there are no available threads to run,      // this way we avoid a useless reschedule to the idle thread. -    if (nanoseconds == 0 && !Core::System::GetInstance().Scheduler().HaveReadyThreads()) +    if (nanoseconds == 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads())          return;      // Sleep current thread and check for next thread to schedule @@ -634,7 +635,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target                  condition_variable_addr, target);      u32 processed = 0; -    auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); +    auto& thread_list = Core::System::GetInstance().CurrentScheduler().GetThreadList();      for (auto& thread : thread_list) {          if (thread->condvar_wait_address != condition_variable_addr) diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index c86ad3e04..40aa88cc1 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -13,14 +13,14 @@  namespace Kernel { -#define PARAM(n) Core::CPU().GetReg(n) +#define PARAM(n) Core::CurrentArmInterface().GetReg(n)  /**   * HLE a function return from the current ARM userland process   * @param res Result to return   */  static inline void FuncReturn(u64 res) { -    Core::CPU().SetReg(0, res); +    Core::CurrentArmInterface().SetReg(0, res);  }  //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -45,7 +45,7 @@ template <ResultCode func(u32*, u32)>  void SvcWrap() {      u32 param_1 = 0;      u32 retval = func(¶m_1, (u32)PARAM(1)).raw; -    Core::CPU().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(1, param_1);      FuncReturn(retval);  } @@ -53,7 +53,7 @@ template <ResultCode func(u32*, u64)>  void SvcWrap() {      u32 param_1 = 0;      u32 retval = func(¶m_1, PARAM(1)).raw; -    Core::CPU().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(1, param_1);      FuncReturn(retval);  } @@ -66,7 +66,7 @@ template <ResultCode func(u64*, u64)>  void SvcWrap() {      u64 param_1 = 0;      u32 retval = func(¶m_1, PARAM(1)).raw; -    Core::CPU().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(1, param_1);      FuncReturn(retval);  } @@ -85,8 +85,8 @@ void SvcWrap() {      u32 param_1 = 0;      u64 param_2 = 0;      ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), ¶m_1, ¶m_2); -    Core::CPU().SetReg(1, param_1); -    Core::CPU().SetReg(2, param_2); +    Core::CurrentArmInterface().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(2, param_2);      FuncReturn(retval.raw);  } @@ -120,7 +120,7 @@ template <ResultCode func(u32*, u64, u64, s64)>  void SvcWrap() {      u32 param_1 = 0;      ResultCode retval = func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3)); -    Core::CPU().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(1, param_1);      FuncReturn(retval.raw);  } @@ -133,7 +133,7 @@ template <ResultCode func(u64*, u64, u64, u64)>  void SvcWrap() {      u64 param_1 = 0;      u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3)).raw; -    Core::CPU().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(1, param_1);      FuncReturn(retval);  } @@ -143,7 +143,7 @@ void SvcWrap() {      u32 retval =          func(¶m_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF))              .raw; -    Core::CPU().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(1, param_1);      FuncReturn(retval);  } @@ -166,7 +166,7 @@ template <ResultCode func(u32*, u64, u64, u32)>  void SvcWrap() {      u32 param_1 = 0;      u32 retval = func(¶m_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; -    Core::CPU().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(1, param_1);      FuncReturn(retval);  } @@ -175,7 +175,7 @@ void SvcWrap() {      u32 param_1 = 0;      u32 retval =          func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; -    Core::CPU().SetReg(1, param_1); +    Core::CurrentArmInterface().SetReg(1, param_1);      FuncReturn(retval);  } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 1bd5d9ebf..0a5441684 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -64,7 +64,7 @@ void Thread::Stop() {      // Clean up thread from ready queue      // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)      if (status == THREADSTATUS_READY) { -        Core::System::GetInstance().Scheduler().UnscheduleThread(this, current_priority); +        scheduler->UnscheduleThread(this, current_priority);      }      status = THREADSTATUS_DEAD; @@ -92,7 +92,7 @@ void WaitCurrentThread_Sleep() {  void ExitCurrentThread() {      Thread* thread = GetCurrentThread();      thread->Stop(); -    Core::System::GetInstance().Scheduler().RemoveThread(thread); +    Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);  }  /** @@ -188,7 +188,7 @@ void Thread::ResumeFromWait() {      wakeup_callback = nullptr;      status = THREADSTATUS_READY; -    Core::System::GetInstance().Scheduler().ScheduleThread(this, current_priority); +    scheduler->ScheduleThread(this, current_priority);      Core::System::GetInstance().PrepareReschedule();  } @@ -259,8 +259,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,      SharedPtr<Thread> thread(new Thread); -    Core::System::GetInstance().Scheduler().AddThread(thread, priority); -      thread->thread_id = NewThreadId();      thread->status = THREADSTATUS_DORMANT;      thread->entry_point = entry_point; @@ -275,6 +273,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,      thread->name = std::move(name);      thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();      thread->owner_process = owner_process; +    thread->scheduler = Core::System().GetInstance().Scheduler(static_cast<size_t>(processor_id)); +    thread->scheduler->AddThread(thread, priority);      // Find the next available TLS index, and mark it as used      auto& tls_slots = owner_process->tls_slots; @@ -337,7 +337,7 @@ void Thread::SetPriority(u32 priority) {  }  void Thread::BoostPriority(u32 priority) { -    Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); +    scheduler->SetThreadPriority(this, priority);      current_priority = priority;  } @@ -406,7 +406,7 @@ void Thread::UpdatePriority() {      if (new_priority == current_priority)          return; -    Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority); +    scheduler->SetThreadPriority(this, new_priority);      current_priority = new_priority; @@ -421,7 +421,7 @@ void Thread::UpdatePriority() {   * Gets the current thread   */  Thread* GetCurrentThread() { -    return Core::System::GetInstance().Scheduler().GetCurrentThread(); +    return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();  }  void ThreadingInit() { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index e0a3c0934..0a3bb1183 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -4,6 +4,7 @@  #pragma once +#include <memory>  #include <string>  #include <unordered_map>  #include <vector> @@ -56,6 +57,7 @@ enum class ThreadWakeupReason {  namespace Kernel {  class Process; +class Scheduler;  class Thread final : public WaitObject {  public: @@ -240,6 +242,8 @@ public:      // available. In case of a timeout, the object will be nullptr.      std::function<WakeupCallback> wakeup_callback; +    std::shared_ptr<Scheduler> scheduler; +  private:      Thread();      ~Thread() override; diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 2f0044c11..676e5b282 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -104,8 +104,15 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,      VirtualMemoryArea& final_vma = vma_handle->second;      ASSERT(final_vma.size == size); -    Core::CPU().MapBackingMemory(target, size, block->data() + offset, -                                 VMAPermission::ReadWriteExecute); +    auto& system = Core::System::GetInstance(); +    system.ArmInterface(0).MapBackingMemory(target, size, block->data() + offset, +                                            VMAPermission::ReadWriteExecute); +    system.ArmInterface(1).MapBackingMemory(target, size, block->data() + offset, +                                            VMAPermission::ReadWriteExecute); +    system.ArmInterface(2).MapBackingMemory(target, size, block->data() + offset, +                                            VMAPermission::ReadWriteExecute); +    system.ArmInterface(3).MapBackingMemory(target, size, block->data() + offset, +                                            VMAPermission::ReadWriteExecute);      final_vma.type = VMAType::AllocatedMemoryBlock;      final_vma.permissions = VMAPermission::ReadWrite; @@ -126,7 +133,11 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me      VirtualMemoryArea& final_vma = vma_handle->second;      ASSERT(final_vma.size == size); -    Core::CPU().MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); +    auto& system = Core::System::GetInstance(); +    system.ArmInterface(0).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); +    system.ArmInterface(1).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); +    system.ArmInterface(2).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); +    system.ArmInterface(3).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);      final_vma.type = VMAType::BackingMemory;      final_vma.permissions = VMAPermission::ReadWrite; @@ -184,7 +195,11 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) {      ASSERT(FindVMA(target)->second.size >= size); -    Core::CPU().UnmapMemory(target, size); +    auto& system = Core::System::GetInstance(); +    system.ArmInterface(0).UnmapMemory(target, size); +    system.ArmInterface(1).UnmapMemory(target, size); +    system.ArmInterface(2).UnmapMemory(target, size); +    system.ArmInterface(3).UnmapMemory(target, size);      return RESULT_SUCCESS;  }  | 
