mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-22 10:56:20 +08:00
[Kernel] Implement clock_getres and the POSIX pthread_once alias
clock_getres (smIj7eqzZE8) was missing entirely. It reports 100ns, which is the resolution clock_gettime here actually delivers via DateTimeOffset.UtcNow, rather than claiming the 1ns a caller might otherwise rely on. A null res pointer is accepted per POSIX. pthread_once (Z4QosVuAsA0) needed no new logic: libKernel exports the same routine under two NIDs and only scePthreadOnce (14bOACANTBo) was registered. Shipped middleware links the plain name. Both are imported by DOOM + DOOM II (PPSA21444): clock_getres blocked party.prx from initialising, and pthread_once is used by libcohtml, libPlayFabMultiplayer, party.prx and the eboot. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2327,6 +2327,37 @@ public static partial class KernelMemoryCompatExports
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||
}
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "smIj7eqzZE8",
|
||||
ExportName = "clock_getres",
|
||||
Target = Generation.Gen4 | Generation.Gen5,
|
||||
LibraryName = "libKernel")]
|
||||
public static int ClockGetres(CpuContext ctx)
|
||||
{
|
||||
var timespecAddress = ctx[CpuRegister.Rsi];
|
||||
|
||||
// POSIX allows a null resolution pointer: the call then only validates
|
||||
// the clock id, which every id a title passes here does.
|
||||
if (timespecAddress == 0)
|
||||
{
|
||||
ctx[CpuRegister.Rax] = 0;
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||
}
|
||||
|
||||
// clock_gettime above is backed by DateTimeOffset.UtcNow, whose tick is
|
||||
// 100 ns, so that is the honest resolution to report rather than the 1 ns
|
||||
// a caller might otherwise assume it can rely on.
|
||||
const ulong ResolutionNanoseconds = 100;
|
||||
if (!ctx.TryWriteUInt64(timespecAddress, 0) ||
|
||||
!ctx.TryWriteUInt64(timespecAddress + sizeof(long), ResolutionNanoseconds))
|
||||
{
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
ctx[CpuRegister.Rax] = 0;
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||
}
|
||||
|
||||
[SysAbiExport(
|
||||
Nid = "vNe1w4diLCs",
|
||||
ExportName = "__tls_get_addr",
|
||||
|
||||
@@ -578,6 +578,19 @@ public static class KernelPthreadCompatExports
|
||||
return SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_OK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The POSIX-named alias of <see cref="PthreadOnce"/>. libKernel exports the
|
||||
/// same routine under two NIDs, and shipped middleware links the plain name:
|
||||
/// DOOM's libcohtml, PlayFab and party modules all import this one rather
|
||||
/// than scePthreadOnce.
|
||||
/// </summary>
|
||||
[SysAbiExport(
|
||||
Nid = "Z4QosVuAsA0",
|
||||
ExportName = "pthread_once",
|
||||
Target = Generation.Gen4 | Generation.Gen5,
|
||||
LibraryName = "libKernel")]
|
||||
public static int PthreadOncePOSIX(CpuContext ctx) => PthreadOnce(ctx);
|
||||
|
||||
private static int PthreadMutexInitCore(CpuContext ctx, ulong mutexAddress, ulong attrAddress)
|
||||
{
|
||||
if (mutexAddress == 0)
|
||||
|
||||
Reference in New Issue
Block a user