Skip to content

Commit a0d2390

Browse files
committed
Fix iOS startup event waits
1 parent aa40213 commit a0d2390

4 files changed

Lines changed: 155 additions & 9 deletions

File tree

UnleashedRecomp/kernel/imports.cpp

Lines changed: 145 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,68 @@
1717
#include <ntstatus.h>
1818
#endif
1919

20+
static std::atomic<uint32_t> g_keSetEventGeneration;
21+
22+
static void NotifyWaitForMultipleObjects()
23+
{
24+
++g_keSetEventGeneration;
25+
g_keSetEventGeneration.notify_all();
26+
}
27+
28+
#ifdef UNLEASHED_RECOMP_IOS
29+
static uint32_t GetGuestLinkRegisterForLog()
30+
{
31+
#ifndef PPC_CONFIG_SKIP_LR
32+
if (auto* ctx = GetPPCContext())
33+
return uint32_t(ctx->lr);
34+
#endif
35+
36+
return 0;
37+
}
38+
39+
static bool ShouldLogKernelWait(uint32_t count)
40+
{
41+
return count <= 128 || (count % 512) == 0;
42+
}
43+
44+
static const char* GetDispatcherTypeName(uint32_t type)
45+
{
46+
switch (type)
47+
{
48+
case 0:
49+
return "NotificationEvent";
50+
case 1:
51+
return "SynchronizationEvent";
52+
case 5:
53+
return "Semaphore";
54+
default:
55+
return "Unknown";
56+
}
57+
}
58+
59+
static void LogKernelWait(const char* name, uint32_t object, uint32_t timeout, int64_t rawTimeout, uint32_t type, uint32_t signalState, uint32_t extra = 0)
60+
{
61+
static std::atomic<uint32_t> s_waitLogCount;
62+
const uint32_t count = ++s_waitLogCount;
63+
if (!ShouldLogKernelWait(count))
64+
return;
65+
66+
LOGFN("iOS wait #{} {} object=0x{:08X} type={}({}) signal={} timeout={} rawTimeout={} extra={} lr=0x{:08X} thread=0x{:08X}",
67+
count,
68+
name,
69+
object,
70+
GetDispatcherTypeName(type),
71+
type,
72+
signalState,
73+
timeout,
74+
rawTimeout,
75+
extra,
76+
GetGuestLinkRegisterForLog(),
77+
GuestThread::GetCurrentThreadId());
78+
}
79+
80+
#endif
81+
2082
struct Event final : KernelObject, HostObject<XKEVENT>
2183
{
2284
bool manualReset;
@@ -83,6 +145,8 @@ struct Event final : KernelObject, HostObject<XKEVENT>
83145
else
84146
signaled.notify_one();
85147

148+
NotifyWaitForMultipleObjects();
149+
86150
return TRUE;
87151
}
88152

@@ -93,8 +157,6 @@ struct Event final : KernelObject, HostObject<XKEVENT>
93157
}
94158
};
95159

96-
static std::atomic<uint32_t> g_keSetEventGeneration;
97-
98160
struct Semaphore final : KernelObject, HostObject<XKSEMAPHORE>
99161
{
100162
std::atomic<uint32_t> count;
@@ -158,9 +220,44 @@ struct Semaphore final : KernelObject, HostObject<XKSEMAPHORE>
158220

159221
count += releaseCount;
160222
count.notify_all();
223+
NotifyWaitForMultipleObjects();
161224
}
162225
};
163226

