Merge pull request #27 from georgemoralis/pthreads

Pthreads
This commit is contained in:
georgemoralis 2023-07-20 13:36:08 +03:00 committed by GitHub
commit 1474e9d87d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 241 additions and 20 deletions

1
.gitignore vendored
View File

@ -31,6 +31,7 @@ bld/
[Oo]bj/ [Oo]bj/
[Ll]og/ [Ll]og/
[Ll]ogs/ [Ll]ogs/
[Bb]uild/
# Visual Studio 2015/2017 cache/options directory # Visual Studio 2015/2017 cache/options directory
.vs/ .vs/

4
.gitmodules vendored
View File

@ -22,3 +22,7 @@
path = third-party/zydis path = third-party/zydis
url = https://github.com/zyantific/zydis.git url = https://github.com/zyantific/zydis.git
shallow = true shallow = true
[submodule "third-party/winpthread"]
path = third-party/winpthread
url = https://github.com/shadps4/winpthread.git
branch = main

View File

@ -15,8 +15,8 @@ include_directories(third-party/sdl/)
include_directories(third-party/fmt/include) include_directories(third-party/fmt/include)
include_directories(third-party/magic_enum/include) include_directories(third-party/magic_enum/include)
include_directories(third-party/zydis/include/Zydis) include_directories(third-party/zydis/include/Zydis)
include_directories(third-party/winpthread/include)
add_subdirectory("third-party") add_subdirectory("third-party")
#=================== EXAMPLE =================== #=================== EXAMPLE ===================
add_executable(shadps4 add_executable(shadps4
@ -34,13 +34,15 @@ 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/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/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")
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
target_link_libraries(shadps4 PUBLIC fmt spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY}) target_link_libraries(shadps4 PUBLIC fmt spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY})
add_custom_command(TARGET shadps4 POST_BUILD add_custom_command(TARGET shadps4 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:SDL3-shared> $<TARGET_FILE:SDL3-shared>
$<TARGET_FILE_DIR:shadps4>) $<TARGET_FILE_DIR:shadps4>)
add_custom_command(TARGET shadps4 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${PROJECT_SOURCE_DIR}/third-party/winpthread/bin/libwinpthread-1.dll" $<TARGET_FILE_DIR:shadps4>)

View File

@ -0,0 +1,5 @@
#pragma once
constexpr int SCE_OK = 0;
constexpr int SCE_KERNEL_ERROR_ENOMEM = 0x8002000c;//Insufficient memory
constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016;//null or invalid states

View File

@ -0,0 +1,131 @@
#include "ThreadManagement.h"
#include "../ErrorCodes.h"
namespace HLE::Libs::LibKernel::ThreadManagement
{
thread_local PthreadInternal* g_pthread_self = nullptr;
PThreadCxt* g_pthread_cxt = nullptr;
void Pthread_Init_Self_MainThread() {
g_pthread_self = new PthreadInternal{};
scePthreadAttrInit(&g_pthread_self->attr);
g_pthread_self->pth = pthread_self();
g_pthread_self->name = "Main_Thread";
}
int scePthreadAttrInit(ScePthreadAttr* attr) {
*attr = new PthreadAttrInternal{};
int result = pthread_attr_init(&(*attr)->pth_attr);
(*attr)->affinity = 0x7f;
(*attr)->guard_size = 0x1000;
SceKernelSchedParam param{};
param.sched_priority = 700;
result = (result == 0 ? scePthreadAttrSetinheritsched(attr, 4) : result);
result = (result == 0 ? scePthreadAttrSetschedparam(attr, &param) : result);
result = (result == 0 ? scePthreadAttrSetschedpolicy(attr, SCHED_OTHER) : result);
result = (result == 0 ? scePthreadAttrSetdetachstate(attr, PTHREAD_CREATE_JOINABLE) : result);
switch (result) {
case 0: return SCE_OK;
case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM;
default: return SCE_KERNEL_ERROR_EINVAL;
}
}
int scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate) {
if (attr == nullptr || *attr == nullptr) {
return SCE_KERNEL_ERROR_EINVAL;
}
int pstate = PTHREAD_CREATE_JOINABLE;
switch (detachstate) {
case 0: pstate = PTHREAD_CREATE_JOINABLE; break;
case 1: pstate = PTHREAD_CREATE_DETACHED; break;
default:
__debugbreak(); //unknown state
}
int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate);
(*attr)->detached = (pstate == PTHREAD_CREATE_DETACHED);
if (result == 0) {
return SCE_OK;
}
return SCE_KERNEL_ERROR_EINVAL;
}
int scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched) {
if (attr == nullptr || *attr == nullptr) {
return SCE_KERNEL_ERROR_EINVAL;
}
int pinherit_sched = PTHREAD_INHERIT_SCHED;
switch (inheritSched) {
case 0: pinherit_sched = PTHREAD_EXPLICIT_SCHED; break;
case 4: pinherit_sched = PTHREAD_INHERIT_SCHED; break;
default: __debugbreak(); // unknown inheritSched
}
int result = pthread_attr_setinheritsched(&(*attr)->pth_attr, pinherit_sched);
if (result == 0) {
return SCE_OK;
}
return SCE_KERNEL_ERROR_EINVAL;
}
int scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param) {
if (param == nullptr || attr == nullptr || *attr == nullptr) {
return SCE_KERNEL_ERROR_EINVAL;
}
SceKernelSchedParam pparam{};
if (param->sched_priority <= 478) {
pparam.sched_priority = +2;
} else if (param->sched_priority >= 733) {
pparam.sched_priority = -2;
} else {
pparam.sched_priority = 0;
}
int result = pthread_attr_setschedparam(&(*attr)->pth_attr, &pparam);
if (result == 0) {
return SCE_OK;
}
return SCE_KERNEL_ERROR_EINVAL;
}
int scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy) {
if (attr == nullptr || *attr == nullptr) {
return SCE_KERNEL_ERROR_EINVAL;
}
if (policy!= SCHED_OTHER)
{
__debugbreak();//invest if policy is other and if winpthreadlibrary support it
}
(*attr)->policy = policy;
int result = pthread_attr_setschedpolicy(&(*attr)->pth_attr, policy);
if (result == 0) {
return SCE_OK;
}
return SCE_KERNEL_ERROR_EINVAL;
}
};

