mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-25 06:44:59 +00:00
Merge 917d648dfe
into 8fa725d5e4
This commit is contained in:
commit
3c89dcc1f2
2 changed files with 25 additions and 84 deletions
|
@ -5,20 +5,15 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <thread>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Event.h"
|
|
||||||
#include "Common/Flag.h"
|
|
||||||
#include "Common/Logging/Log.h"
|
#include "Common/Logging/Log.h"
|
||||||
#include "Common/MsgHandler.h"
|
#include "Common/MsgHandler.h"
|
||||||
#include "Common/SPSCQueue.h"
|
#include "Common/SPSCQueue.h"
|
||||||
#include "Common/Thread.h"
|
|
||||||
#include "Common/Timer.h"
|
#include "Common/Timer.h"
|
||||||
|
|
||||||
#include "Core/ConfigManager.h"
|
#include "Core/ConfigManager.h"
|
||||||
|
@ -46,44 +41,24 @@ void DVDThread::Start()
|
||||||
{
|
{
|
||||||
m_finish_read = m_system.GetCoreTiming().RegisterEvent("FinishReadDVDThread", GlobalFinishRead);
|
m_finish_read = m_system.GetCoreTiming().RegisterEvent("FinishReadDVDThread", GlobalFinishRead);
|
||||||
|
|
||||||
m_request_queue_expanded.Reset();
|
|
||||||
m_result_queue_expanded.Reset();
|
|
||||||
m_request_queue.Clear();
|
|
||||||
m_result_queue.Clear();
|
|
||||||
|
|
||||||
// This is reset on every launch for determinism, but it doesn't matter
|
// This is reset on every launch for determinism, but it doesn't matter
|
||||||
// much, because this will never get exposed to the emulated game.
|
// much, because this will never get exposed to the emulated game.
|
||||||
m_next_id = 0;
|
m_next_id = 0;
|
||||||
|
|
||||||
StartDVDThread();
|
m_dvd_thread.Reset("DVD thread", std::bind_front(&DVDThread::ProcessReadRequest, this));
|
||||||
}
|
|
||||||
|
|
||||||
void DVDThread::StartDVDThread()
|
|
||||||
{
|
|
||||||
ASSERT(!m_dvd_thread.joinable());
|
|
||||||
m_dvd_thread_exiting.Clear();
|
|
||||||
m_dvd_thread = std::thread(&DVDThread::DVDThreadMain, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DVDThread::Stop()
|
void DVDThread::Stop()
|
||||||
{
|
{
|
||||||
StopDVDThread();
|
m_dvd_thread.Cancel();
|
||||||
|
m_dvd_thread.Shutdown();
|
||||||
|
|
||||||
|
m_result_queue.Clear();
|
||||||
|
m_result_map.clear();
|
||||||
|
|
||||||
m_disc.reset();
|
m_disc.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DVDThread::StopDVDThread()
|
|
||||||
{
|
|
||||||
ASSERT(m_dvd_thread.joinable());
|
|
||||||
|
|
||||||
// By setting dvd_thread_exiting, we ask the DVD thread to cleanly exit.
|
|
||||||
// In case the request queue is empty, we need to set request_queue_expanded
|
|
||||||
// so that the DVD thread will wake up and check dvd_thread_exiting.
|
|
||||||
m_dvd_thread_exiting.Set();
|
|
||||||
m_request_queue_expanded.Set();
|
|
||||||
|
|
||||||
m_dvd_thread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DVDThread::DoState(PointerWrap& p)
|
void DVDThread::DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
// By waiting for the DVD thread to be done working, we ensure
|
// By waiting for the DVD thread to be done working, we ensure
|
||||||
|
@ -98,7 +73,6 @@ void DVDThread::DoState(PointerWrap& p)
|
||||||
while (m_result_queue.Pop(result))
|
while (m_result_queue.Pop(result))
|
||||||
m_result_map.emplace(result.first.id, std::move(result));
|
m_result_map.emplace(result.first.id, std::move(result));
|
||||||
|
|
||||||
// Both queues are now empty, so we don't need to savestate them.
|
|
||||||
p.Do(m_result_map);
|
p.Do(m_result_map);
|
||||||
p.Do(m_next_id);
|
p.Do(m_next_id);
|
||||||
|
|
||||||
|
@ -202,11 +176,7 @@ void DVDThread::WaitUntilIdle()
|
||||||
{
|
{
|
||||||
ASSERT(Core::IsCPUThread());
|
ASSERT(Core::IsCPUThread());
|
||||||
|
|
||||||
while (!m_request_queue.Empty())
|
m_dvd_thread.WaitForCompletion();
|
||||||
m_result_queue_expanded.Wait();
|
|
||||||
|
|
||||||
StopDVDThread();
|
|
||||||
StartDVDThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DVDThread::StartRead(u64 dvd_offset, u32 length, const DiscIO::Partition& partition,
|
void DVDThread::StartRead(u64 dvd_offset, u32 length, const DiscIO::Partition& partition,
|
||||||
|
@ -246,9 +216,7 @@ void DVDThread::StartReadInternal(bool copy_to_ram, u32 output_address, u64 dvd_
|
||||||
request.time_started_ticks = core_timing.GetTicks();
|
request.time_started_ticks = core_timing.GetTicks();
|
||||||
request.realtime_started_us = Common::Timer::NowUs();
|
request.realtime_started_us = Common::Timer::NowUs();
|
||||||
|
|
||||||
m_request_queue.Push(std::move(request));
|
m_dvd_thread.Push(std::move(request));
|
||||||
m_request_queue_expanded.Set();
|
|
||||||
|
|
||||||
core_timing.ScheduleEvent(ticks_until_completion, m_finish_read, id);
|
core_timing.ScheduleEvent(ticks_until_completion, m_finish_read, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,12 +248,11 @@ void DVDThread::FinishRead(u64 id, s64 cycles_late)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
while (!m_result_queue.Pop(result))
|
m_result_queue.WaitForData();
|
||||||
m_result_queue_expanded.Wait();
|
m_result_queue.Pop(result);
|
||||||
|
|
||||||
if (result.first.id == id)
|
if (result.first.id == id)
|
||||||
break;
|
break;
|
||||||
else
|
|
||||||
m_result_map.emplace(result.first.id, std::move(result));
|
m_result_map.emplace(result.first.id, std::move(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,20 +295,8 @@ void DVDThread::FinishRead(u64 id, s64 cycles_late)
|
||||||
dvd_interface.FinishExecutingCommand(request.reply_type, interrupt, cycles_late, buffer);
|
dvd_interface.FinishExecutingCommand(request.reply_type, interrupt, cycles_late, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DVDThread::DVDThreadMain()
|
void DVDThread::ProcessReadRequest(ReadRequest&& request)
|
||||||
{
|
{
|
||||||
Common::SetCurrentThreadName("DVD thread");
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
m_request_queue_expanded.Wait();
|
|
||||||
|
|
||||||
if (m_dvd_thread_exiting.IsSet())
|
|
||||||
return;
|
|
||||||
|
|
||||||
ReadRequest request;
|
|
||||||
while (m_request_queue.Pop(request))
|
|
||||||
{
|
|
||||||
m_file_logger.Log(*m_disc, request.partition, request.dvd_offset);
|
m_file_logger.Log(*m_disc, request.partition, request.dvd_offset);
|
||||||
|
|
||||||
std::vector<u8> buffer(request.length);
|
std::vector<u8> buffer(request.length);
|
||||||
|
@ -351,11 +306,5 @@ void DVDThread::DVDThreadMain()
|
||||||
request.realtime_done_us = Common::Timer::NowUs();
|
request.realtime_done_us = Common::Timer::NowUs();
|
||||||
|
|
||||||
m_result_queue.Push(ReadResult(std::move(request), std::move(buffer)));
|
m_result_queue.Push(ReadResult(std::move(request), std::move(buffer)));
|
||||||
m_result_queue_expanded.Set();
|
|
||||||
|
|
||||||
if (m_dvd_thread_exiting.IsSet())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace DVD
|
} // namespace DVD
|
||||||
|
|
|
@ -6,15 +6,13 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <thread>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/Event.h"
|
|
||||||
#include "Common/Flag.h"
|
|
||||||
#include "Common/SPSCQueue.h"
|
#include "Common/SPSCQueue.h"
|
||||||
|
|
||||||
|
#include "Common/WorkQueueThread.h"
|
||||||
#include "Core/HW/DVD/DVDInterface.h"
|
#include "Core/HW/DVD/DVDInterface.h"
|
||||||
#include "Core/HW/DVD/FileMonitor.h"
|
#include "Core/HW/DVD/FileMonitor.h"
|
||||||
|
|
||||||
|
@ -87,8 +85,6 @@ public:
|
||||||
s64 ticks_until_completion);
|
s64 ticks_until_completion);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void StartDVDThread();
|
|
||||||
void StopDVDThread();
|
|
||||||
void WaitUntilIdle();
|
void WaitUntilIdle();
|
||||||
|
|
||||||
void StartReadInternal(bool copy_to_ram, u32 output_address, u64 dvd_offset, u32 length,
|
void StartReadInternal(bool copy_to_ram, u32 output_address, u64 dvd_offset, u32 length,
|
||||||
|
@ -98,8 +94,6 @@ private:
|
||||||
static void GlobalFinishRead(Core::System& system, u64 id, s64 cycles_late);
|
static void GlobalFinishRead(Core::System& system, u64 id, s64 cycles_late);
|
||||||
void FinishRead(u64 id, s64 cycles_late);
|
void FinishRead(u64 id, s64 cycles_late);
|
||||||
|
|
||||||
void DVDThreadMain();
|
|
||||||
|
|
||||||
struct ReadRequest
|
struct ReadRequest
|
||||||
{
|
{
|
||||||
bool copy_to_ram = false;
|
bool copy_to_ram = false;
|
||||||
|
@ -124,19 +118,17 @@ private:
|
||||||
u64 realtime_done_us = 0;
|
u64 realtime_done_us = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ProcessReadRequest(ReadRequest&& read_request);
|
||||||
|
|
||||||
using ReadResult = std::pair<ReadRequest, std::vector<u8>>;
|
using ReadResult = std::pair<ReadRequest, std::vector<u8>>;
|
||||||
|
|
||||||
CoreTiming::EventType* m_finish_read = nullptr;
|
CoreTiming::EventType* m_finish_read = nullptr;
|
||||||
|
|
||||||
u64 m_next_id = 0;
|
u64 m_next_id = 0;
|
||||||
|
|
||||||
std::thread m_dvd_thread;
|
Common::WorkQueueThread<ReadRequest> m_dvd_thread;
|
||||||
Common::Event m_request_queue_expanded; // Is set by CPU thread
|
|
||||||
Common::Event m_result_queue_expanded; // Is set by DVD thread
|
|
||||||
Common::Flag m_dvd_thread_exiting = Common::Flag(false); // Is set by CPU thread
|
|
||||||
|
|
||||||
Common::SPSCQueue<ReadRequest> m_request_queue;
|
Common::WaitableSPSCQueue<ReadResult> m_result_queue;
|
||||||
Common::SPSCQueue<ReadResult> m_result_queue;
|
|
||||||
std::map<u64, ReadResult> m_result_map;
|
std::map<u64, ReadResult> m_result_map;
|
||||||
|
|
||||||
std::unique_ptr<DiscIO::Volume> m_disc;
|
std::unique_ptr<DiscIO::Volume> m_disc;
|
||||||
|
|
Loading…
Add table
Reference in a new issue