227+
#ifdef UNLEASHED_RECOMP_IOS
228+
static const char* GetKernelObjectName(KernelObject* object)
229+
{
230+
if (dynamic_cast<Event*>(object) != nullptr)
231+
return "Event";
232+
233+
if (dynamic_cast<Semaphore*>(object) != nullptr)
234+
return "Semaphore";
235+
236+
if (dynamic_cast<GuestThreadHandle*>(object) != nullptr)
237+
return "GuestThread";
238+
239+
return "KernelObject";
240+
}
241+
242+
static void LogKernelHandleWait(const char* name, uint32_t handle, KernelObject* object, uint32_t timeout, int64_t rawTimeout)
243+
{
244+
static std::atomic<uint32_t> s_handleWaitLogCount;
245+
const uint32_t count = ++s_handleWaitLogCount;
246+
if (!ShouldLogKernelWait(count))
247+
return;
248+
249+
LOGFN("iOS handle wait #{} {} handle=0x{:08X} objectType={} timeout={} rawTimeout={} lr=0x{:08X} thread=0x{:08X}",
250+
count,
251+
name,
252+
handle,
253+
GetKernelObjectName(object),
254+
timeout,
255+
rawTimeout,
256+
GetGuestLinkRegisterForLog(),
257+
GuestThread::GetCurrentThreadId());
258+
}
259+
#endif
260+
164261
inline void CloseKernelObject(XDISPATCHER_HEADER& header)
165262
{
166263
if (header.WaitListHead.Flink != OBJECT_SIGNATURE)
@@ -408,7 +505,11 @@ uint32_t NtWaitForSingleObjectEx(uint32_t Handle, uint32_t WaitMode, uint32_t Al
408505

409506
if (IsKernelObject(Handle))
410507
{
411-
return GetKernelObject(Handle)->Wait(timeout);
508+
auto* object = GetKernelObject(Handle);
509+
#ifdef UNLEASHED_RECOMP_IOS
510+
LogKernelHandleWait("NtWaitForSingleObjectEx", Handle, object, timeout, Timeout ? int64_t(*Timeout) : 0);
511+
#endif
512+
return object->Wait(timeout);
412513
}
413514
else
414515
{
@@ -569,6 +670,21 @@ uint32_t KeDelayExecutionThread(uint32_t WaitMode, bool Alertable, be<int64_t>*
569670

570671
uint32_t timeout = GuestTimeoutToMilliseconds(Timeout);
571672

673+
#ifdef UNLEASHED_RECOMP_IOS
674+
static std::atomic<uint32_t> s_delayLogCount;
675+
const uint32_t delayLogCount = ++s_delayLogCount;
676+
if (timeout == INFINITE || timeout >= 500 || delayLogCount <= 16)
677+
{
678+
LOGFN("iOS delay #{} timeout={} rawTimeout={} waitMode={} lr=0x{:08X} thread=0x{:08X}",
679+
delayLogCount,
680+
timeout,
681+
Timeout ? int64_t(*Timeout) : 0,
682+
WaitMode,
683+
GetGuestLinkRegisterForLog(),
684+
GuestThread::GetCurrentThreadId());
685+
}
686+
#endif
687+
572688
#ifdef _WIN32
573689
Sleep(timeout);
574690
#else
@@ -999,9 +1115,6 @@ bool KeSetEvent(XKEVENT* pEvent, uint32_t Increment, bool Wait)
9991115
{
10001116
bool result = QueryKernelObject<Event>(*pEvent)->Set();
10011117

1002-
++g_keSetEventGeneration;
1003-
g_keSetEventGeneration.notify_all();
1004-
10051118
return result;
10061119
}
10071120

@@ -1015,6 +1128,15 @@ uint32_t KeWaitForSingleObject(XDISPATCHER_HEADER* Object, uint32_t WaitReason,
10151128
const uint32_t timeout = GuestTimeoutToMilliseconds(Timeout);
10161129
assert(timeout == INFINITE);
10171130

1131+
#ifdef UNLEASHED_RECOMP_IOS
1132+
LogKernelWait("KeWaitForSingleObject",
1133+
g_memory.MapVirtual(Object),
1134+
timeout,
1135+
Timeout ? int64_t(*Timeout) : 0,
1136+
Object->Type,
1137+
Object->SignalState);
1138+
#endif
1139+
10181140
switch (Object->Type)
10191141
{
10201142
case 0:
@@ -1325,6 +1447,12 @@ uint32_t NtResumeThread(GuestThreadHandle* hThread, uint32_t* suspendCount)
13251447

13261448
uint32_t NtSetEvent(Event* handle, uint32_t* previousState)
13271449
{
1450+
#ifdef UNLEASHED_RECOMP_IOS
1451+
LOGFN("iOS NtSetEvent handle=0x{:08X} lr=0x{:08X} thread=0x{:08X}",
1452+
g_memory.MapVirtual(handle),
1453+
GetGuestLinkRegisterForLog(),
1454+
GuestThread::GetCurrentThreadId());
1455+
#endif
13281456
handle->Set();
13291457
return 0;
13301458
}
@@ -1506,6 +1634,17 @@ uint32_t KeWaitForMultipleObjects(uint32_t Count, xpointer<XDISPATCHER_HEADER>*
15061634
const uint64_t timeout = GuestTimeoutToMilliseconds(Timeout);
15071635
assert(timeout == INFINITE);
15081636

1637+
#ifdef UNLEASHED_RECOMP_IOS
1638+
auto* firstObject = Count > 0 ? Objects[0].get() : nullptr;
1639+
LogKernelWait("KeWaitForMultipleObjects",
1640+
firstObject != nullptr ? g_memory.MapVirtual(firstObject) : 0,
1641+
uint32_t(timeout),
1642+
Timeout ? int64_t(*Timeout) : 0,
1643+
firstObject != nullptr ? firstObject->Type : 0xFFFFFFFF,
1644+
firstObject != nullptr ? uint32_t(firstObject->SignalState) : 0,
1645+
(Count << 8) | WaitType);
1646+
#endif
1647+
15091648
if (WaitType == 0) // Wait all
15101649
{
15111650
for (size_t i = 0; i < Count; i++)

UnleashedRecomp/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ int main(int argc, char *argv[])
214214
os::logger::Init();
215215

216216
#ifdef UNLEASHED_RECOMP_IOS
217-
LOGN("iOS startup build: install-validation-v3");
217+
LOGN("iOS startup build: sync-wait-fix-v4");
218218
#endif
219219

220220
PreloadContext preloadContext;

UnleashedRecomp/misc_impl.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "stdafx.h"
22
#include <kernel/function.h>
33
#include <kernel/xdm.h>
4+
#include <os/logger.h>
45

56
uint32_t QueryPerformanceCounterImpl(LARGE_INTEGER* lpPerformanceCount)
67
{
@@ -46,7 +47,13 @@ GUEST_FUNCTION_HOOK(sub_831CCAA0, memset);
4647
#ifdef _WIN32
4748
GUEST_FUNCTION_HOOK(sub_82BD4CA8, OutputDebugStringA);
4849
#else
49-
GUEST_FUNCTION_STUB(sub_82BD4CA8);
50+
static void OutputDebugStringAImpl(const char* message)
51+
{
52+
if (message != nullptr && message[0] != '\0')
53+
LOGFN("Guest debug: {}", message);
54+
}
55+
56+
GUEST_FUNCTION_HOOK(sub_82BD4CA8, OutputDebugStringAImpl);
5057
#endif
5158

5259
GUEST_FUNCTION_HOOK(sub_82BD4AC8, QueryPerformanceCounterImpl);

UnleashedRecomp/res/version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
VERSION_MILESTONE=""
22
VERSION_MAJOR=1
33
VERSION_MINOR=0
4-
VERSION_REVISION=5
4+
VERSION_REVISION=6

0 commit comments

Comments
 (0)