From 0e1ca354a9f09267d2aaa6bf912a7a0e37787423 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 1 Aug 2023 12:49:57 +0300 Subject: [PATCH] Added Thread class --- CMakeLists.txt | 2 + src/Lib/Threads.cpp | 79 ++++++++++++++++++++++++ src/Lib/Threads.h | 125 ++++++++++++++++++++++++++++++++++++++ src/Lib/Timer.cpp | 143 +++++++++++++++++--------------------------- src/main.cpp | 9 ++- 5 files changed, 267 insertions(+), 91 deletions(-) create mode 100644 src/Lib/Threads.cpp create mode 100644 src/Lib/Threads.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 06d4e348..e949f732 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,8 @@ add_executable(shadps4 src/Core/Memory.h src/Core/PS4/Linker.cpp src/Core/PS4/Linker.h + src/Lib/Threads.cpp + src/Lib/Threads.h "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Util/StringUtil.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceVideoOut.cpp" "src/Core/PS4/HLE/LibSceVideoOut.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/Debug.h" "src/Core/PS4/HLE/Kernel/MemoryManagement.cpp" "src/Core/PS4/HLE/Kernel/MemoryManagement.h" "src/Core/PS4/HLE/Kernel/MemMngCodes.h" "src/Core/PS4/HLE/Kernel/PhysicalMemory.cpp" "src/Util/StringUtil.cpp") find_package(OpenGL REQUIRED) diff --git a/src/Lib/Threads.cpp b/src/Lib/Threads.cpp new file mode 100644 index 00000000..bd391f5e --- /dev/null +++ b/src/Lib/Threads.cpp @@ -0,0 +1,79 @@ +#include "Threads.h" + +#include + +static std::thread::id g_main_thread; +static int g_main_thread_int; +static std::atomic 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); } diff --git a/src/Lib/Threads.h b/src/Lib/Threads.h new file mode 100644 index 00000000..4ca5f515 --- /dev/null +++ b/src/Lib/Threads.h @@ -0,0 +1,125 @@ +#pragma once + +#include "windows.h" +#include +#include +#include +#include +#include + +#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; +}; +} // namespace Lib \ No newline at end of file diff --git a/src/Lib/Timer.cpp b/src/Lib/Timer.cpp index 421edf00..66cb9fa3 100644 --- a/src/Lib/Timer.cpp +++ b/src/Lib/Timer.cpp @@ -1,113 +1,80 @@ #include "Timer.h" +#include -#ifdef _WIN64 -#include "windows.h" -#endif - -Lib::Timer::Timer() -{ -#ifdef _WIN64 - LARGE_INTEGER f; - QueryPerformanceFrequency(&f); - m_Frequency = f.QuadPart; -#endif +Lib::Timer::Timer() { + LARGE_INTEGER f; + QueryPerformanceFrequency(&f); + m_Frequency = f.QuadPart; } -void Lib::Timer::Start() -{ -#ifdef _WIN64 - LARGE_INTEGER c; - QueryPerformanceCounter(&c); - m_StartTime = c.QuadPart; -#endif - m_is_timer_paused = false; +void Lib::Timer::Start() { + LARGE_INTEGER c; + QueryPerformanceCounter(&c); + m_StartTime = c.QuadPart; + m_is_timer_paused = false; } -void Lib::Timer::Pause() -{ -#ifdef _WIN64 - LARGE_INTEGER c; - QueryPerformanceCounter(&c); - m_PauseTime = c.QuadPart; -#endif - m_is_timer_paused = true; +void Lib::Timer::Pause() { + LARGE_INTEGER c; + QueryPerformanceCounter(&c); + m_PauseTime = c.QuadPart; + m_is_timer_paused = true; } -void Lib::Timer::Resume() -{ - u64 current_time = 0; +void Lib::Timer::Resume() { + u64 current_time = 0; -#ifdef _WIN64 - LARGE_INTEGER c; - QueryPerformanceCounter(&c); - current_time = c.QuadPart; -#endif + LARGE_INTEGER c; + QueryPerformanceCounter(&c); + current_time = c.QuadPart; - m_StartTime += current_time - m_PauseTime; - m_is_timer_paused = false; + m_StartTime += current_time - m_PauseTime; + m_is_timer_paused = false; } -bool Lib::Timer::IsPaused() const -{ - return m_is_timer_paused; +bool Lib::Timer::IsPaused() const { return m_is_timer_paused; } + +double Lib::Timer::GetTimeMsec() const { + if (m_is_timer_paused) { + return 1000.0 * (static_cast(m_PauseTime - m_StartTime)) / static_cast(m_Frequency); + } + + u64 current_time = 0; + + LARGE_INTEGER c; + QueryPerformanceCounter(&c); + current_time = c.QuadPart; + + return 1000.0 * (static_cast(current_time - m_StartTime)) / static_cast(m_Frequency); } -double Lib::Timer::GetTimeMsec() const -{ - if (m_is_timer_paused) - { - return 1000.0 * (static_cast(m_PauseTime - m_StartTime)) / static_cast(m_Frequency); - } +double Lib::Timer::GetTimeSec() const { + if (m_is_timer_paused) { + return (static_cast(m_PauseTime - m_StartTime)) / static_cast(m_Frequency); + } - u64 current_time = 0; + u64 current_time = 0; -#ifdef _WIN64 - LARGE_INTEGER c; - QueryPerformanceCounter(&c); - current_time = c.QuadPart; -#endif + LARGE_INTEGER c; + QueryPerformanceCounter(&c); + current_time = c.QuadPart; - return 1000.0 * (static_cast(current_time - m_StartTime)) / static_cast(m_Frequency); + return (static_cast(current_time - m_StartTime)) / static_cast(m_Frequency); } -double Lib::Timer::GetTimeSec() const -{ - if (m_is_timer_paused) - { - return (static_cast(m_PauseTime - m_StartTime)) / static_cast(m_Frequency); - } +u64 Lib::Timer::GetTicks() const { + if (m_is_timer_paused) { + return (m_PauseTime - m_StartTime); + } - u64 current_time = 0; + u64 current_time = 0; -#ifdef _WIN64 - LARGE_INTEGER c; - QueryPerformanceCounter(&c); - current_time = c.QuadPart; -#endif + LARGE_INTEGER c; + QueryPerformanceCounter(&c); + current_time = c.QuadPart; - return (static_cast(current_time - m_StartTime)) / static_cast(m_Frequency); + return (current_time - m_StartTime); } -u64 Lib::Timer::GetTicks() const -{ - if (m_is_timer_paused) - { - return (m_PauseTime - m_StartTime); - } - - u64 current_time = 0; - -#ifdef _WIN64 - LARGE_INTEGER c; - QueryPerformanceCounter(&c); - current_time = c.QuadPart; -#endif - - return (current_time - m_StartTime); -} - -u64 Lib::Timer::GetFrequency() const -{ - return m_Frequency; -} +u64 Lib::Timer::GetFrequency() const { return m_Frequency; } diff --git a/src/main.cpp b/src/main.cpp index 4d715777..ab3d0c9f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -29,17 +29,20 @@ #include #include #include "Core/PS4/HLE/Libs.h" +#include "Lib/Threads.h" // Main code int main(int argc, char* argv[]) { - /* if (argc == 1) { + if (argc == 1) { printf("Usage: %s \n", argv[0]); return -1; - }*/ + } logging::init(true);//init logging - const char* const path = argv[1]; // argument 1 is the path of self file to boot + Lib::InitThreads(); + const char* const path = argv[1]; //argument 1 is the path of self file to boot + auto* linker = Singleton::Instance(); HLE::Libs::Init_HLE_Libs(linker->getHLESymbols()); auto *module =linker->LoadModule(path);//load main executable