[Kernel] Share the sync-on-address wait and wake cores

Co-authored-by: Sekai <140012992+igettingit@users.noreply.github.com>
This commit is contained in:
ParantezTech 2026-10-06 13:44:49 +03:00
parent 6d62f8599f
commit fbefcaeb34
1 changed files with 97 additions and 15 deletions

View File

@ -215,14 +215,29 @@ public static class KernelSyncOnAddressCompatExports
{
var address = ctx[CpuRegister.Rdi];
var requested = unchecked((int)ctx[CpuRegister.Rsi]);
return Wake(ctx, address, requested, usePosixResult: false);
}
private static int Wake(
CpuContext ctx,
ulong address,
int requested,
bool usePosixResult)
{
if (address == 0 || (address & 3) != 0 || requested < 0)
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT,
usePosixResult);
}
if (requested == 0)
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_OK,
usePosixResult);
}
List<SyncWaiter>? selected = null;
@ -294,7 +309,10 @@ public static class KernelSyncOnAddressCompatExports
GuestThreadExecution.CurrentGuestThreadHandle,
Environment.CurrentManagedThreadId);
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_OK,
usePosixResult);
}
private static void CaptureCallStack(
@ -339,15 +357,15 @@ public static class KernelSyncOnAddressCompatExports
private static int Wait(CpuContext ctx, bool is64Bit)
{
var address = ctx[CpuRegister.Rdi];
var expected = is64Bit
? ctx[CpuRegister.Rsi]
: unchecked((uint)ctx[CpuRegister.Rsi]);
var alignmentMask = is64Bit ? 7UL : 3UL;
if (address == 0 || (address & alignmentMask) != 0)
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT);
}
var expected = is64Bit
? ctx[CpuRegister.Rsi]
: unchecked((uint)ctx[CpuRegister.Rsi]);
if (!TryReadValue(ctx, address, is64Bit, out var current))
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
@ -369,28 +387,92 @@ public static class KernelSyncOnAddressCompatExports
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
}
if (timeoutMicroseconds == 0)
{
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_TIMED_OUT);
}
timeout = TimeSpan.FromTicks((long)timeoutMicroseconds * 10L);
deadline = GuestThreadExecution.ComputeDeadlineTimestamp(timeout.Value);
}
var waiter = new SyncWaiter(ctx, address, expected, is64Bit);
return WaitCore(
ctx,
is64Bit,
address,
expected,
timeout,
deadline,
usePosixResult: false,
reason: is64Bit
? "sceKernelSyncOnAddressWait64"
: "sceKernelSyncOnAddressWait32");
}
private static int WaitCore(
CpuContext ctx,
bool is64Bit,
ulong address,
ulong expected,
TimeSpan? timeout,
long deadline,
bool usePosixResult,
string reason)
{
var alignmentMask = is64Bit ? 7UL : 3UL;
if (address == 0 || (address & alignmentMask) != 0)
{
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_INVALID_ARGUMENT,
usePosixResult);
}
if (!TryReadValue(ctx, address, is64Bit, out var current))
{
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT,
usePosixResult);
}
if (current != expected)
{
KernelSyncOnAddressProfile.RecordImmediate(address);
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_OK,
usePosixResult);
}
if (timeout == TimeSpan.Zero)
{
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_TIMED_OUT,
usePosixResult);
}
var waiter = new SyncWaiter(
ctx,
address,
expected,
is64Bit,
usePosixResult,
deadline);
Register(address, waiter);
if (!TryReadValue(ctx, address, is64Bit, out current))
{
Unregister(waiter);
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT);
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT,
usePosixResult);
}
if (current != expected || waiter.TryWake())
{
Unregister(waiter);
KernelSyncOnAddressProfile.RecordImmediate(address);
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
return CompleteResult(
ctx,
(int)OrbisGen2Result.ORBIS_GEN2_OK,
usePosixResult);
}
var returnRip = 0UL;
@ -418,7 +500,7 @@ public static class KernelSyncOnAddressCompatExports
if (GuestThreadExecution.RequestCurrentThreadBlock(
ctx,
is64Bit ? "sceKernelSyncOnAddressWait64" : "sceKernelSyncOnAddressWait32",
reason,
waiter.WakeKey,
waiter,
deadline))