mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
Follow-up to the keepalive work in the hybrid JIT safety change. The lock it adds closes the race between the idle canary and code memory being unmapped, which is the important half, but the activity check sits outside that lock and leaves a smaller gap behind. WaitForJITValidation drains by taking the mutex and dropping it again, so it only ever waits for a handler that has already acquired the lock. A handler that passed the activity check but has not reached the acquire yet is invisible to it. The boot path sets the VM active, cancels the timer and drains, all of which that handler misses, and then it carries on into BeginCodeWrite and flips protection across the whole arena while the EE thread is executing out of it. That is the same shape as the Devil May Cry crash, and the comment above ARMSX2JITWorkerBusy already describes the consequence as an instant instruction abort. Reading activity inside the lock leaves only two possible orderings and both are fine. Either the handler gets there first and the drain waits for it to restore the canary byte, or it gets there second, sees the VM is busy and returns without touching anything. The window is a few instructions against a twelve second timer, so nobody was going to hit this on purpose, but it costs two lines to remove.