Op 28-09-12 14:42, Maarten Lankhorst schreef:
A fence can be attached to a buffer which is being filled or consumed by hw, to allow userspace to pass the buffer without waiting to another device. For example, userspace can call page_flip ioctl to display the next frame of graphics after kicking the GPU but while the GPU is still rendering. The display device sharing the buffer with the GPU would attach a callback to get notified when the GPU's rendering-complete IRQ fires, to update the scan-out address of the display, without having to wake up userspace.
A fence is transient, one-shot deal. It is allocated and attached to one or more dma-buf's. When the one that attached it is done, with the pending operation, it can signal the fence:
- fence_signal()
To have a rough approximation whether a fence is fired, call:
- fence_is_signaled()
The dma-buf-mgr handles tracking, and waiting on, the fences associated with a dma-buf.
The one pending on the fence can add an async callback:
- fence_add_callback()
The callback can optionally be cancelled with:
- fence_remove_callback()
To wait synchronously, optionally with a timeout:
- fence_wait()
- fence_wait_timeout()
...
Implementing this makes the locking feel weird, instead of abusing fence->event_queue.lock I think it would make sense to remove this part entirely, and have a simply linked list plus a pointer to a spinlock.
enable_signaling should be called with this spinlock held. This way, the enable_signaling callback would be easier to implement and doesn't have to double check for races as much in there.
Also __fence_signal should be exported which would be the same as fence_signal, but without taking the spinlock as separate step, so it can be called with the spinlock held.
How do you feel about these proposed changes?
~Maarten