Skip to content

The way to Unity, pt.3 #1681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/common/ntapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ NtClose_t NtClose = nullptr;
NtSetInformationFile_t NtSetInformationFile = nullptr;
NtCreateThread_t NtCreateThread = nullptr;
NtTerminateThread_t NtTerminateThread = nullptr;
NtQueueApcThreadEx_t NtQueueApcThreadEx = nullptr;

namespace Common::NtApi {

Expand All @@ -21,6 +22,7 @@ void Initialize() {
(NtSetInformationFile_t)GetProcAddress(nt_handle, "NtSetInformationFile");
NtCreateThread = (NtCreateThread_t)GetProcAddress(nt_handle, "NtCreateThread");
NtTerminateThread = (NtTerminateThread_t)GetProcAddress(nt_handle, "NtTerminateThread");
NtQueueApcThreadEx = (NtQueueApcThreadEx_t)GetProcAddress(nt_handle, "NtQueueApcThreadEx");
}

} // namespace Common::NtApi
Expand Down
20 changes: 20 additions & 0 deletions src/common/ntapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,20 @@ typedef struct _TEB { /* win32/win64 */
static_assert(offsetof(TEB, DeallocationStack) ==
0x1478); /* The only member we care about at the moment */

typedef enum _QUEUE_USER_APC_FLAGS {
QueueUserApcFlagsNone,
QueueUserApcFlagsSpecialUserApc,
QueueUserApcFlagsMaxValue
} QUEUE_USER_APC_FLAGS;

typedef union _USER_APC_OPTION {
ULONG_PTR UserApcFlags;
HANDLE MemoryReserveHandle;
} USER_APC_OPTION, *PUSER_APC_OPTION;

using PPS_APC_ROUTINE = void (*)(PVOID ApcArgument1, PVOID ApcArgument2, PVOID ApcArgument3,
PCONTEXT Context);

typedef u64(__stdcall* NtClose_t)(HANDLE Handle);

typedef u64(__stdcall* NtSetInformationFile_t)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock,
Expand All @@ -522,10 +536,16 @@ typedef u64(__stdcall* NtCreateThread_t)(PHANDLE ThreadHandle, ACCESS_MASK Desir

typedef u64(__stdcall* NtTerminateThread_t)(HANDLE ThreadHandle, u64 ExitStatus);

typedef u64(__stdcall* NtQueueApcThreadEx_t)(HANDLE ThreadHandle,
USER_APC_OPTION UserApcReserveHandle,
PPS_APC_ROUTINE ApcRoutine, PVOID ApcArgument1,
PVOID ApcArgument2, PVOID ApcArgument3);

extern NtClose_t NtClose;
extern NtSetInformationFile_t NtSetInformationFile;
extern NtCreateThread_t NtCreateThread;
extern NtTerminateThread_t NtTerminateThread;
extern NtQueueApcThreadEx_t NtQueueApcThreadEx;

namespace Common::NtApi {
void Initialize();
Expand Down
2 changes: 2 additions & 0 deletions src/core/libraries/ajm/ajm_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "common/assert.h"
#include "common/logging/log.h"
#include "common/thread.h"
#include "core/libraries/ajm/ajm.h"
#include "core/libraries/ajm/ajm_at9.h"
#include "core/libraries/ajm/ajm_context.h"
Expand Down Expand Up @@ -53,6 +54,7 @@ s32 AjmContext::ModuleRegister(AjmCodecType type) {
}

void AjmContext::WorkerThread(std::stop_token stop) {
Common::SetCurrentThreadName("shadPS4:AjmWorker");
while (!stop.stop_requested()) {
auto batch = batch_queue.PopWait(stop);
if (batch != nullptr) {
Expand Down
3 changes: 2 additions & 1 deletion src/core/libraries/kernel/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void KernelSignalRequest() {
}

static void KernelServiceThread(std::stop_token stoken) {
Common::SetCurrentThreadName("shadPS4:Kernel_ServiceThread");
Common::SetCurrentThreadName("shadPS4:KernelServiceThread");

while (!stoken.stop_requested()) {
HLE_TRACE;
Expand Down Expand Up @@ -255,6 +255,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
sceLibcHeapGetTraceInfo);
LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write);
LIB_FUNCTION("FN4gaPmuFV8", "libScePosix", 1, "libkernel", 1, 1, ps4__write);
}

} // namespace Libraries::Kernel
3 changes: 1 addition & 2 deletions src/core/libraries/kernel/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -492,8 +492,7 @@ int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) {
return ORBIS_OK;
}
auto* memory = Core::Memory::Instance();
memory->UnmapMemory(std::bit_cast<VAddr>(addr), len);
return ORBIS_OK;
return memory->UnmapMemory(std::bit_cast<VAddr>(addr), len);
}

int PS4_SYSV_ABI posix_munmap(void* addr, size_t len) {
Expand Down
15 changes: 11 additions & 4 deletions src/core/libraries/kernel/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, size_t arg

// Load PRX module and relocate any modules that import it.
auto* linker = Common::Singleton<Core::Linker>::Instance();
u32 handle = linker->LoadModule(path, true);
if (handle == -1) {
return ORBIS_KERNEL_ERROR_EINVAL;
u32 handle = linker->FindByName(path);
if (handle != -1) {
return handle;
}
handle = linker->LoadModule(path, true);
auto* module = linker->GetModule(handle);
linker->RelocateAnyImports(module);

Expand All @@ -60,7 +61,10 @@ s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, size_t arg
// Retrieve and verify proc param according to libkernel.
u64* param = module->GetProcParam<u64*>();
ASSERT_MSG(!param || param[0] >= 0x18, "Invalid module param size: {}", param[0]);
module->Start(args, argp, param);
s32 ret = module->Start(args, argp, param);
if (pRes) {
*pRes = ret;
}

return handle;
}
Expand Down Expand Up @@ -104,6 +108,9 @@ s32 PS4_SYSV_ABI sceKernelGetModuleInfoForUnwind(VAddr addr, int flags,
LOG_INFO(Lib_Kernel, "called addr = {:#x}, flags = {:#x}", addr, flags);
auto* linker = Common::Singleton<Core::Linker>::Instance();
auto* module = linker->FindByAddress(addr);
if (!module) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
const auto mod_info = module->GetModuleInfoEx();

// Fill in module info.
Expand Down
42 changes: 29 additions & 13 deletions src/core/libraries/kernel/sync/semaphore.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,23 @@ class Semaphore {
template <class Rep, class Period>
bool try_acquire_for(const std::chrono::duration<Rep, Period>& rel_time) {
#ifdef _WIN64
const auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time);
const u64 timeout_ms = static_cast<u64>(rel_time_ms.count());
const auto start_time = std::chrono::high_resolution_clock::now();
auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time);

if (timeout_ms == 0) {
return false;
while (rel_time_ms.count() > 0) {
u64 timeout_ms = static_cast<u64>(rel_time_ms.count());
u64 res = WaitForSingleObjectEx(sem, timeout_ms, true);
if (res == WAIT_OBJECT_0) {
return true;
} else if (res == WAIT_IO_COMPLETION) {
auto elapsed_time = std::chrono::high_resolution_clock::now() - start_time;
rel_time_ms -= std::chrono::duration_cast<std::chrono::milliseconds>(elapsed_time);
} else {
return false;
}
}

return WaitForSingleObjectEx(sem, timeout_ms, true) == WAIT_OBJECT_0;
return false;
#elif defined(__APPLE__)
const auto rel_time_ns = std::chrono::ceil<std::chrono::nanoseconds>(rel_time).count();
const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns);
Expand All @@ -107,19 +116,26 @@ class Semaphore {
template <class Clock, class Duration>
bool try_acquire_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
#ifdef _WIN64
const auto now = Clock::now();
if (now >= abs_time) {
const auto start_time = Clock::now();
if (start_time >= abs_time) {
return false;
}

const auto rel_time = std::chrono::ceil<std::chrono::milliseconds>(abs_time - now);
const u64 timeout_ms = static_cast<u64>(rel_time.count());
if (timeout_ms == 0) {
return false;
auto rel_time = std::chrono::ceil<std::chrono::milliseconds>(abs_time - start_time);
while (rel_time.count() > 0) {
u64 timeout_ms = static_cast<u64>(rel_time.count());
u64 res = WaitForSingleObjectEx(sem, timeout_ms, true);
if (res == WAIT_OBJECT_0) {
return true;
} else if (res == WAIT_IO_COMPLETION) {
auto elapsed_time = Clock::now() - start_time;
rel_time -= std::chrono::duration_cast<std::chrono::milliseconds>(elapsed_time);
} else {
return false;
}
}

u64 res = WaitForSingleObjectEx(sem, static_cast<u64>(timeout_ms), true);
return res == WAIT_OBJECT_0;
return false;
#elif defined(__APPLE__)
auto abs_s = std::chrono::time_point_cast<std::chrono::seconds>(abs_time);
auto abs_ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(abs_time) -
Expand Down
30 changes: 29 additions & 1 deletion src/core/libraries/kernel/threads/event_flag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,33 @@ class EventFlagInternal {
m_bits &= bits;
}

void Cancel(u64 setPattern, int* numWaitThreads) {
std::unique_lock lock{m_mutex};

while (m_status != Status::Set) {
m_mutex.unlock();
std::this_thread::sleep_for(std::chrono::microseconds(10));
m_mutex.lock();
}

if (numWaitThreads) {
*numWaitThreads = m_waiting_threads;
}

m_status = Status::Canceled;
m_bits = setPattern;

m_cond_var.notify_all();

while (m_waiting_threads > 0) {
m_mutex.unlock();
std::this_thread::sleep_for(std::chrono::microseconds(10));
m_mutex.lock();
}

m_status = Status::Set;
}

private:
enum class Status { Set, Canceled, Deleted };

Expand Down Expand Up @@ -232,7 +259,8 @@ int PS4_SYSV_ABI sceKernelClearEventFlag(OrbisKernelEventFlag ef, u64 bitPattern

int PS4_SYSV_ABI sceKernelCancelEventFlag(OrbisKernelEventFlag ef, u64 setPattern,
int* pNumWaitThreads) {
LOG_ERROR(Kernel_Event, "(STUBBED) called");
LOG_DEBUG(Kernel_Event, "called");
ef->Cancel(setPattern, pNumWaitThreads);
return ORBIS_OK;
}

Expand Down
50 changes: 40 additions & 10 deletions src/core/libraries/kernel/threads/exception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "core/libraries/libs.h"

#ifdef _WIN64
#include "common/ntapi.h"
#else
#include <signal.h>
#endif
Expand Down Expand Up @@ -64,6 +65,34 @@ void SigactionHandler(int signum, siginfo_t* inf, ucontext_t* raw_context) {
handler(POSIX_SIGUSR1, &ctx);
}
}
#else
void ExceptionHandler(void* arg1, void* arg2, void* arg3, PCONTEXT context) {
const char* thrName = (char*)arg1;
LOG_INFO(Lib_Kernel, "Exception raised successfully on thread '{}'", thrName);
const auto handler = Handlers[POSIX_SIGUSR1];
if (handler) {
auto ctx = Ucontext{};
ctx.uc_mcontext.mc_r8 = context->R8;
ctx.uc_mcontext.mc_r9 = context->R9;
ctx.uc_mcontext.mc_r10 = context->R10;
ctx.uc_mcontext.mc_r11 = context->R11;
ctx.uc_mcontext.mc_r12 = context->R12;
ctx.uc_mcontext.mc_r13 = context->R13;
ctx.uc_mcontext.mc_r14 = context->R14;
ctx.uc_mcontext.mc_r15 = context->R15;
ctx.uc_mcontext.mc_rdi = context->Rdi;
ctx.uc_mcontext.mc_rsi = context->Rsi;
ctx.uc_mcontext.mc_rbp = context->Rbp;
ctx.uc_mcontext.mc_rbx = context->Rbx;
ctx.uc_mcontext.mc_rdx = context->Rdx;
ctx.uc_mcontext.mc_rax = context->Rax;
ctx.uc_mcontext.mc_rcx = context->Rcx;
ctx.uc_mcontext.mc_rsp = context->Rsp;
ctx.uc_mcontext.mc_fs = context->SegFs;
ctx.uc_mcontext.mc_gs = context->SegGs;
handler(POSIX_SIGUSR1, &ctx);
}
}
#endif

int PS4_SYSV_ABI sceKernelInstallExceptionHandler(s32 signum, SceKernelExceptionHandler handler) {
Expand All @@ -73,9 +102,7 @@ int PS4_SYSV_ABI sceKernelInstallExceptionHandler(s32 signum, SceKernelException
}
ASSERT_MSG(!Handlers[POSIX_SIGUSR1], "Invalid parameters");
Handlers[POSIX_SIGUSR1] = handler;
#ifdef _WIN64
UNREACHABLE_MSG("Missing exception implementation");
#else
#ifndef _WIN64
struct sigaction act = {};
act.sa_flags = SA_SIGINFO | SA_RESTART;
act.sa_sigaction = reinterpret_cast<decltype(act.sa_sigaction)>(SigactionHandler);
Expand All @@ -91,9 +118,7 @@ int PS4_SYSV_ABI sceKernelRemoveExceptionHandler(s32 signum) {
}
ASSERT_MSG(Handlers[POSIX_SIGUSR1], "Invalid parameters");
Handlers[POSIX_SIGUSR1] = nullptr;
#ifdef _WIN64
UNREACHABLE_MSG("Missing exception implementation");
#else
#ifndef _WIN64
struct sigaction act = {};
act.sa_flags = SA_SIGINFO | SA_RESTART;
act.sa_sigaction = nullptr;
Expand All @@ -103,13 +128,18 @@ int PS4_SYSV_ABI sceKernelRemoveExceptionHandler(s32 signum) {
}

int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
LOG_ERROR(Lib_Kernel, "Raising exception");
LOG_WARNING(Lib_Kernel, "Raising exception on thread '{}'", thread->name);
ASSERT_MSG(signum == POSIX_SIGUSR1, "Attempting to raise non user defined signal!");
#ifdef _WIN64
UNREACHABLE_MSG("Missing exception implementation");
#else
#ifndef _WIN64
pthread_t pthr = *reinterpret_cast<pthread_t*>(thread->native_thr.GetHandle());
pthread_kill(pthr, SIGUSR2);
#else
USER_APC_OPTION option;
option.UserApcFlags = QueueUserApcFlagsSpecialUserApc;

u64 res = NtQueueApcThreadEx(reinterpret_cast<HANDLE>(thread->native_thr.GetHandle()), option,
ExceptionHandler, (void*)thread->name.c_str(), nullptr, nullptr);
ASSERT(res == 0);
#endif
return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions src/core/libraries/kernel/threads/pthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,8 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("onNY9Byn-W8", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_join));
LIB_FUNCTION("P41kTWUS3EI", "libkernel", 1, "libkernel", 1, 1,
ORBIS(posix_pthread_getschedparam));
LIB_FUNCTION("oIRFTjoILbg", "libkernel", 1, "libkernel", 1, 1,
ORBIS(posix_pthread_setschedparam));
LIB_FUNCTION("How7B8Oet6k", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_getname_np));
LIB_FUNCTION("3kg7rT0NQIs", "libkernel", 1, "libkernel", 1, 1, posix_pthread_exit);
LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
Expand Down
Loading
Loading