View File

@ -0,0 +1,42 @@
#pragma once
#define _TIMESPEC_DEFINED
#include <pthread.h>
#include <sched.h>
#include "../../../../types.h"
#include <string>
namespace HLE::Libs::LibKernel::ThreadManagement {
struct PthreadAttrInternal;
using SceKernelSchedParam = ::sched_param;
using ScePthreadAttr = PthreadAttrInternal*;
struct PthreadInternal {
u08 reserved[4096];
std::string name;
pthread_t pth;
ScePthreadAttr attr;
};
struct PthreadAttrInternal {
u08 reserved[64];
u64 affinity;
size_t guard_size;
int policy;
bool detached;
pthread_attr_t pth_attr;
};
class PThreadCxt {};
void Pthread_Init_Self_MainThread();
//HLE FUNCTIONS
int scePthreadAttrInit(ScePthreadAttr* attr);
int scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate);
int scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched);
int scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param);
int scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy);
} // namespace HLE::Libs::LibKernel::ThreadManagement

View File

@ -8,10 +8,7 @@ namespace HLE::Libs::LibC {
static void init_env() //every game/demo should probably static void init_env() //every game/demo should probably
{ {
for(;;) { //dummy no need atm
printf("__debugbreak\n");
}
//__debugbreak();//if we reach here it will be a great progress :D
} }
int __cxa_guard_acquire(u64* guard_object) int __cxa_guard_acquire(u64* guard_object)
@ -39,7 +36,11 @@ namespace HLE::Libs::LibC {
} }
static int atexit(void (*func)()) static int atexit(void (*func)())
{ return 0; {
for (;;) {
printf("we reached here too!\n");
}
return 0;
} }
void LibC_Register(SymbolsResolver* sym) void LibC_Register(SymbolsResolver* sym)

View File

@ -5,6 +5,7 @@
#include "../../Util/StringUtil.h" #include "../../Util/StringUtil.h"
#include "Util/aerolib.h" #include "Util/aerolib.h"
#include "Loader/SymbolsResolver.h" #include "Loader/SymbolsResolver.h"
#include "HLE/Kernel/ThreadManagement.h"
constexpr bool debug_loader = true; constexpr bool debug_loader = true;
@ -628,4 +629,27 @@ void Linker::Resolve(const std::string& name, int Symtype, Module* m, SymbolReco
__debugbreak();//oute edo mallon __debugbreak();//oute edo mallon
} }
}
using exit_func_t = void (*)();
using entry_func_t = void (*)(EntryParams* params, exit_func_t atexit_func);
static void ProgramExitFunc() {
printf("exit function called\n");
}
static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func) {
reinterpret_cast<entry_func_t>(addr)(params, exit_func);
}
void Linker::Execute()
{
HLE::Libs::LibKernel::ThreadManagement::Pthread_Init_Self_MainThread();
EntryParams p{};
p.argc = 1;
p.argv[0] = "eboot.bin"; //hmm should be ok?
run_main_entry(m_modules.at(0)->elf->GetElfEntry()+m_modules.at(0)->base_virtual_addr, &p, ProgramExitFunc);
} }

