With Atomic FIFO fetch, read() can fetch a packet header while PUT is exactly
at header + 4. The FIFO_EMPTY branch left m_fifo_pos on arg0 with
m_command_reg = base, but read_unsafe() pre-increments both, so the resume
skipped arg0, took the word after the packet as an argument and decoded the
next header one word late. For 1-argument packets m_command_inc was also left
from the previous multi-argument packet. Since fetch_u32() only waits when PUT
is exactly at the address, the resume read unpublished memory.
Rewind to the header and recompute the increment, using the same convention
as restore_state().
On a PS3 the funcStat callback of AutoSave/AutoLoad runs about 200 ms
after the call when the save exists, and about 80 ms after it for a new
save. On RPCS3 it ran after 2-11 ms.
A game creates a singleton lazily, without a lock, both from its main
thread and from the funcStat of its AutoLoad2, which runs on a thread
with a 64 KB stack. The constructor calls a function with a 66 KB stack
frame. On a PS3 the main thread has built the singleton by the time
funcStat runs; on RPCS3 funcStat wins the race, runs the constructor and
overflows the stack.
Wait in savedata_op, before funcStat, until 200 ms (80 ms for a new
save) after the call start. Both values are the lowest measured on a PS3.
The wait counts from the call start like the AutoSave/AutoLoad duration,
so the total time of a call that ends with funcFile is unchanged.
Fixes#19949
A list callback may set focusPosition to NEWDATA while hiding the new data
entry (listSet->newData == NULL), e.g. when the game's save slot limit is
reached. Load and Save lists now focus the list head in that case instead
of failing with CELL_SAVEDATA_ERROR_PARAM; Delete lists keep the error.
Delete lists also reject a listSet->newData entry with
CELL_SAVEDATA_ERROR_PARAM, and their initial focusPosition is DIRNAME.
The load confirmation of the new data entry uses its title.
Verified against a PSL1GHT test on real hardware (22 cases).
Fixes#19163
vm::writer_lock requires the caller to set cpu_flag::wait on a PPU
thread, otherwise the PPU thread is terminated with "vm::writer_lock is
being used without cpu_flag::wait set by the caller!" once it holds the
passive lock. Several HLE functions allocate or free guest memory
without it:
- cellFont: cellFontOpenFontFile (and cellFontOpenFontset through it),
cellFontCloseFont
- cellFontFT: cellFontInitLibraryFreeTypeWithRevision (and
cellFontInitLibraryFreeType through it)
- cellGcmSys: cellGcmMapLocalMemory
- cellGifDec: cellGifDecOpen, cellGifDecClose
- cellSail: cellSailPlayerCreateDescriptor
- sys_heap: _sys_heap_malloc, _sys_heap_memalign, _sys_heap_free
- sys_ppu_thread_: sys_initialize_tls, sys_ppu_thread_exit
- sys_spu_: sys_spu_image_import, sys_spu_image_close
Same pattern as _sys_malloc/_sys_free and #19963.