Skip to content

Commit df19a82

Browse files
committed
The way to Unity, pt.3
1 parent 4fb2247 commit df19a82

File tree

17 files changed

+256
-50
lines changed

17 files changed

+256
-50
lines changed

src/common/ntapi.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ NtClose_t NtClose = nullptr;
99
NtSetInformationFile_t NtSetInformationFile = nullptr;
1010
NtCreateThread_t NtCreateThread = nullptr;
1111
NtTerminateThread_t NtTerminateThread = nullptr;
12+
NtQueueApcThreadEx_t NtQueueApcThreadEx = nullptr;
1213

1314
namespace Common::NtApi {
1415

@@ -21,6 +22,7 @@ void Initialize() {
2122
(NtSetInformationFile_t)GetProcAddress(nt_handle, "NtSetInformationFile");
2223
NtCreateThread = (NtCreateThread_t)GetProcAddress(nt_handle, "NtCreateThread");
2324
NtTerminateThread = (NtTerminateThread_t)GetProcAddress(nt_handle, "NtTerminateThread");
25+
NtQueueApcThreadEx = (NtQueueApcThreadEx_t)GetProcAddress(nt_handle, "NtQueueApcThreadEx");
2426
}
2527

2628
} // namespace Common::NtApi

src/common/ntapi.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,20 @@ typedef struct _TEB { /* win32/win64 */
509509
static_assert(offsetof(TEB, DeallocationStack) ==
510510
0x1478); /* The only member we care about at the moment */
511511

512+
typedef enum _QUEUE_USER_APC_FLAGS {
513+
QueueUserApcFlagsNone,
514+
QueueUserApcFlagsSpecialUserApc,
515+
QueueUserApcFlagsMaxValue
516+
} QUEUE_USER_APC_FLAGS;
517+
518+
typedef union _USER_APC_OPTION {
519+
ULONG_PTR UserApcFlags;
520+
HANDLE MemoryReserveHandle;
521+
} USER_APC_OPTION, *PUSER_APC_OPTION;
522+
523+
using PPS_APC_ROUTINE = void (*)(PVOID ApcArgument1, PVOID ApcArgument2, PVOID ApcArgument3,
524+
PCONTEXT Context);
525+
512526
typedef u64(__stdcall* NtClose_t)(HANDLE Handle);
513527

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

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

539+
typedef u64(__stdcall* NtQueueApcThreadEx_t)(HANDLE ThreadHandle,
540+
USER_APC_OPTION UserApcReserveHandle,
541+
PPS_APC_ROUTINE ApcRoutine, PVOID ApcArgument1,
542+
PVOID ApcArgument2, PVOID ApcArgument3);
543+
525544
extern NtClose_t NtClose;
526545
extern NtSetInformationFile_t NtSetInformationFile;
527546
extern NtCreateThread_t NtCreateThread;
528547
extern NtTerminateThread_t NtTerminateThread;
548+
extern NtQueueApcThreadEx_t NtQueueApcThreadEx;
529549

530550
namespace Common::NtApi {
531551
void Initialize();

src/core/libraries/ajm/ajm_context.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "common/assert.h"
55
#include "common/logging/log.h"
6+
#include "common/thread.h"
67
#include "core/libraries/ajm/ajm.h"
78
#include "core/libraries/ajm/ajm_at9.h"
89
#include "core/libraries/ajm/ajm_context.h"
@@ -53,6 +54,7 @@ s32 AjmContext::ModuleRegister(AjmCodecType type) {
5354
}
5455

5556
void AjmContext::WorkerThread(std::stop_token stop) {
57+
Common::SetCurrentThreadName("shadPS4:AjmWorker");
5658
while (!stop.stop_requested()) {
5759
auto batch = batch_queue.PopWait(stop);
5860
if (batch != nullptr) {

src/core/libraries/kernel/kernel.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ void KernelSignalRequest() {
4646
}
4747

4848
static void KernelServiceThread(std::stop_token stoken) {
49-
Common::SetCurrentThreadName("shadPS4:Kernel_ServiceThread");
49+
Common::SetCurrentThreadName("shadPS4:KernelServiceThread");
5050

5151
while (!stoken.stop_requested()) {
5252
HLE_TRACE;
@@ -255,6 +255,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
255255
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
256256
sceLibcHeapGetTraceInfo);
257257
LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write);
258+
LIB_FUNCTION("FN4gaPmuFV8", "libScePosix", 1, "libkernel", 1, 1, ps4__write);
258259
}
259260

260261
} // namespace Libraries::Kernel

src/core/libraries/kernel/memory.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,7 @@ int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) {
492492
return ORBIS_OK;
493493
}
494494
auto* memory = Core::Memory::Instance();
495-
memory->UnmapMemory(std::bit_cast<VAddr>(addr), len);
496-
return ORBIS_OK;
495+
return memory->UnmapMemory(std::bit_cast<VAddr>(addr), len);
497496
}
498497

499498
int PS4_SYSV_ABI posix_munmap(void* addr, size_t len) {

src/core/libraries/kernel/process.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, size_t arg
4545

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

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

6569
return handle;
6670
}
@@ -104,6 +108,9 @@ s32 PS4_SYSV_ABI sceKernelGetModuleInfoForUnwind(VAddr addr, int flags,
104108
LOG_INFO(Lib_Kernel, "called addr = {:#x}, flags = {:#x}", addr, flags);
105109
auto* linker = Common::Singleton<Core::Linker>::Instance();
106110
auto* module = linker->FindByAddress(addr);
111+
if (!module) {
112+
return ORBIS_KERNEL_ERROR_EFAULT;
113+
}
107114
const auto mod_info = module->GetModuleInfoEx();
108115

109116
// Fill in module info.

src/core/libraries/kernel/sync/semaphore.h

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,23 @@ class Semaphore {
8787
template <class Rep, class Period>
8888
bool try_acquire_for(const std::chrono::duration<Rep, Period>& rel_time) {
8989
#ifdef _WIN64
90-
const auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time);
91-
const u64 timeout_ms = static_cast<u64>(rel_time_ms.count());
90+
const auto start_time = std::chrono::high_resolution_clock::now();
91+
auto rel_time_ms = std::chrono::ceil<std::chrono::milliseconds>(rel_time);
9292

93-
if (timeout_ms == 0) {
94-
return false;
93+
while (rel_time_ms.count() > 0) {
94+
u64 timeout_ms = static_cast<u64>(rel_time_ms.count());
95+
u64 res = WaitForSingleObjectEx(sem, timeout_ms, true);
96+
if (res == WAIT_OBJECT_0) {
97+
return true;
98+
} else if (res == WAIT_IO_COMPLETION) {
99+
auto elapsed_time = std::chrono::high_resolution_clock::now() - start_time;
100+
rel_time_ms -= std::chrono::duration_cast<std::chrono::milliseconds>(elapsed_time);
101+
} else {
102+
return false;
103+
}
95104
}
96105

97-
return WaitForSingleObjectEx(sem, timeout_ms, true) == WAIT_OBJECT_0;
106+
return false;
98107
#elif defined(__APPLE__)
99108
const auto rel_time_ns = std::chrono::ceil<std::chrono::nanoseconds>(rel_time).count();
100109
const auto timeout = dispatch_time(DISPATCH_TIME_NOW, rel_time_ns);
@@ -107,19 +116,26 @@ class Semaphore {
107116
template <class Clock, class Duration>
108117
bool try_acquire_until(const std::chrono::time_point<Clock, Duration>& abs_time) {
109118
#ifdef _WIN64
110-
const auto now = Clock::now();
111-
if (now >= abs_time) {
119+
const auto start_time = Clock::now();
120+
if (start_time >= abs_time) {
112121
return false;
113122
}
114123

115-
const auto rel_time = std::chrono::ceil<std::chrono::milliseconds>(abs_time - now);
116-
const u64 timeout_ms = static_cast<u64>(rel_time.count());
117-
if (timeout_ms == 0) {
118-
return false;
124+
auto rel_time = std::chrono::ceil<std::chrono::milliseconds>(abs_time - start_time);
125+
while (rel_time.count() > 0) {
126+
u64 timeout_ms = static_cast<u64>(rel_time.count());
127+
u64 res = WaitForSingleObjectEx(sem, timeout_ms, true);
128+
if (res == WAIT_OBJECT_0) {
129+
return true;
130+
} else if (res == WAIT_IO_COMPLETION) {
131+
auto elapsed_time = Clock::now() - start_time;
132+
rel_time -= std::chrono::duration_cast<std::chrono::milliseconds>(elapsed_time);
133+
} else {
134+
return false;
135+
}
119136
}
120137

121-
u64 res = WaitForSingleObjectEx(sem, static_cast<u64>(timeout_ms), true);
122-
return res == WAIT_OBJECT_0;
138+
return false;
123139
#elif defined(__APPLE__)
124140
auto abs_s = std::chrono::time_point_cast<std::chrono::seconds>(abs_time);
125141
auto abs_ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(abs_time) -

src/core/libraries/kernel/threads/event_flag.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,33 @@ class EventFlagInternal {
132132
m_bits &= bits;
133133
}
134134

135+
void Cancel(u64 setPattern, int* numWaitThreads) {
136+
std::unique_lock lock{m_mutex};
137+
138+
while (m_status != Status::Set) {
139+
m_mutex.unlock();
140+
std::this_thread::sleep_for(std::chrono::microseconds(10));
141+
m_mutex.lock();
142+
}
143+
144+
if (numWaitThreads) {
145+
*numWaitThreads = m_waiting_threads;
146+
}
147+
148+
m_status = Status::Canceled;
149+
m_bits = setPattern;
150+
151+
m_cond_var.notify_all();
152+
153+
while (m_waiting_threads > 0) {
154+
m_mutex.unlock();
155+
std::this_thread::sleep_for(std::chrono::microseconds(10));
156+
m_mutex.lock();
157+
}
158+
159+
m_status = Status::Set;
160+
}
161+
135162
private:
136163
enum class Status { Set, Canceled, Deleted };
137164

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

233260
int PS4_SYSV_ABI sceKernelCancelEventFlag(OrbisKernelEventFlag ef, u64 setPattern,
234261
int* pNumWaitThreads) {
235-
LOG_ERROR(Kernel_Event, "(STUBBED) called");
262+
LOG_DEBUG(Kernel_Event, "called");
263+
ef->Cancel(setPattern, pNumWaitThreads);
236264
return ORBIS_OK;
237265
}
238266

src/core/libraries/kernel/threads/exception.cpp

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "core/libraries/libs.h"
88

99
#ifdef _WIN64
10+
#include "common/ntapi.h"
1011
#else
1112
#include <signal.h>
1213
#endif
@@ -64,6 +65,34 @@ void SigactionHandler(int signum, siginfo_t* inf, ucontext_t* raw_context) {
6465
handler(POSIX_SIGUSR1, &ctx);
6566
}
6667
}
68+
#else
69+
void ExceptionHandler(void* arg1, void* arg2, void* arg3, PCONTEXT context) {
70+
const char* thrName = (char*)arg1;
71+
LOG_INFO(Lib_Kernel, "Exception raised successfully on thread '{}'", thrName);
72+
const auto handler = Handlers[POSIX_SIGUSR1];
73+
if (handler) {
74+
auto ctx = Ucontext{};
75+
ctx.uc_mcontext.mc_r8 = context->R8;
76+
ctx.uc_mcontext.mc_r9 = context->R9;
77+
ctx.uc_mcontext.mc_r10 = context->R10;
78+
ctx.uc_mcontext.mc_r11 = context->R11;
79+
ctx.uc_mcontext.mc_r12 = context->R12;
80+
ctx.uc_mcontext.mc_r13 = context->R13;
81+
ctx.uc_mcontext.mc_r14 = context->R14;
82+
ctx.uc_mcontext.mc_r15 = context->R15;
83+
ctx.uc_mcontext.mc_rdi = context->Rdi;
84+
ctx.uc_mcontext.mc_rsi = context->Rsi;
85+
ctx.uc_mcontext.mc_rbp = context->Rbp;
86+
ctx.uc_mcontext.mc_rbx = context->Rbx;
87+
ctx.uc_mcontext.mc_rdx = context->Rdx;
88+
ctx.uc_mcontext.mc_rax = context->Rax;
89+
ctx.uc_mcontext.mc_rcx = context->Rcx;
90+
ctx.uc_mcontext.mc_rsp = context->Rsp;
91+
ctx.uc_mcontext.mc_fs = context->SegFs;
92+
ctx.uc_mcontext.mc_gs = context->SegGs;
93+
handler(POSIX_SIGUSR1, &ctx);
94+
}
95+
}
6796
#endif
6897

6998
int PS4_SYSV_ABI sceKernelInstallExceptionHandler(s32 signum, SceKernelExceptionHandler handler) {
@@ -73,9 +102,7 @@ int PS4_SYSV_ABI sceKernelInstallExceptionHandler(s32 signum, SceKernelException
73102
}
74103
ASSERT_MSG(!Handlers[POSIX_SIGUSR1], "Invalid parameters");
75104
Handlers[POSIX_SIGUSR1] = handler;
76-
#ifdef _WIN64
77-
UNREACHABLE_MSG("Missing exception implementation");
78-
#else
105+
#ifndef _WIN64
79106
struct sigaction act = {};
80107
act.sa_flags = SA_SIGINFO | SA_RESTART;
81108
act.sa_sigaction = reinterpret_cast<decltype(act.sa_sigaction)>(SigactionHandler);
@@ -91,9 +118,7 @@ int PS4_SYSV_ABI sceKernelRemoveExceptionHandler(s32 signum) {
91118
}
92119
ASSERT_MSG(Handlers[POSIX_SIGUSR1], "Invalid parameters");
93120
Handlers[POSIX_SIGUSR1] = nullptr;
94-
#ifdef _WIN64
95-
UNREACHABLE_MSG("Missing exception implementation");
96-
#else
121+
#ifndef _WIN64
97122
struct sigaction act = {};
98123
act.sa_flags = SA_SIGINFO | SA_RESTART;
99124
act.sa_sigaction = nullptr;
@@ -103,13 +128,18 @@ int PS4_SYSV_ABI sceKernelRemoveExceptionHandler(s32 signum) {
103128
}
104129

105130
int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
106-
LOG_ERROR(Lib_Kernel, "Raising exception");
131+
LOG_WARNING(Lib_Kernel, "Raising exception on thread '{}'", thread->name);
107132
ASSERT_MSG(signum == POSIX_SIGUSR1, "Attempting to raise non user defined signal!");
108-
#ifdef _WIN64
109-
UNREACHABLE_MSG("Missing exception implementation");
110-
#else
133+
#ifndef _WIN64
111134
pthread_t pthr = *reinterpret_cast<pthread_t*>(thread->native_thr.GetHandle());
112135
pthread_kill(pthr, SIGUSR2);
136+
#else
137+
USER_APC_OPTION option;
138+
option.UserApcFlags = QueueUserApcFlagsSpecialUserApc;
139+
140+
u64 res = NtQueueApcThreadEx(reinterpret_cast<HANDLE>(thread->native_thr.GetHandle()), option,
141+
ExceptionHandler, (void*)thread->name.c_str(), nullptr, nullptr);
142+
ASSERT(res == 0);
113143
#endif
114144
return 0;
115145
}

src/core/libraries/kernel/threads/pthread.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,8 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
540540
LIB_FUNCTION("onNY9Byn-W8", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_join));
541541
LIB_FUNCTION("P41kTWUS3EI", "libkernel", 1, "libkernel", 1, 1,
542542
ORBIS(posix_pthread_getschedparam));
543+
LIB_FUNCTION("oIRFTjoILbg", "libkernel", 1, "libkernel", 1, 1,
544+
ORBIS(posix_pthread_setschedparam));
543545
LIB_FUNCTION("How7B8Oet6k", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_getname_np));
544546
LIB_FUNCTION("3kg7rT0NQIs", "libkernel", 1, "libkernel", 1, 1, posix_pthread_exit);
545547
LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);

0 commit comments

Comments
 (0)