mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 05:51:27 +12:00
* use one central unified log with channels/priorities ad-hoc listener registration and de-registration * disable buffering by default * add multi-threaded ringbuffer implementation * use buffered listener for the gui (using the ringbuffer)
155 lines
3 KiB
C++
155 lines
3 KiB
C++
#include "stdafx.h"
|
|
#include "Utilities/Log.h"
|
|
#include "Emu/Memory/Memory.h"
|
|
#include "Emu/System.h"
|
|
|
|
#include "CPUThreadManager.h"
|
|
#include "Emu/Cell/PPUThread.h"
|
|
#include "Emu/Cell/SPUThread.h"
|
|
#include "Emu/Cell/RawSPUThread.h"
|
|
#include "Emu/ARMv7/ARMv7Thread.h"
|
|
|
|
CPUThreadManager::CPUThreadManager()
|
|
: m_raw_spu_num(0)
|
|
{
|
|
}
|
|
|
|
CPUThreadManager::~CPUThreadManager()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
void CPUThreadManager::Close()
|
|
{
|
|
m_raw_spu_num = 0;
|
|
while(m_threads.size()) RemoveThread(m_threads[0]->GetId());
|
|
}
|
|
|
|
CPUThread& CPUThreadManager::AddThread(CPUThreadType type)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
|
|
|
CPUThread* new_thread;
|
|
|
|
switch(type)
|
|
{
|
|
case CPU_THREAD_PPU: new_thread = new PPUThread(); break;
|
|
case CPU_THREAD_SPU: new_thread = new SPUThread(); break;
|
|
case CPU_THREAD_RAW_SPU: new_thread = new RawSPUThread(m_raw_spu_num++); break;
|
|
case CPU_THREAD_ARMv7: new_thread = new ARMv7Thread(); break;
|
|
default: assert(0);
|
|
}
|
|
|
|
new_thread->SetId(Emu.GetIdManager().GetNewID(fmt::Format("%s Thread", new_thread->GetTypeString().c_str()), new_thread));
|
|
|
|
m_threads.push_back(new_thread);
|
|
SendDbgCommand(DID_CREATE_THREAD, new_thread);
|
|
|
|
return *new_thread;
|
|
}
|
|
|
|
void CPUThreadManager::RemoveThread(const u32 id)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
|
|
|
CPUThread* thr = nullptr;
|
|
u32 thread_index = 0;
|
|
|
|
for (u32 i = 0; i < m_threads.size(); ++i)
|
|
{
|
|
if (m_threads[i]->m_wait_thread_id == id)
|
|
{
|
|
m_threads[i]->Wait(false);
|
|
m_threads[i]->m_wait_thread_id = -1;
|
|
}
|
|
|
|
if (m_threads[i]->GetId() != id) continue;
|
|
|
|
thr = m_threads[i];
|
|
thread_index = i;
|
|
}
|
|
|
|
if (thr)
|
|
{
|
|
SendDbgCommand(DID_REMOVE_THREAD, thr);
|
|
thr->Close();
|
|
|
|
m_threads.erase(m_threads.begin() + thread_index);
|
|
}
|
|
|
|
// Removing the ID should trigger the actual deletion of the thread
|
|
Emu.GetIdManager().RemoveID(id);
|
|
Emu.CheckStatus();
|
|
}
|
|
|
|
s32 CPUThreadManager::GetThreadNumById(CPUThreadType type, u32 id)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
|
|
|
s32 num = 0;
|
|
|
|
for(u32 i=0; i<m_threads.size(); ++i)
|
|
{
|
|
if(m_threads[i]->GetId() == id) return num;
|
|
if(m_threads[i]->GetType() == type) num++;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
CPUThread* CPUThreadManager::GetThread(u32 id)
|
|
{
|
|
CPUThread* res;
|
|
|
|
if (!id) return nullptr;
|
|
|
|
if (!Emu.GetIdManager().GetIDData(id, res)) return nullptr;
|
|
|
|
return res;
|
|
}
|
|
|
|
RawSPUThread* CPUThreadManager::GetRawSPUThread(u32 num)
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
|
|
|
for (u32 i = 0; i < m_threads.size(); i++)
|
|
{
|
|
if (m_threads[i]->GetType() == CPU_THREAD_RAW_SPU)
|
|
{
|
|
RawSPUThread* t = (RawSPUThread*)m_threads[i];
|
|
|
|
if (t->GetIndex() == num)
|
|
{
|
|
return t;
|
|
}
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void CPUThreadManager::NotifyThread(const u32 id)
|
|
{
|
|
if (!id) return;
|
|
|
|
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
|
|
|
for (u32 i = 0; i < m_threads.size(); i++)
|
|
{
|
|
if (m_threads[i]->GetId() == id)
|
|
{
|
|
m_threads[i]->Notify();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CPUThreadManager::Exec()
|
|
{
|
|
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
|
|
|
for(u32 i=0; i<m_threads.size(); ++i)
|
|
{
|
|
m_threads[i]->Exec();
|
|
}
|
|
}
|