FreeBSD 11 fopen opens the path with _open, and vn_open_vnode refuses a
directory only for FWRITE or O_TRUNC, so fopen of a directory in a read
mode succeeds; Linux hosts already open it. On Windows CreateFileW
without FILE_FLAG_BACKUP_SEMANTICS refused it with EACCES.
fopen now opens such a path as a libkernel directory descriptor, which
libkernel registers in libc when it loads, and fclose and freopen remove
it from libkernel's table. Reads on the stream fail with EISDIR and set
the error indicator, as on a Linux host and FreeBSD's tmpfs: the Windows
CRT fails them already but reports EINVAL. Writes fail with EBADF, and
fseek, ftell and ungetc work, as on any read-only stream.
The guest block's tail trim unmapped begin + bytes + UnitBytes - aligned bytes from the end of the block, which runs past the mapping it made. Trim begin + UnitBytes - aligned, as the sibling tests do.
After the argument checks, shadPS4 looks the request up and returns
REQUEST_NOT_FOUND for one that was never created or was deleted. The
library already tracks live requests for sceNpSetTimeout.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
On Windows a DLL is only loaded when the executable imports from it. The
thread test imported nothing from libkernel, so its load-time registration
never ran and _Tss_create threw. Comparing _Thrd_current with
scePthreadSelf imports libkernel and checks the forward.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RbLgECLQ2bpDM7oe2urGZK
Implement sceNpWebApi2AddWebTraceTag with the (int64_t request_id, const char* value) signature from shadPS4. Validates that value is not null, accepts any request id, and acts as a silent stub matching the other offline request functions.
A slice of a 2D array color target was refreshed one layer wide while its attachment view spans color.layers, so a layered draw refreshed only its first slice. Pass the attached layer count.
On a device that cannot sample two-sample depth, as lavapipe, the DB
depth copy case now also creates a two-sample surface and expects the
copy's sampling refusal, so that refusal is covered where it applies.
Devices that sample two-sample depth skip it.
Co-authored-by: simonbbby <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
ImportWatched kept a copy of every non-zero page of the range being imported, so that a page the
write watch reported during the import could be told from one that still held its bytes. The copy
had the range's footprint: a first import of a 0.5-3 GiB guest heap held that much host memory
while it ran.
The window now keeps a 64-bit digest per 4 KiB page (four xxHash64 lanes) and compares digests:
8 bytes per page, 1/512 of the range. Same decision for every page, same reads of guest memory.
CheckImportWindowFootprint imports a 64 MiB watched range and requires the heap held during the
import to stay under 1 MiB. It failed with "held 64 MiB" before this change.
The idle flush (VulkanDevice::StoreIdleResults) publishes the unit shadows over guest memory into
the host import and only submits the copies. publishUnits picks the units to store on the CPU,
and the slab -> import copy lands when the GPU runs it, so a guest store made between the two is
overwritten with the older shadow bytes. The memory-access hook waits through SyncThrough right
after its flush; the idle flush has no reader that waits.
FlushPending and PublishShadowsOnly now sync the recorder under the GPU mutex after an idle
publish that stored units. Other flush reasons are unchanged.
Test: agc_idle_publish_wait (a CPU store made after the idle flush returns survives; a label
flush's publish stays recorded).