With the queue-0 draw pipeline on, the default since #1202, the packet
loop hands every label-writing packet to the pipeline and skips the rest
of the loop. A RELEASE_MEM that completes a reserved EOP flip
(sceVideoOutSubmitEopFlip, #5539) is a label write, so its label landed
but the flip branch never ran: the reservation was consumed and the flip
never presented. video_out_flip_eop and video_out_flip_eop_main failed
and video_out_flip_eop_aftergpu timed out.
Keep packets that carry a reserved flip out of the pipeline. They take
the normal path, which drains the pipeline before the flip as it does
for flip packets.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An FDE whose address range is 0 describes no instructions, and an
unwinder never matches a pc in it. The exception-table reader rejected
it with "inconsistent FDE function range", which stopped the
conversion of Limbo (CUSA01664): one of its 17328 FDEs covers 0 bytes
at 0x47dd0, where the next record starts. Such a record is now read
and left out of the function list.
A fifth ABI deferral mode, abi_deferred_undecodable_state. A vertex
shader whose specials route it through geometry (VGT_SHADER_STAGES_EN
0x2030), which registration leaves alone, is resolved through
ResolveGraphicsStagesAbi with the context and primitive registers that
sceAgcCreatePrimState passes for it. DecodeShaderStages refuses its
VGT_GS_OUT_PRIM_TYPE of 1.
The call must not throw and must log the stage once with the decode's
reason, and a second call must neither prepare nor log it again. A draw
that routes the stage through the vertex path then prepares it at its
first use without reporting it as missing a registration artifact.
A lea of a table base recorded only the exact base address as address-taken, so import slots after it in a function-pointer or vtable table were treated as dead. unused-filter=2 then stripped those NIDs and indexed calls hit unbound slots. The base walk now marks every consecutive import slot or relocated pointer starting at the base.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
An elevated Windows process can bypass the parent directory DACL while holding SeBackupPrivilege or SeRestorePrivilege. Remove both privileges before DeniedParentWatch so the test exercises the denied-open path reliably.
Co-Authored-By: Adam Franke <[email protected]>
A title's graphics pipeline ABI call decodes the stage routing and programs
from the registered state and the call's own context and primitive
registers. When that decode refused the state, the exception left the
call and ended the title, although the draws that later use the stages
decode their own state.
The decode failure now defers every stage of the call the same way a
stage whose preparation fails is deferred: each is prepared when a draw
uses it.
Two more detached driver threads were never stopped: the helpers of the
parallel compare pool, started at the first large compare, and the
pipeline library's job thread, started at the first link-time optimized
pipeline. A process that exited right after starting them killed them
inside the first waits that take winpthreads' global condition-variable
lock, as with the preparation workers.
The driver's shutdown now stops both and joins them, after the device
is reset. A compare in progress finishes first and later compares run
on the caller. The library worker finishes the job it is running, the
jobs still queued are dropped and counted off their device, and later
pipelines are not optimized in the background.
Closing a preparation pool waited until its queue was empty, but its
detached workers stayed parked on the queue until ExitProcess killed
them. A pool first used shortly before shutdown still had workers
starting at exit, inside the first waits that take winpthreads' global
condition-variable lock, which the next DLL-detach destructor of an
unwaited static condition variable then waits for forever.
The workers are now joinable and leave once their pool is closed and
idle, and Close joins them, so after the driver's shutdown no
preparation worker is running or starting.
CloseRegistrationPreparation took RegistrationPreparePool::Instance(),
which creates the pool and starts its detached workers (half the
hardware threads, at least two) when nothing was queued for preparation
yet. In a process that prepared nothing in the background, the driver's
shutdown started the workers only to close the pool, and the process
exited while they were still starting. Their first waits take the
global lock of winpthreads' statically initialized condition variables;
ExitProcess killed them holding it, and the destructor of the next
static condition variable that was never waited on spun on it forever
at DLL detach (~DeviceUseGate in ~Driver, or one of libkernel's). On
GitHub's Windows runners agc_interpolant_mapping hung that way in 15 of
60 rounds of eight test runs.
Shutdown now closes only the pools that exist, and a pool first used
after it starts no workers, so later preparations run on the caller as
they did on a closed pool.
kevent threw for any descriptor that is not a guest socket. The read end
of a pipe now gets the descriptor knote, following FreeBSD 11's
filt_piperead: data is the number of buffered bytes and EV_EOF is set
once the write end is closed. GuestSockets::Ready falls back to the new
PipeReadState for a descriptor that is not a socket, and WaitAny waits on
the pipe with ppoll on Linux or in 1 ms WSAPoll slices on Windows, only
when the queue holds a pipe. On Windows the equeue waker now starts
Winsock itself, since a queue can wait on a pipe before any socket exists.
guest_host_standard_error and exception_runtime fork children that end in
SIGABRT on purpose. When kernel.core_pattern pipes cores to a handler, as
Ubuntu's apport and systemd-coredump do, the kernel starts it for every
dumpable crash even with RLIMIT_CORE at 0. apport takes about 1.1 s per
crash here, so guest_host_standard_error spent 2.3 s waiting and timed out
at its 10 s limit under parallel ctest load. Marking those children
non-dumpable on Linux skips the handler: 2.29 s to 0.01 s and
1.17 s to 0.01 s, with the same SIGABRT and message checks.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
INPUT_MAPPING.md names the actions and says that omitted actions keep their built-in bindings, but not what those bindings are. The table is read from InputMapping in core/libs/prx/libScePad/include/InputMapping.hpp.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Dinkumware's setw returns a manipulator holding a function pointer and the
width, which the caller applies to the stream; the function stores the
width in the stream's ios_base. The export returns that pair in RAX:RDX and
the function writes ios_base::width, leaving flags and precision alone.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The deadline was built as seconds plus nanoseconds, a nanosecond duration,
and converted implicitly to a system_clock time point. Where system_clock
counts microseconds, as on macOS, that conversion is lossy and does not
compile, so libc did not build there.
The seconds now stay in the clock's unit and only the nanoseconds are
rounded up to it, so the wait never ends before the requested time. With
a nanosecond system_clock nothing changes. Converting the nanosecond sum
instead would compile but overflow above 2^63 nanoseconds, which the
clock range check above allows on macOS: a 10^10 second deadline then
wraps into the past and the wait times out at once.
A deadline of 10^10 seconds does not fit a nanosecond count but fits the
host clock where system_clock counts microseconds, as on macOS. There the
wait must block until it is woken; where the clock cannot hold the
deadline, _Cnd_timedwait must throw the overflow error as for any other
deadline past the clock's range.
The host heap's VK_EXT_memory_budget report lowered a set
APS5_HOST_IMPORT_MIB of 6400 MiB to 4480 MiB on Resident Evil Village
(PPSA01556), where 6400 MiB runs without a vkAllocateMemory failure, and
85,047 imports were refused. A set APS5_HOST_IMPORT_MIB is now never
lowered by the report, and the default is held to the report only once
an import's vkAllocateMemory has failed. The failure ceiling is
unchanged. The first time the report would lower the budget, a [gpu]
host import budget line prints the heap's reported budget and usage and
the live imports, and the refusal line names where its budget came from.
PixelFailure wrote a 128x128 payload, exactly the 64 KiB a default Linux
pipe holds. Once the consumer read the 54-byte header, the whole payload
fit in the pipe, so the write could finish before the reader closed and
the expected EPIPE never came. agc_frame_dump_io failed in 147 of 300 runs
on Linux. A 512x512 payload exceeds the default pipe capacity on Linux and
macOS, so the write always reaches the closed reader.
Co-Authored-By: Claude Opus 5.5 <[email protected]>