Added Thread class

This commit is contained in:
georgemoralis 2023-08-01 12:49:57 +03:00
parent 692759099f
commit 0e1ca354a9
5 changed files with 267 additions and 91 deletions

View File

@ -34,6 +34,8 @@ add_executable(shadps4
src/Core/Memory.h src/Core/Memory.h
src/Core/PS4/Linker.cpp src/Core/PS4/Linker.cpp
src/Core/PS4/Linker.h 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") "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) find_package(OpenGL REQUIRED)

79
src/Lib/Threads.cpp Normal file
View File

@ -0,0 +1,79 @@
#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); }

125
src/Lib/Threads.h Normal file
View File

@ -0,0 +1,125 @@
#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;
};
} // namespace Lib

View File

@ -1,113 +1,80 @@
#include "Timer.h" #include "Timer.h"
#include <windows.h>
#ifdef _WIN64 Lib::Timer::Timer() {
#include "windows.h"
#endif
Lib::Timer::Timer()
{
#ifdef _WIN64
LARGE_INTEGER f; LARGE_INTEGER f;
QueryPerformanceFrequency(&f); QueryPerformanceFrequency(&f);
m_Frequency = f.QuadPart; m_Frequency = f.QuadPart;
#endif
} }
void Lib::Timer::Start() void Lib::Timer::Start() {
{
#ifdef _WIN64
LARGE_INTEGER c; LARGE_INTEGER c;
QueryPerformanceCounter(&c); QueryPerformanceCounter(&c);
m_StartTime = c.QuadPart; m_StartTime = c.QuadPart;
#endif
m_is_timer_paused = false; m_is_timer_paused = false;
} }
void Lib::Timer::Pause() void Lib::Timer::Pause() {
{
#ifdef _WIN64
LARGE_INTEGER c; LARGE_INTEGER c;
QueryPerformanceCounter(&c); QueryPerformanceCounter(&c);
m_PauseTime = c.QuadPart; m_PauseTime = c.QuadPart;
#endif
m_is_timer_paused = true; m_is_timer_paused = true;
} }
void Lib::Timer::Resume() void Lib::Timer::Resume() {
{
u64 current_time = 0; u64 current_time = 0;
#ifdef _WIN64
LARGE_INTEGER c; LARGE_INTEGER c;
QueryPerformanceCounter(&c); QueryPerformanceCounter(&c);
current_time = c.QuadPart; current_time = c.QuadPart;
#endif
m_StartTime += current_time - m_PauseTime; m_StartTime += current_time - m_PauseTime;
m_is_timer_paused = false; m_is_timer_paused = false;
} }
bool Lib::Timer::IsPaused() const bool Lib::Timer::IsPaused() const { return m_is_timer_paused; }
{
return m_is_timer_paused;
}
double Lib::Timer::GetTimeMsec() const double Lib::Timer::GetTimeMsec() const {
{ if (m_is_timer_paused) {
if (m_is_timer_paused)
{
return 1000.0 * (static_cast<double>(m_PauseTime - m_StartTime)) / static_cast<double>(m_Frequency); return 1000.0 * (static_cast<double>(m_PauseTime - m_StartTime)) / static_cast<double>(m_Frequency);
} }
u64 current_time = 0; u64 current_time = 0;
#ifdef _WIN64
LARGE_INTEGER c; LARGE_INTEGER c;
QueryPerformanceCounter(&c); QueryPerformanceCounter(&c);
current_time = c.QuadPart; current_time = c.QuadPart;
#endif
return 1000.0 * (static_cast<double>(current_time - m_StartTime)) / static_cast<double>(m_Frequency); return 1000.0 * (static_cast<double>(current_time - m_StartTime)) / static_cast<double>(m_Frequency);
} }
double Lib::Timer::GetTimeSec() const double Lib::Timer::GetTimeSec() const {
{ if (m_is_timer_paused) {
if (m_is_timer_paused)
{
return (static_cast<double>(m_PauseTime - m_StartTime)) / static_cast<double>(m_Frequency); return (static_cast<double>(m_PauseTime - m_StartTime)) / static_cast<double>(m_Frequency);
} }
u64 current_time = 0; u64 current_time = 0;
#ifdef _WIN64
LARGE_INTEGER c; LARGE_INTEGER c;
QueryPerformanceCounter(&c); QueryPerformanceCounter(&c);
current_time = c.QuadPart; current_time = c.QuadPart;
#endif
return (static_cast<double>(current_time - m_StartTime)) / static_cast<double>(m_Frequency); return (static_cast<double>(current_time - m_StartTime)) / static_cast<double>(m_Frequency);
} }
u64 Lib::Timer::GetTicks() const u64 Lib::Timer::GetTicks() const {
{ if (m_is_timer_paused) {
if (m_is_timer_paused)
{
return (m_PauseTime - m_StartTime); return (m_PauseTime - m_StartTime);
} }
u64 current_time = 0; u64 current_time = 0;
#ifdef _WIN64
LARGE_INTEGER c; LARGE_INTEGER c;
QueryPerformanceCounter(&c); QueryPerformanceCounter(&c);
current_time = c.QuadPart; current_time = c.QuadPart;
#endif
return (current_time - m_StartTime); return (current_time - m_StartTime);
} }
u64 Lib::Timer::GetFrequency() const u64 Lib::Timer::GetFrequency() const { return m_Frequency; }
{
return m_Frequency;
}

View File

@ -29,17 +29,20 @@
#include <inttypes.h> #include <inttypes.h>
#include <Zydis/Zydis.h> #include <Zydis/Zydis.h>
#include "Core/PS4/HLE/Libs.h" #include "Core/PS4/HLE/Libs.h"
#include "Lib/Threads.h"
// Main code // Main code
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
/* if (argc == 1) { if (argc == 1) {
printf("Usage: %s <elf or eboot.bin path>\n", argv[0]); printf("Usage: %s <elf or eboot.bin path>\n", argv[0]);
return -1; return -1;
}*/ }
logging::init(true);//init logging logging::init(true);//init logging
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