View File

@ -7,6 +7,12 @@
struct DynamicModuleInfo; struct DynamicModuleInfo;
class Linker; class Linker;
struct EntryParams {
int argc;
u32 padding;
const char* argv[3];
};
/*this struct keeps neccesary info about loaded modules.Main executeable is included too as well*/ /*this struct keeps neccesary info about loaded modules.Main executeable is included too as well*/
struct Module struct Module
{ {
@ -115,8 +121,9 @@ public:
SymbolsResolver* getHLESymbols() { return m_HLEsymbols; } SymbolsResolver* getHLESymbols() { return m_HLEsymbols; }
void Relocate(Module* m); void Relocate(Module* m);
void Resolve(const std::string& name, int Symtype, Module* m, SymbolRecord* return_info); void Resolve(const std::string& name, int Symtype, Module* m, SymbolRecord* return_info);
void Execute();
private: private:
const ModuleInfo* FindModule(const Module& m, const std::string& id); const ModuleInfo* FindModule(const Module& m, const std::string& id);
const LibraryInfo* FindLibrary(const Module& program, const std::string& id); const LibraryInfo* FindLibrary(const Module& program, const std::string& id);

View File

@ -33,17 +33,18 @@
// 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 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
linker->Execute();
#if 0 #if 0
// Setup SDL // Setup SDL
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0)

View File

@ -27,6 +27,8 @@ option(ZYDIS_BUILD_EXAMPLES "" OFF)
set(zydis_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zydis) set(zydis_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zydis)
add_subdirectory(${zydis_DIR}) add_subdirectory(${zydis_DIR})
#========== winpthreads ======================
add_subdirectory(winpthread)
#=================== IMGUI =================== #=================== IMGUI ===================
set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/imgui) set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/imgui)
@ -56,6 +58,6 @@ find_package(OpenGL REQUIRED)
target_link_libraries(IMGUI PUBLIC ${OPENGL_LIBRARIES}) target_link_libraries(IMGUI PUBLIC ${OPENGL_LIBRARIES})
target_link_libraries(IMGUI PUBLIC SDL3-shared ${CMAKE_DL_LIBS} Zydis) target_link_libraries(IMGUI PUBLIC SDL3-shared ${CMAKE_DL_LIBS} Zydis winpthread)

2
third-party/SDL vendored

@ -1 +1 @@
Subproject commit 125e7420ecd2b0d1847aef804f53e614fbc68253 Subproject commit 27556e098ecce54014ed1fc11c1e974ffdf4bc93

2
third-party/fmt vendored

@ -1 +1 @@
Subproject commit de0757b578244e0bf7ac50007fb5e25fcc899c7c Subproject commit 661b23edeb52d400cf5812e7330f14f05c072fab

2
third-party/imgui vendored

@ -1 +1 @@
Subproject commit 4fab72b40e2972f5d56fc884ed5797446238844e Subproject commit 52125a54a57a458e89bc61502010e964add3cdd5

@ -1 +1 @@
Subproject commit 5018ef9677521983bfedb127901284432d1a05a2 Subproject commit 4904822db8770d04444add00a9e155568d3e8bd1

2
third-party/spdlog vendored

@ -1 +1 @@
Subproject commit 5a6b6cafa8d4aee3e6d0dd16a2cae9169141c831 Subproject commit 76dfc7e7c0d3c69d3cdaa3399b63545235ccbb02

1
third-party/winpthread vendored Submodule

@ -0,0 +1 @@
Subproject commit 918de958b720c3ba7bc47f4988609c0109a0f75b

2
third-party/zydis vendored

@ -1 +1 @@
Subproject commit d4c37ae7a9db989495eb66636a65d8d4ff69eb35 Subproject commit a6d0c713b71b5009634868389f0ff551871273d6