huangcm
2025-08-14 5d6606c55520a76d5bb8297d83fd9bbf967e5244
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Motivation:
 
In complicated DMA pipelines such as graphics (multimedia, camera, gpu, display)
a consumer of a buffer needs to know when the producer has finished producing
it.  Likewise the producer needs to know when the consumer is finished with the
buffer so it can reuse it.  A particular buffer may be consumed by multiple
consumers which will retain the buffer for different amounts of time.  In
addition, a consumer may consume multiple buffers atomically.
The sync framework adds an API which allows synchronization between the
producers and consumers in a generic way while also allowing platforms which
have shared hardware synchronization primitives to exploit them.
 
Goals:
   * provide a generic API for expressing synchronization dependencies
   * allow drivers to exploit hardware synchronization between hardware
     blocks
   * provide a userspace API that allows a compositor to manage
     dependencies.
   * provide rich telemetry data to allow debugging slowdowns and stalls of
      the graphics pipeline.
 
Objects:
   * sync_timeline
   * sync_pt
   * sync_fence
 
sync_timeline:
 
A sync_timeline is an abstract monotonically increasing counter. In general,
each driver/hardware block context will have one of these.  They can be backed
by the appropriate hardware or rely on the generic sw_sync implementation.
Timelines are only ever created through their specific implementations
(i.e. sw_sync.)
 
sync_pt:
 
A sync_pt is an abstract value which marks a point on a sync_timeline. Sync_pts
have a single timeline parent.  They have 3 states: active, signaled, and error.
They start in active state and transition, once, to either signaled (when the
timeline counter advances beyond the sync_pt’s value) or error state.
 
sync_fence:
 
Sync_fences are the primary primitives used by drivers to coordinate
synchronization of their buffers.  They are a collection of sync_pts which may
or may not have the same timeline parent.  A sync_pt can only exist in one fence
and the fence's list of sync_pts is immutable once created.  Fences can be
waited on synchronously or asynchronously.  Two fences can also be merged to
create a third fence containing a copy of the two fences’ sync_pts.  Fences are
backed by file descriptors to allow userspace to coordinate the display pipeline
dependencies.
 
Use:
 
A driver implementing sync support should have a work submission function which:
     * takes a fence argument specifying when to begin work
     * asynchronously queues that work to kick off when the fence is signaled
     * returns a fence to indicate when its work will be done.
     * signals the returned fence once the work is completed.
 
Consider an imaginary display driver that has the following API:
/*
 * assumes buf is ready to be displayed.
 * blocks until the buffer is on screen.
 */
    void display_buffer(struct dma_buf *buf);
 
The new API will become:
/*
 * will display buf when fence is signaled.
 * returns immediately with a fence that will signal when buf
 * is no longer displayed.
 */
struct sync_fence* display_buffer(struct dma_buf *buf,
                                 struct sync_fence *fence);