New Kernel Modesetting Locking
Now that my kernel modesetting lockig rework has landed in Dave’s drm-next tree and is gearing up for inclusion into 3.9 I’ve figured it’s time to also post my little intro here:
The aim of this locking rework is that ioctls which a compositor should be might call for every frame (set_cursor, page_flip, addfb, rmfb and getfb/create_handle) should not be able to block on kms background activities like output detection. And since each EDID read takes about 25ms (in the best case), that always means we’ll drop at least one frame.
The solution is to add per-crtc locking for these ioctls, and restrict background activities to only use the global lock. Change-the-world type of events (modeset, dpms, …) need to grab all locks. Two tricky parts arose in the conversion:
- A lot of current code assumes that a kms fb object can't disappear while holding the global lock, since the current code serializes fb destruction with it. Hence proper lifetime management using the already created refcounting for fbs need to be instantiated for all ioctls and interfaces/users.
- The rmfb ioctl removes the to-be-deleted fb from all active users. But unconditionally taking the global kms lock to do so introduces an unacceptable potential stall point. And obviously changing the userspace abi isn't on the table, either. Hence this conversion opportunistically checks whether the rmfb ioctl holds the very last reference, which guarantees that the fb isn't in active use on any crtc or plane (thanks to the conversion to the new lifetime rules using proper refcounting). Only if this is not the case will the code go through the slowpath and grab all modeset locks. Sane compositors will never hit this path and so avoid the stall, but userspace relying on these semantics will also not break.
All these cases are exercised by the newly subtests for the i-g-t kms_flip, tested on a machine where a full detect cycle takes around 100 ms. It works, and no frames are dropped any more with these patches applied. kms_flip also contains a special case to exercise the above-describe rmfb slowpath.
For anyone curious about some of the details of this rework or ARM drm driver writers needing to port out-of-tree stuff I suggest to just read through the patches - I’ve tried really hard to properly document things in commmit messages and note about the implications of the new design.
The downside of this all is that we can now enable some really paranoid inter-frame jitter checks and vblank counter timestamp checks in the kms_flip testcase. After all, no frames should be dropped any longer. But it turns out that a lot of the different platforms still have small issues here and there with races and other inconsistencies like completing a page flip immediately right after a modeset.
So there’s still plenty of work to do until we have perfect pageflip support. And there’s also a few funny issues like racing gpu hangs against pageflips, client crashes against pageflips or trying to flip overlays and cursor on the same vblank as the underlying framebuffer. Ville Syrjälä and other guys at Intel and elsewhere are working on this. So stay tuned.