Added Thread class
This commit is contained in:
parent
692759099f
commit
0e1ca354a9
|
@ -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)
|
||||||
|
|
|
@ -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); }
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
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<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
|
||||||
|
|
Loading…
Reference in New Issue