diff options
| -rw-r--r-- | src/core/core.cpp | 18 | ||||
| -rw-r--r-- | src/core/core.h | 4 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.cpp | 82 | ||||
| -rw-r--r-- | src/yuzu/bootmanager.h | 51 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 82 | ||||
| -rw-r--r-- | src/yuzu/main.h | 1 | 
6 files changed, 65 insertions, 173 deletions
| diff --git a/src/core/core.cpp b/src/core/core.cpp index a738f221f..47292cd78 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -183,26 +183,20 @@ struct System::Impl {          Initialize(system);      } -    SystemResultStatus Run() { +    void Run() {          std::unique_lock<std::mutex> lk(suspend_guard); -        status = SystemResultStatus::Success;          kernel.Suspend(false);          core_timing.SyncPause(false);          is_paused.store(false, std::memory_order_relaxed); - -        return status;      } -    SystemResultStatus Pause() { +    void Pause() {          std::unique_lock<std::mutex> lk(suspend_guard); -        status = SystemResultStatus::Success;          core_timing.SyncPause(true);          kernel.Suspend(true);          is_paused.store(true, std::memory_order_relaxed); - -        return status;      }      bool IsPaused() const { @@ -553,12 +547,12 @@ void System::Initialize() {      impl->Initialize(*this);  } -SystemResultStatus System::Run() { -    return impl->Run(); +void System::Run() { +    impl->Run();  } -SystemResultStatus System::Pause() { -    return impl->Pause(); +void System::Pause() { +    impl->Pause();  }  bool System::IsPaused() const { diff --git a/src/core/core.h b/src/core/core.h index 4ebedffd9..fb5cda2f5 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -152,13 +152,13 @@ public:       * Run the OS and Application       * This function will start emulation and run the relevant devices       */ -    [[nodiscard]] SystemResultStatus Run(); +    void Run();      /**       * Pause the OS and Application       * This function will pause emulation and stop the relevant devices       */ -    [[nodiscard]] SystemResultStatus Pause(); +    void Pause();      /// Check if the core is currently paused.      [[nodiscard]] bool IsPaused() const; diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 1368b20d5..13782869d 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -46,30 +46,28 @@  static Core::Frontend::WindowSystemType GetWindowSystemType(); -EmuThread::EmuThread(Core::System& system_) : system{system_} {} +EmuThread::EmuThread(Core::System& system) : m_system{system} {}  EmuThread::~EmuThread() = default;  void EmuThread::run() { -    std::string name = "EmuControlThread"; -    MicroProfileOnThreadCreate(name.c_str()); -    Common::SetCurrentThreadName(name.c_str()); +    const char* name = "EmuControlThread"; +    MicroProfileOnThreadCreate(name); +    Common::SetCurrentThreadName(name); -    auto& gpu = system.GPU(); -    auto stop_token = stop_source.get_token(); -    bool debugger_should_start = system.DebuggerEnabled(); +    auto& gpu = m_system.GPU(); +    auto stop_token = m_stop_source.get_token(); -    system.RegisterHostThread(); +    m_system.RegisterHostThread();      // Main process has been loaded. Make the context current to this thread and begin GPU and CPU      // execution.      gpu.ObtainContext();      emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); -      if (Settings::values.use_disk_shader_cache.GetValue()) { -        system.Renderer().ReadRasterizer()->LoadDiskResources( -            system.GetCurrentProcessProgramID(), stop_token, +        m_system.Renderer().ReadRasterizer()->LoadDiskResources( +            m_system.GetCurrentProcessProgramID(), stop_token,              [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {                  emit LoadProgress(stage, value, total);              }); @@ -79,57 +77,35 @@ void EmuThread::run() {      gpu.ReleaseContext();      gpu.Start(); -    system.GetCpuManager().OnGpuReady(); +    m_system.GetCpuManager().OnGpuReady(); +    m_system.RegisterExitCallback([this] { m_stop_source.request_stop(); }); -    system.RegisterExitCallback([this]() { -        stop_source.request_stop(); -        SetRunning(false); -    }); +    if (m_system.DebuggerEnabled()) { +        m_system.InitializeDebugger(); +    } -    // Holds whether the cpu was running during the last iteration, -    // so that the DebugModeLeft signal can be emitted before the -    // next execution step -    bool was_active = false;      while (!stop_token.stop_requested()) { -        if (running) { -            if (was_active) { -                emit DebugModeLeft(); -            } +        std::unique_lock lk{m_should_run_mutex}; +        if (m_should_run) { +            m_system.Run(); +            m_is_running.store(true); +            m_is_running.notify_all(); -            running_guard = true; -            Core::SystemResultStatus result = system.Run(); -            if (result != Core::SystemResultStatus::Success) { -                running_guard = false; -                this->SetRunning(false); -                emit ErrorThrown(result, system.GetStatusDetails()); -            } - -            if (debugger_should_start) { -                system.InitializeDebugger(); -                debugger_should_start = false; -            } - -            running_wait.Wait(); -            result = system.Pause(); -            if (result != Core::SystemResultStatus::Success) { -                running_guard = false; -                this->SetRunning(false); -                emit ErrorThrown(result, system.GetStatusDetails()); -            } -            running_guard = false; - -            if (!stop_token.stop_requested()) { -                was_active = true; -                emit DebugModeEntered(); -            } +            Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return !m_should_run; });          } else { -            std::unique_lock lock{running_mutex}; -            Common::CondvarWait(running_cv, lock, stop_token, [&] { return IsRunning(); }); +            m_system.Pause(); +            m_is_running.store(false); +            m_is_running.notify_all(); + +            emit DebugModeEntered(); +            Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; }); +            emit DebugModeLeft();          }      }      // Shutdown the main emulated process -    system.ShutdownMainProcess(); +    m_system.DetachDebugger(); +    m_system.ShutdownMainProcess();  #if MICROPROFILE_ENABLED      MicroProfileOnThreadExit(); diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index b24141fd9..1c2e76369 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -47,7 +47,7 @@ class EmuThread final : public QThread {      Q_OBJECT  public: -    explicit EmuThread(Core::System& system_); +    explicit EmuThread(Core::System& system);      ~EmuThread() override;      /** @@ -57,30 +57,30 @@ public:      void run() override;      /** -     * Sets whether the emulation thread is running or not -     * @param running_ Boolean value, set the emulation thread to running if true -     * @note This function is thread-safe +     * Sets whether the emulation thread should run or not +     * @param should_run Boolean value, set the emulation thread to running if true       */ -    void SetRunning(bool running_) { -        std::unique_lock lock{running_mutex}; -        running = running_; -        lock.unlock(); -        running_cv.notify_all(); -        if (!running) { -            running_wait.Set(); -            /// Wait until effectively paused -            while (running_guard) -                ; +    void SetRunning(bool should_run) { +        // TODO: Prevent other threads from modifying the state until we finish. +        { +            // Notify the running thread to change state. +            std::unique_lock run_lk{m_should_run_mutex}; +            m_should_run = should_run; +            m_should_run_cv.notify_one(); +        } + +        // Wait until paused, if pausing. +        if (!should_run) { +            m_is_running.wait(true);          }      }      /**       * Check if the emulation thread is running or not       * @return True if the emulation thread is running, otherwise false -     * @note This function is thread-safe       */      bool IsRunning() const { -        return running; +        return m_is_running.load();      }      /** @@ -88,18 +88,17 @@ public:       */      void ForceStop() {          LOG_WARNING(Frontend, "Force stopping EmuThread"); -        stop_source.request_stop(); -        SetRunning(false); +        m_stop_source.request_stop();      }  private: -    bool running = false; -    std::stop_source stop_source; -    std::mutex running_mutex; -    std::condition_variable_any running_cv; -    Common::Event running_wait{}; -    std::atomic_bool running_guard{false}; -    Core::System& system; +    Core::System& m_system; + +    std::stop_source m_stop_source; +    std::mutex m_should_run_mutex; +    std::condition_variable_any m_should_run_cv; +    std::atomic<bool> m_is_running{false}; +    bool m_should_run{true};  signals:      /** @@ -120,8 +119,6 @@ signals:       */      void DebugModeLeft(); -    void ErrorThrown(Core::SystemResultStatus, std::string); -      void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);  }; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index fe140dce0..820f60e61 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1498,7 +1498,7 @@ void GMainWindow::SetupSigInterrupts() {  void GMainWindow::HandleSigInterrupt(int sig) {      if (sig == SIGINT) { -        exit(1); +        _exit(1);      }      // Calling into Qt directly from a signal handler is not safe, @@ -1794,15 +1794,16 @@ void GMainWindow::ShutdownGame() {      Settings::values.use_speed_limit.SetValue(true);      system->SetShuttingDown(true); -    system->DetachDebugger();      discord_rpc->Pause();      RequestGameExit(); +    emu_thread->disconnect(); +    emu_thread->SetRunning(true);      emit EmulationStopping();      // Wait for emulation thread to complete and delete it -    if (!emu_thread->wait(5000)) { +    if (system->DebuggerEnabled() || !emu_thread->wait(5000)) {          emu_thread->ForceStop();          emu_thread->wait();      } @@ -2919,8 +2920,6 @@ void GMainWindow::OnStartGame() {      emu_thread->SetRunning(true); -    connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError); -      UpdateMenuState();      OnTasStateChanged(); @@ -3904,79 +3903,6 @@ void GMainWindow::OnMouseActivity() {      mouse_center_timer.stop();  } -void GMainWindow::OnCoreError(Core::SystemResultStatus result, std::string details) { -    QMessageBox::StandardButton answer; -    QString status_message; -    const QString common_message = -        tr("The game you are trying to load requires additional files from your Switch to be " -           "dumped " -           "before playing.<br/><br/>For more information on dumping these files, please see the " -           "following wiki page: <a " -           "href='https://yuzu-emu.org/wiki/" -           "dumping-system-archives-and-the-shared-fonts-from-a-switch-console/'>Dumping System " -           "Archives and the Shared Fonts from a Switch Console</a>.<br/><br/>Would you like to " -           "quit " -           "back to the game list? Continuing emulation may result in crashes, corrupted save " -           "data, or other bugs."); -    switch (result) { -    case Core::SystemResultStatus::ErrorSystemFiles: { -        QString message; -        if (details.empty()) { -            message = -                tr("yuzu was unable to locate a Switch system archive. %1").arg(common_message); -        } else { -            message = tr("yuzu was unable to locate a Switch system archive: %1. %2") -                          .arg(QString::fromStdString(details), common_message); -        } - -        answer = QMessageBox::question(this, tr("System Archive Not Found"), message, -                                       QMessageBox::Yes | QMessageBox::No, QMessageBox::No); -        status_message = tr("System Archive Missing"); -        break; -    } - -    case Core::SystemResultStatus::ErrorSharedFont: { -        const QString message = -            tr("yuzu was unable to locate the Switch shared fonts. %1").arg(common_message); -        answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message, -                                       QMessageBox::Yes | QMessageBox::No, QMessageBox::No); -        status_message = tr("Shared Font Missing"); -        break; -    } - -    default: -        answer = QMessageBox::question( -            this, tr("Fatal Error"), -            tr("yuzu has encountered a fatal error, please see the log for more details. " -               "For more information on accessing the log, please see the following page: " -               "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How " -               "to " -               "Upload the Log File</a>.<br/><br/>Would you like to quit back to the game " -               "list? " -               "Continuing emulation may result in crashes, corrupted save data, or other " -               "bugs."), -            QMessageBox::Yes | QMessageBox::No, QMessageBox::No); -        status_message = tr("Fatal Error encountered"); -        break; -    } - -    if (answer == QMessageBox::Yes) { -        if (emu_thread) { -            ShutdownGame(); - -            Settings::RestoreGlobalState(system->IsPoweredOn()); -            system->HIDCore().ReloadInputDevices(); -            UpdateStatusButtons(); -        } -    } else { -        // Only show the message if the game is still running. -        if (emu_thread) { -            emu_thread->SetRunning(true); -            message_label->setText(status_message); -        } -    } -} -  void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {      if (behavior == ReinitializeKeyBehavior::Warning) {          const auto res = QMessageBox::information( diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 1047ba276..5b84c7a00 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -332,7 +332,6 @@ private slots:      void ResetWindowSize900();      void ResetWindowSize1080();      void OnCaptureScreenshot(); -    void OnCoreError(Core::SystemResultStatus, std::string);      void OnReinitializeKeys(ReinitializeKeyBehavior behavior);      void OnLanguageChanged(const QString& locale);      void OnMouseActivity(); | 
