turnip: Make KGSL wait IOCTLs interrupt-safe
We were testing Skyline Emulator with Turnip's KGSL backend and noticed that it would run into assert(errno == ETIME)
inside tu_WaitForFences
. Skyline is built around using signals for its core scheduling functionality so threads that were waiting on the fence would be interrupted resulting in early returns on release builds of Turnip and assertions on debug builds.
It turned out that the bug was due to ioctl
being used for tu_WaitForFences
and tu_GetFenceStatus
which didn't correctly handle EAGAIN
/EINTR
and would end up returning early or asserting instead. The reason that safe_ioctl
wasn't used for timer calls is because KGSL doesn't use absolute timestamps for its timeout which would cause any restarted syscalls to wait for the full duration of the timeout with no consideration for the amount of time that had already been waited.
This has been fixed by extrapolating the wait IOCTL into its own function which automatically adjusts the timeout to account for any time already waited for any restarted calls and is now called into from tu_WaitForFences
and tu_GetFenceStatus
.