core: Switch to std threading primitives

This commit is contained in:
GPUCode 2023-10-22 17:10:25 +03:00
parent f39744cf62
commit e2b1b059ed
24 changed files with 98 additions and 329 deletions

View File

@ -83,8 +83,6 @@ add_executable(shadps4
src/Core/PS4/Stubs.cpp src/Core/PS4/Stubs.cpp
src/Core/PS4/Stubs.h src/Core/PS4/Stubs.h
src/Core/PS4/Util/aerolib.cpp src/Core/PS4/Util/aerolib.cpp
src/Lib/Threads.cpp
src/Lib/Threads.h
src/Core/PS4/HLE/Kernel/Objects/physical_memory.h src/Core/PS4/HLE/Kernel/Objects/physical_memory.h
src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp
src/Util/string_util.cpp src/Util/string_util.cpp

View File

@ -14,7 +14,7 @@ void* GPU::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) { void GPU::memorySetAllocArea(u64 virtual_addr, u64 size) {
auto* gpumemory = singleton<GPUMemory>::instance(); auto* gpumemory = singleton<GPUMemory>::instance();
Lib::LockMutexGuard lock(gpumemory->m_mutex); std::scoped_lock lock{gpumemory->m_mutex};
MemoryHeap h; MemoryHeap h;
h.allocated_virtual_addr = virtual_addr; h.allocated_virtual_addr = virtual_addr;
@ -80,7 +80,7 @@ void* GPU::GPUMemory::memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::Graphi
int virtual_addr_num, const GPUObject& info) { int virtual_addr_num, const GPUObject& info) {
auto* gpumemory = singleton<GPUMemory>::instance(); auto* gpumemory = singleton<GPUMemory>::instance();
Lib::LockMutexGuard lock(gpumemory->m_mutex); std::scoped_lock lock{gpumemory->m_mutex};
int heap_id = gpumemory->getHeapId(virtual_addr[0], size[0]); int heap_id = gpumemory->getHeapId(virtual_addr[0], size[0]);
@ -172,7 +172,7 @@ void GPU::GPUMemory::update(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx,
} }
void GPU::GPUMemory::flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx) { void GPU::GPUMemory::flushAllHeaps(HLE::Libs::Graphics::GraphicCtx* ctx) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
int heap_id = 0; int heap_id = 0;
for (auto& heap : m_heaps) { for (auto& heap : m_heaps) {

View File

@ -2,6 +2,7 @@
#include <Core/PS4/HLE/Graphics/graphics_ctx.h> #include <Core/PS4/HLE/Graphics/graphics_ctx.h>
#include <types.h> #include <types.h>
#include <mutex>
#include <vector> #include <vector>
namespace GPU { namespace GPU {
@ -66,7 +67,7 @@ class GPUMemory {
GPUMemory() {} GPUMemory() {}
virtual ~GPUMemory() {} virtual ~GPUMemory() {}
int getHeapId(u64 vaddr, u64 size); int getHeapId(u64 vaddr, u64 size);
Lib::Mutex m_mutex; std::mutex m_mutex;
std::vector<MemoryHeap> m_heaps; std::vector<MemoryHeap> m_heaps;
void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr, void* memoryCreateObj(u64 submit_id, HLE::Libs::Graphics::GraphicCtx* ctx, /*CommandBuffer* buffer*/ void* todo, const u64* virtual_addr,
const u64* size, int virtual_addr_num, const GPUObject& info); const u64* size, int virtual_addr_num, const GPUObject& info);

View File

@ -1,6 +1,6 @@
#include "tile_manager.h" #include "tile_manager.h"
#include "Lib/Threads.h"
#include "Emulator/Util/singleton.h" #include "Emulator/Util/singleton.h"
#include <mutex>
namespace GPU { namespace GPU {
@ -10,7 +10,7 @@ class TileManager {
public: public:
TileManager(){} TileManager(){}
virtual ~TileManager() { } virtual ~TileManager() { }
Lib::Mutex m_mutex; std::mutex m_mutex;
}; };
class TileManager32 { class TileManager32 {
@ -145,7 +145,7 @@ void convertTileToLinear(void* dst, const void* src,u32 width, u32 height, bool
auto* g_TileManager = singleton<TileManager>::instance(); auto* g_TileManager = singleton<TileManager>::instance();
Lib::LockMutexGuard lock(g_TileManager->m_mutex); std::scoped_lock lock{g_TileManager->m_mutex};
for (u32 y = 0; y < height; y++) { for (u32 y = 0; y < height; y++) {
u32 x = 0; u32 x = 0;

View File

@ -12,7 +12,7 @@ void VideoOutCtx::Init(u32 width, u32 height) {
m_video_out_ctx.m_resolution.paneHeight = height; m_video_out_ctx.m_resolution.paneHeight = height;
} }
int VideoOutCtx::Open() { int VideoOutCtx::Open() {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
int handle = -1; int handle = -1;
@ -30,7 +30,7 @@ int VideoOutCtx::Open() {
return handle; return handle;
} }
void VideoOutCtx::Close(s32 handle) { void VideoOutCtx::Close(s32 handle) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
m_video_out_ctx.isOpened = false; m_video_out_ctx.isOpened = false;
@ -55,18 +55,19 @@ void VideoOutCtx::Close(s32 handle) {
} }
VideoConfigInternal* VideoOutCtx::getCtx(int handle) { VideoConfigInternal* VideoOutCtx::getCtx(int handle) {
if (handle != 1) return nullptr; if (handle != 1) [[unlikely]] {
return nullptr;
}
return &m_video_out_ctx; // assuming that it's the only ctx TODO check if we need more return &m_video_out_ctx; // assuming that it's the only ctx TODO check if we need more
} }
void FlipQueue::getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out) { void FlipQueue::getFlipStatus(VideoConfigInternal* cfg, SceVideoOutFlipStatus* out) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock(m_mutex);
*out = cfg->m_flip_status; *out = cfg->m_flip_status;
} }
bool FlipQueue::submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg) { bool FlipQueue::submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
if (m_requests.size() >= 2) { if (m_requests.size() >= 2) {
return false; return false;
@ -83,50 +84,51 @@ bool FlipQueue::submitFlip(VideoConfigInternal* cfg, s32 index, s64 flip_arg) {
cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size()); cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size());
cfg->m_flip_status.gcQueueNum = 0; cfg->m_flip_status.gcQueueNum = 0;
m_submit_cond.SignalCondVar(); m_submit_cond.notify_one();
return true; return true;
} }
bool FlipQueue::flip(u32 micros) { bool FlipQueue::flip(u32 micros) {
m_mutex.LockMutex(); const auto request = [&]() -> Request* {
if (m_requests.size() == 0) { std::unique_lock lock{m_mutex};
m_submit_cond.WaitCondVarFor(&m_mutex, micros); m_submit_cond.wait_for(lock, std::chrono::microseconds(micros),
[&] { return !m_requests.empty(); });
if (m_requests.empty()) {
return nullptr;
}
return &m_requests.at(0); // Process first request
}();
if (m_requests.size() == 0) { if (!request) {
m_mutex.UnlockMutex();
return false; return false;
} }
}
auto request = m_requests.at(0); // proceed first request
m_mutex.UnlockMutex();
auto* buffer = request.cfg->buffers[request.index].buffer_render;
const auto buffer = request->cfg->buffers[request->index].buffer_render;
Emu::DrawBuffer(buffer); Emu::DrawBuffer(buffer);
m_mutex.LockMutex(); std::scoped_lock lock{m_mutex};
request.cfg->m_mutex.LockMutex(); {
for (auto& flip_eq : request.cfg->m_flip_evtEq) { std::scoped_lock cfg_lock{request->cfg->m_mutex};
for (auto& flip_eq : request->cfg->m_flip_evtEq) {
if (flip_eq != nullptr) { if (flip_eq != nullptr) {
flip_eq->triggerEvent(SCE_VIDEO_OUT_EVENT_FLIP, HLE::Kernel::Objects::EVFILT_VIDEO_OUT, reinterpret_cast<void*>(request.flip_arg)); flip_eq->triggerEvent(SCE_VIDEO_OUT_EVENT_FLIP, HLE::Kernel::Objects::EVFILT_VIDEO_OUT,
reinterpret_cast<void*>(request->flip_arg));
}
} }
} }
request.cfg->m_mutex.UnlockMutex();
m_requests.erase(m_requests.begin()); m_requests.erase(m_requests.begin());
m_done_cond.SignalCondVar(); m_done_cond.notify_one();
request.cfg->m_flip_status.count++; request->cfg->m_flip_status.count++;
//TODO request.cfg->m_flip_status.processTime = LibKernel::KernelGetProcessTime(); //TODO request.cfg->m_flip_status.processTime = LibKernel::KernelGetProcessTime();
request.cfg->m_flip_status.tsc = HLE::Libs::LibKernel::sceKernelReadTsc(); request->cfg->m_flip_status.tsc = HLE::Libs::LibKernel::sceKernelReadTsc();
request.cfg->m_flip_status.submitTsc = request.submit_tsc; request->cfg->m_flip_status.submitTsc = request->submit_tsc;
request.cfg->m_flip_status.flipArg = request.flip_arg; request->cfg->m_flip_status.flipArg = request->flip_arg;
request.cfg->m_flip_status.currentBuffer = request.index; request->cfg->m_flip_status.currentBuffer = request->index;
request.cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size()); request->cfg->m_flip_status.flipPendingNum = static_cast<int>(m_requests.size());
m_mutex.UnlockMutex();
return false; return false;
} }

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <condition_variable>
#include <mutex>
#include <Core/PS4/HLE/Graphics/video_out.h> #include <Core/PS4/HLE/Graphics/video_out.h>
#include <Lib/Threads.h>
#include <Core/PS4/HLE/Graphics/graphics_ctx.h> #include <Core/PS4/HLE/Graphics/graphics_ctx.h>
#include <emulator.h> #include <emulator.h>
@ -17,7 +19,7 @@ struct VideoOutBufferInfo {
}; };
struct VideoConfigInternal { struct VideoConfigInternal {
Lib::Mutex m_mutex; std::mutex m_mutex;
SceVideoOutResolutionStatus m_resolution; SceVideoOutResolutionStatus m_resolution;
bool isOpened = false; bool isOpened = false;
SceVideoOutFlipStatus m_flip_status; SceVideoOutFlipStatus m_flip_status;
@ -45,9 +47,9 @@ class FlipQueue {
uint64_t submit_tsc; uint64_t submit_tsc;
}; };
Lib::Mutex m_mutex; std::mutex m_mutex;
Lib::ConditionVariable m_submit_cond; std::condition_variable m_submit_cond;
Lib::ConditionVariable m_done_cond; std::condition_variable m_done_cond;
std::vector<Request> m_requests; std::vector<Request> m_requests;
}; };
@ -62,16 +64,16 @@ class VideoOutCtx {
VideoConfigInternal* getCtx(int handle); VideoConfigInternal* getCtx(int handle);
FlipQueue& getFlipQueue() { return m_flip_queue; } FlipQueue& getFlipQueue() { return m_flip_queue; }
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
if (m_graphic_ctx == nullptr) { if (!m_graphic_ctx) {
m_graphic_ctx = Emu::getGraphicCtx(); m_graphic_ctx = Emu::getGraphicCtx();
} }
return m_graphic_ctx; return m_graphic_ctx;
} }
private: private:
Lib::Mutex m_mutex; std::mutex m_mutex;
VideoConfigInternal m_video_out_ctx; VideoConfigInternal m_video_out_ctx;
FlipQueue m_flip_queue; FlipQueue m_flip_queue;
HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr; HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr;

View File

@ -2,13 +2,12 @@
#include <types.h> #include <types.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include <mutex>
#include "Lib/Threads.h"
namespace HLE::Libs::Graphics { namespace HLE::Libs::Graphics {
struct VulkanCommandPool { struct VulkanCommandPool {
Lib::Mutex mutex; std::mutex mutex;
VkCommandPool pool = nullptr; VkCommandPool pool = nullptr;
VkCommandBuffer* buffers = nullptr; VkCommandBuffer* buffers = nullptr;
VkFence* fences = nullptr; VkFence* fences = nullptr;
@ -18,7 +17,7 @@ struct VulkanCommandPool {
}; };
struct VulkanQueueInfo { struct VulkanQueueInfo {
Lib::Mutex* mutex = nullptr; std::mutex* mutex = nullptr;
u32 family = static_cast<u32>(-1); u32 family = static_cast<u32>(-1);
u32 index = static_cast<u32>(-1); u32 index = static_cast<u32>(-1);
VkQueue vk_queue = nullptr; VkQueue vk_queue = nullptr;

View File

@ -14,7 +14,7 @@ void GPU::renderCreateCtx() {
void GPU::CommandBuffer::allocateBuffer() { void GPU::CommandBuffer::allocateBuffer() {
m_pool = g_command_pool.getPool(m_queue); m_pool = g_command_pool.getPool(m_queue);
Lib::LockMutexGuard lock(m_pool->mutex); std::scoped_lock lock{m_pool->mutex};
for (uint32_t i = 0; i < m_pool->buffers_count; i++) { for (uint32_t i = 0; i < m_pool->buffers_count; i++) {
if (!m_pool->busy[i]) { if (!m_pool->busy[i]) {
@ -27,7 +27,7 @@ void GPU::CommandBuffer::allocateBuffer() {
} }
void GPU::CommandBuffer::freeBuffer() { void GPU::CommandBuffer::freeBuffer() {
Lib::LockMutexGuard lock(m_pool->mutex); std::scoped_lock lock{m_pool->mutex};
waitForFence(); waitForFence();
@ -91,17 +91,8 @@ void GPU::CommandBuffer::executeWithSemaphore() {
auto* render_ctx = singleton<RenderCtx>::instance(); auto* render_ctx = singleton<RenderCtx>::instance();
const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue]; const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue];
if (queue.mutex != nullptr) {
queue.mutex->LockMutex();
}
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence); auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
if (queue.mutex != nullptr) {
queue.mutex->LockMutex();
}
m_execute = true; m_execute = true;
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {
@ -126,17 +117,8 @@ void GPU::CommandBuffer::execute() {
auto* render_ctx = singleton<RenderCtx>::instance(); auto* render_ctx = singleton<RenderCtx>::instance();
const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue]; const auto& queue = render_ctx->getGraphicCtx()->queues[m_queue];
if (queue.mutex != nullptr) {
queue.mutex->LockMutex();
}
auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence); auto result = vkQueueSubmit(queue.vk_queue, 1, &submit_info, fence);
if (queue.mutex != nullptr) {
queue.mutex->UnlockMutex();
}
m_execute = true; m_execute = true;
if (result != VK_SUCCESS) { if (result != VK_SUCCESS) {

View File

@ -94,7 +94,7 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(LibKernel::EventQueues::SceKernelEqueue
if (ctx == nullptr) { if (ctx == nullptr) {
return SCE_VIDEO_OUT_ERROR_INVALID_HANDLE; return SCE_VIDEO_OUT_ERROR_INVALID_HANDLE;
} }
Lib::LockMutexGuard lock(ctx->m_mutex); std::scoped_lock lock(ctx->m_mutex);
if (eq == nullptr) { if (eq == nullptr) {
return SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE; return SCE_VIDEO_OUT_ERROR_INVALID_EVENT_QUEUE;

View File

@ -8,7 +8,7 @@ namespace HLE::Kernel::Objects {
EqueueInternal::~EqueueInternal() {} EqueueInternal::~EqueueInternal() {}
int EqueueInternal::addEvent(const EqueueEvent& event) { int EqueueInternal::addEvent(const EqueueEvent& event) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
if (m_events.size() > 0) { if (m_events.size() > 0) {
BREAKPOINT(); BREAKPOINT();
@ -24,7 +24,7 @@ int EqueueInternal::addEvent(const EqueueEvent& event) {
} }
int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) { int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
Lib::LockMutexGuard lock(m_mutex); std::unique_lock lock{m_mutex};
u32 timeElapsed = 0; u32 timeElapsed = 0;
Lib::Timer t; Lib::Timer t;
@ -38,9 +38,9 @@ int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
} }
if (micros == 0) { if (micros == 0) {
m_cond.WaitCondVar(&m_mutex); m_cond.wait(lock);
} else { } else {
m_cond.WaitCondVarFor(&m_mutex, micros - timeElapsed); m_cond.wait_for(lock, std::chrono::microseconds(micros - timeElapsed));
} }
timeElapsed = static_cast<uint32_t>(t.GetTimeSec() * 1000000.0); timeElapsed = static_cast<uint32_t>(t.GetTimeSec() * 1000000.0);
@ -50,7 +50,7 @@ int EqueueInternal::waitForEvents(SceKernelEvent* ev, int num, u32 micros) {
} }
bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) { bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
if (m_events.size() > 1) { if (m_events.size() > 1) {
BREAKPOINT(); // we currently support one event BREAKPOINT(); // we currently support one event
@ -63,14 +63,12 @@ bool EqueueInternal::triggerEvent(u64 ident, s16 filter, void* trigger_data) {
event.isTriggered = true; event.isTriggered = true;
} }
m_cond.SignalCondVar(); m_cond.notify_one();
return true; return true;
} }
int EqueueInternal::getTriggeredEvents(SceKernelEvent* ev, int num) { int EqueueInternal::getTriggeredEvents(SceKernelEvent* ev, int num) {
Lib::LockMutexGuard lock(m_mutex);
int ret = 0; int ret = 0;
if (m_events.size() > 1) { if (m_events.size() > 1) {

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <types.h> #include <types.h>
#include <Lib/Threads.h> #include <mutex>
#include <string> #include <string>
#include <vector> #include <vector>
@ -71,8 +72,8 @@ class EqueueInternal {
int getTriggeredEvents(SceKernelEvent* ev, int num); int getTriggeredEvents(SceKernelEvent* ev, int num);
private: private:
std::string m_name; std::string m_name;
Lib::Mutex m_mutex; std::mutex m_mutex;
std::vector<EqueueEvent> m_events; std::vector<EqueueEvent> m_events;
Lib::ConditionVariable m_cond; std::condition_variable m_cond;
}; };
}; // namespace HLE::Kernel::Objects }; // namespace HLE::Kernel::Objects

View File

@ -5,7 +5,7 @@ namespace HLE::Kernel::Objects {
static u64 AlignUp(u64 pos, u64 align) { return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos); } static u64 AlignUp(u64 pos, u64 align) { return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos); }
bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut, int memoryType) { bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut, int memoryType) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
u64 find_free_pos = 0; u64 find_free_pos = 0;
// iterate through allocated blocked and find the next free position // iterate through allocated blocked and find the next free position
@ -40,7 +40,7 @@ bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignmen
return false; return false;
} }
bool PhysicalMemory::Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::MemoryMode gpu_mode) { bool PhysicalMemory::Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::MemoryMode gpu_mode) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
for (auto& b : m_allocatedBlocks) { for (auto& b : m_allocatedBlocks) {
if (phys_addr >= b.start_addr && phys_addr < b.start_addr + b.size) { if (phys_addr >= b.start_addr && phys_addr < b.start_addr + b.size) {
if (b.map_virtual_addr != 0 || b.map_size != 0) { if (b.map_virtual_addr != 0 || b.map_size != 0) {

View File

@ -2,8 +2,8 @@
#include <types.h> #include <types.h>
#include <Core/virtual_memory.h> #include <Core/virtual_memory.h>
#include <Core/PS4/GPU/gpu_memory.h> #include <Core/PS4/GPU/gpu_memory.h>
#include <mutex>
#include <vector> #include <vector>
#include "Lib/Threads.h"
namespace HLE::Kernel::Objects { namespace HLE::Kernel::Objects {
@ -28,7 +28,7 @@ class PhysicalMemory {
private: private:
std::vector<AllocatedBlock> m_allocatedBlocks; std::vector<AllocatedBlock> m_allocatedBlocks;
Lib::Mutex m_mutex; std::mutex m_mutex;
}; };
} // namespace HLE::Kernel::Objects } // namespace HLE::Kernel::Objects

View File

@ -2,6 +2,7 @@
#include <Util/log.h> #include <Util/log.h>
#include <debug.h> #include <debug.h>
#include <windows.h>
#include "Emulator/Util/singleton.h" #include "Emulator/Util/singleton.h"
#include "../Loader/Elf.h" #include "../Loader/Elf.h"

View File

@ -70,7 +70,7 @@ static std::string encodeId(u64 nVal)
} }
Module* Linker::LoadModule(const std::string& elf_name) Module* Linker::LoadModule(const std::string& elf_name)
{ {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
auto* m = new Module; auto* m = new Module;
m->linker = this; m->linker = this;
m->elf = new Elf; m->elf = new Elf;

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <mutex>
#include "Loader/Elf.h" #include "Loader/Elf.h"
#include "Loader/SymbolsResolver.h" #include "Loader/SymbolsResolver.h"
#include "Lib/Threads.h"
struct DynamicModuleInfo; struct DynamicModuleInfo;
class Linker; class Linker;
@ -130,5 +130,5 @@ public:
std::vector<Module*> m_modules; std::vector<Module*> m_modules;
SymbolsResolver* m_HLEsymbols = nullptr; SymbolsResolver* m_HLEsymbols = nullptr;
Lib::Mutex m_mutex; std::mutex m_mutex;
}; };

View File

@ -5,7 +5,7 @@ GameController::GameController() { m_states_num = 0;
m_last_state = State(); m_last_state = State();
} }
void GameController::readState(State* state, bool* isConnected, int* connectedCount) { void GameController::readState(State* state, bool* isConnected, int* connectedCount) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
*isConnected = m_connected; *isConnected = m_connected;
*connectedCount = m_connected_count; *connectedCount = m_connected_count;
@ -37,7 +37,7 @@ void GameController::addState(const State& state) {
} }
void GameController::checKButton(int id, u32 button, bool isPressed) { void GameController::checKButton(int id, u32 button, bool isPressed) {
Lib::LockMutexGuard lock(m_mutex); std::scoped_lock lock{m_mutex};
auto state = getLastState(); auto state = getLastState();
if (isPressed) { if (isPressed) {
state.buttonsState |= button; state.buttonsState |= button;

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <types.h> #include <types.h>
#include "Lib/Threads.h" #include <mutex>
namespace Emulator::Host::Controller { namespace Emulator::Host::Controller {
struct State { struct State {
@ -21,7 +21,7 @@ class GameController {
private: private:
Lib::Mutex m_mutex; std::mutex m_mutex;
bool m_connected = false; bool m_connected = false;
State m_last_state; State m_last_state;
int m_connected_count = 0; int m_connected_count = 0;

View File

@ -1,79 +0,0 @@
#include "Threads.h"
#include <sstream>
static std::thread::id g_main_thread;
static int g_main_thread_int;
static std::atomic<int> g_thread_counter = 0;
void Lib::InitThreads() {
g_main_thread = std::this_thread::get_id();
g_main_thread_int = Lib::Thread::GetThreadIdUnique();
}
Lib::Thread::Thread(thread_func_t func, void* arg) {
m_thread = new ThreadStructInternal(func, arg);
while (!m_thread->started) {
SleepThreadMicro(1000);
}
}
Lib::Thread::~Thread() { delete m_thread; }
void Lib::Thread::JoinThread() { m_thread->m_thread.join(); }
void Lib::Thread::DetachThread() { m_thread->m_thread.detach(); }
std::string Lib::Thread::GetId() const {
std::stringstream ss;
ss << m_thread->m_thread.get_id();
return ss.str().c_str();
}
int Lib::Thread::GetUniqueId() const { return m_thread->unique_id; }
void Lib::Thread::SleepThread(u32 millis) { std::this_thread::sleep_for(std::chrono::milliseconds(millis)); }
void Lib::Thread::SleepThreadMicro(u32 micros) { std::this_thread::sleep_for(std::chrono::microseconds(micros)); }
void Lib::Thread::SleepThreadNano(u64 nanos) { std::this_thread::sleep_for(std::chrono::nanoseconds(nanos)); }
bool Lib::Thread::IsMainThread() { return g_main_thread == std::this_thread::get_id(); }
std::string Lib::Thread::GetThreadId() {
std::stringstream ss;
ss << std::this_thread::get_id();
return ss.str().c_str();
}
int Lib::Thread::GetThreadIdUnique() {
static thread_local int tid = ++g_thread_counter;
return tid;
}
Lib::Mutex::Mutex() { m_mutex = new MutexStructInternal(); }
Lib::Mutex::~Mutex() { delete m_mutex; }
void Lib::Mutex::LockMutex() { EnterCriticalSection(&m_mutex->m_cs); }
void Lib::Mutex::UnlockMutex() { LeaveCriticalSection(&m_mutex->m_cs); }
bool Lib::Mutex::TryLockMutex() { return (TryEnterCriticalSection(&m_mutex->m_cs) != 0); }
Lib::ConditionVariable::ConditionVariable() { m_cond_var = new ConditionVariableStructInternal(); }
Lib::ConditionVariable::~ConditionVariable() { delete m_cond_var; }
void Lib::ConditionVariable::WaitCondVar(Mutex* mutex) { SleepConditionVariableCS(&m_cond_var->m_cv, &mutex->m_mutex->m_cs, INFINITE); }
bool Lib::ConditionVariable::WaitCondVarFor(Mutex* mutex, u32 micros) {
bool ok = false;
ok = !(SleepConditionVariableCS(&m_cond_var->m_cv, &mutex->m_mutex->m_cs, (micros < 1000 ? 1 : micros / 1000)) == 0 &&
GetLastError() == ERROR_TIMEOUT);
return ok;
}
void Lib::ConditionVariable::SignalCondVar() { WakeConditionVariable(&m_cond_var->m_cv); }
void Lib::ConditionVariable::SignalCondVarAll() { WakeAllConditionVariable(&m_cond_var->m_cv); }

View File

@ -1,131 +0,0 @@
#pragma once
#include "windows.h"
#include <synchapi.h>
#include <atomic>
#include <condition_variable>
#include <string>
#include <thread>
#include "../types.h"
namespace Lib {
using thread_func_t = void (*)(void*);
void InitThreads();
struct ThreadStructInternal;
struct MutexStructInternal;
struct ConditionVariableStructInternal;
class Thread {
public:
Thread(thread_func_t func, void* arg);
virtual ~Thread();
void JoinThread();
void DetachThread();
std::string GetId() const;
int GetUniqueId() const;
static void SleepThread(u32 millis);
static void SleepThreadMicro(u32 micros);
static void SleepThreadNano(u64 nanos);
static bool IsMainThread();
// Get current thread id (reusable id)
static std::string GetThreadId();
// Get current thread id (unique id)
static int GetThreadIdUnique();
public:
Thread(const Thread&) = delete;
Thread& operator=(const Thread&) = delete;
Thread(Thread&&) = delete;
Thread& operator=(Thread&&) = delete;
private:
ThreadStructInternal* m_thread;
};
struct ThreadStructInternal {
ThreadStructInternal(thread_func_t f, void* a) : func(f), arg(a), m_thread(&Run, this) {}
static void Run(ThreadStructInternal* t) {
t->unique_id = Lib::Thread::GetThreadIdUnique();
t->started = true;
t->func(t->arg);
}
thread_func_t func;
void* arg;
std::atomic_bool started = false;
int unique_id = 0;
std::thread m_thread;
};
class Mutex {
public:
Mutex();
virtual ~Mutex();
void LockMutex();
void UnlockMutex();
bool TryLockMutex();
friend class ConditionVariable;
public:
Mutex(const Mutex&) = delete;
Mutex& operator=(const Mutex&) = delete;
Mutex(Mutex&&) = delete;
Mutex& operator=(Mutex&&) = delete;
private:
MutexStructInternal* m_mutex;
};
struct MutexStructInternal {
MutexStructInternal() { InitializeCriticalSectionAndSpinCount(&m_cs, 4000); }
~MutexStructInternal() { DeleteCriticalSection(&m_cs); }
CRITICAL_SECTION m_cs{};
};
class ConditionVariable {
public:
ConditionVariable();
virtual ~ConditionVariable();
void WaitCondVar(Mutex* mutex);
bool WaitCondVarFor(Mutex* mutex, u32 micros);
void SignalCondVar();
void SignalCondVarAll();
private:
ConditionVariableStructInternal* m_cond_var;
};
struct ConditionVariableStructInternal {
ConditionVariableStructInternal() { InitializeConditionVariable(&m_cv); }
~ConditionVariableStructInternal() = default;
CONDITION_VARIABLE m_cv{};
};
class LockMutexGuard {
public:
explicit LockMutexGuard(Mutex& m) : m_mutex(m) { m_mutex.LockMutex(); }
~LockMutexGuard() { m_mutex.UnlockMutex(); }
private:
Mutex& m_mutex;
public:
LockMutexGuard(const LockMutexGuard&) = delete;
LockMutexGuard& operator=(const LockMutexGuard&) = delete;
LockMutexGuard(LockMutexGuard&&) noexcept = delete;
LockMutexGuard& operator=(LockMutexGuard&&) noexcept = delete;
};
} // namespace Lib

View File

@ -22,10 +22,10 @@ void emuInit(u32 width, u32 height) {
void checkAndWaitForGraphicsInit() { void checkAndWaitForGraphicsInit() {
auto* window_ctx = singleton<Emu::WindowCtx>::instance(); auto* window_ctx = singleton<Emu::WindowCtx>::instance();
Lib::LockMutexGuard lock(window_ctx->m_mutex); std::unique_lock lock{window_ctx->m_mutex};
while (!window_ctx->m_is_graphic_initialized) { while (!window_ctx->m_is_graphic_initialized) {
window_ctx->m_graphic_initialized_cond.WaitCondVar(&window_ctx->m_mutex); window_ctx->m_graphic_initialized_cond.wait(lock);
} }
} }
static void CreateSdlWindow(WindowCtx* ctx) { static void CreateSdlWindow(WindowCtx* ctx) {
@ -51,15 +51,14 @@ static void CreateSdlWindow(WindowCtx* ctx) {
} }
void emuRun() { void emuRun() {
auto* window_ctx = singleton<Emu::WindowCtx>::instance(); auto* window_ctx = singleton<Emu::WindowCtx>::instance();
window_ctx->m_mutex.LockMutex();
{ {
// init window and wait until init finishes // init window and wait until init finishes
std::scoped_lock lock{window_ctx->m_mutex};
CreateSdlWindow(window_ctx); CreateSdlWindow(window_ctx);
Graphics::Vulkan::vulkanCreate(window_ctx); Graphics::Vulkan::vulkanCreate(window_ctx);
window_ctx->m_is_graphic_initialized = true; window_ctx->m_is_graphic_initialized = true;
window_ctx->m_graphic_initialized_cond.SignalCondVar(); window_ctx->m_graphic_initialized_cond.notify_one();
} }
window_ctx->m_mutex.UnlockMutex();
bool exit_loop = false; bool exit_loop = false;
@ -99,8 +98,7 @@ void emuRun() {
HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() { HLE::Libs::Graphics::GraphicCtx* getGraphicCtx() {
auto* window_ctx = singleton<Emu::WindowCtx>::instance(); auto* window_ctx = singleton<Emu::WindowCtx>::instance();
Lib::LockMutexGuard lock(window_ctx->m_mutex); std::scoped_lock lock{window_ctx->m_mutex};
return &window_ctx->m_graphic_ctx; return &window_ctx->m_graphic_ctx;
} }

View File

@ -1,8 +1,10 @@
#pragma once #pragma once
#include <Core/PS4/HLE/Graphics/graphics_ctx.h> #include <Core/PS4/HLE/Graphics/graphics_ctx.h>
#include <Lib/Threads.h>
#include <SDL.h> #include <SDL.h>
#include <mutex>
#include <condition_variable>
#include <vector> #include <vector>
namespace Emu { namespace Emu {
@ -57,9 +59,9 @@ struct VulkanSwapchain {
struct WindowCtx { struct WindowCtx {
HLE::Libs::Graphics::GraphicCtx m_graphic_ctx; HLE::Libs::Graphics::GraphicCtx m_graphic_ctx;
Lib::Mutex m_mutex; std::mutex m_mutex;
bool m_is_graphic_initialized = false; bool m_is_graphic_initialized = false;
Lib::ConditionVariable m_graphic_initialized_cond; std::condition_variable m_graphic_initialized_cond;
SDL_Window* m_window = nullptr; SDL_Window* m_window = nullptr;
bool is_window_hidden = true; bool is_window_hidden = true;
VkSurfaceKHR m_surface = nullptr; VkSurfaceKHR m_surface = nullptr;
@ -69,7 +71,7 @@ struct WindowCtx {
struct EmuPrivate { struct EmuPrivate {
EmuPrivate() = default; EmuPrivate() = default;
Lib::Mutex m_mutex; std::mutex m_mutex;
HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr; HLE::Libs::Graphics::GraphicCtx* m_graphic_ctx = nullptr;
void* data1 = nullptr; void* data1 = nullptr;
void* data2 = nullptr; void* data2 = nullptr;

View File

@ -31,10 +31,10 @@
#include <emulator.h> #include <emulator.h>
#include <inttypes.h> #include <inttypes.h>
#include <stdio.h> #include <stdio.h>
#include <thread>
#include "Core/PS4/HLE/Libs.h" #include "Core/PS4/HLE/Libs.h"
#include "Core/PS4/Linker.h" #include "Core/PS4/Linker.h"
#include "Lib/Threads.h"
#include "Emulator/Util\singleton.h" #include "Emulator/Util\singleton.h"
#include "discord.h" #include "discord.h"
@ -50,25 +50,22 @@ int main(int argc, char* argv[]) {
auto height = Config::getScreenHeight(); auto height = Config::getScreenHeight();
Emu::emuInit(width, height); Emu::emuInit(width, height);
HLE::Libs::Graphics::VideoOut::videoOutInit(width, height); HLE::Libs::Graphics::VideoOut::videoOutInit(width, height);
Lib::InitThreads();
const char* const path = argv[1]; // argument 1 is the path of self file to boot const char* const path = argv[1]; // argument 1 is the path of self file to boot
auto* linker = singleton<Linker>::instance(); auto* linker = singleton<Linker>::instance();
HLE::Libs::Init_HLE_Libs(linker->getHLESymbols()); HLE::Libs::Init_HLE_Libs(linker->getHLESymbols());
auto* module = linker->LoadModule(path); // load main executable auto* module = linker->LoadModule(path); // load main executable
Lib::Thread mainthread( std::jthread mainthread(
[](void*) { [](std::stop_token stop_token, void*) {
auto* linker = singleton<Linker>::instance(); auto* linker = singleton<Linker>::instance();
linker->Execute(); linker->Execute();
}, },
nullptr); nullptr);
mainthread.DetachThread();
Discord::RPC discordRPC; Discord::RPC discordRPC;
discordRPC.init(); discordRPC.init();
discordRPC.update(Discord::RPCStatus::Idling, ""); discordRPC.update(Discord::RPCStatus::Idling, "");
Emu::emuRun(); Emu::emuRun();
mainthread.JoinThread();
#if 0 #if 0
// Setup SDL // Setup SDL

View File

@ -81,8 +81,6 @@ void Graphics::Vulkan::vulkanCreate(Emu::WindowCtx* ctx) {
Emu::VulkanSwapchain* Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count) { Emu::VulkanSwapchain* Graphics::Vulkan::vulkanCreateSwapchain(HLE::Libs::Graphics::GraphicCtx* ctx, u32 image_count) {
auto* window_ctx = singleton<Emu::WindowCtx>::instance(); auto* window_ctx = singleton<Emu::WindowCtx>::instance();
Lib::LockMutexGuard lock(window_ctx->m_mutex);
auto* s = new Emu::VulkanSwapchain; auto* s = new Emu::VulkanSwapchain;
VkExtent2D extent{}; VkExtent2D extent{};
@ -189,7 +187,7 @@ void Graphics::Vulkan::vulkanCreateQueues(HLE::Libs::Graphics::GraphicCtx* ctx,
ctx->queues[id].index = info.index; ctx->queues[id].index = info.index;
vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue); vkGetDeviceQueue(ctx->m_device, ctx->queues[id].family, ctx->queues[id].index, &ctx->queues[id].vk_queue);
if (with_mutex) { if (with_mutex) {
ctx->queues[id].mutex = new Lib::Mutex; ctx->queues[id].mutex = new std::mutex;
} }
}; };