mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-12 18:45:33 -10:00
The polling thread and the frontend shared one adapter list under an OSFastMutex, which the frontend took on every poll, and the HID attach callbacks queued events by swapping the list head out and back in. That swap pair is not atomic as a whole: two callbacks at once (the HID stack calls them from more than one thread) can each take the list and put theirs back over the other's, losing an attach or a detach. A lost detach leaves the pad registered for good. Each thread now keeps its own list and hands adapters across through the lock-free stacks of mpsc_stack.h: attach callbacks -> hid_events -> polling thread polling thread -> hid_new -> frontend: adapters to set up frontend -> hid_retired -> polling thread: to free An adapter's state is a retro_atomic_int_t, and each value is moved on by one thread only, so no two ever write it from the same state. The read completion runs the packet handler before it says READY, since READY is when the polling thread may start winding the adapter down; it used to say READY first. The frontend deregisters and deinitialises a pad as it retires the adapter, the polling thread frees the adapter, and at shutdown the polling thread tears down what is left, as before. No lock remains, and the frontend's poll no longer takes one. samples/input/wiiu_hid_threads runs the driver against stand-ins for Cafe OS on pthreads: two threads attach and detach devices while the frontend polls and an "IOS" thread completes the reads, and every pad must be registered, fed, deregistered and deinitialised in order, on the right threads, with nothing left at shutdown. Its negative build loses the reads in flight at shutdown and must fail. Against the old driver (32-bit PowerPC under qemu) it fails: a few hundred pads of detached devices are never torn down.