]>
Commit | Line | Data |
---|---|---|
7ad530bf EG |
1 | /* |
2 | * include/linux/sync.h | |
3 | * | |
4 | * Copyright (C) 2012 Google, Inc. | |
5 | * | |
6 | * This program is distributed in the hope that it will be useful, | |
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
9 | * GNU General Public License for more details. | |
10 | * | |
11 | */ | |
12 | ||
13 | #ifndef _LINUX_SYNC_H | |
14 | #define _LINUX_SYNC_H | |
15 | ||
16 | #include <linux/types.h> | |
17 | #ifdef __KERNEL__ | |
18 | ||
97a84843 | 19 | #include <linux/ktime.h> |
7ad530bf EG |
20 | #include <linux/list.h> |
21 | #include <linux/spinlock.h> | |
22 | #include <linux/wait.h> | |
23 | ||
24 | struct sync_timeline; | |
25 | struct sync_pt; | |
26 | struct sync_fence; | |
27 | ||
28 | /** | |
29 | * struct sync_timeline_ops - sync object implementation ops | |
30 | * @driver_name: name of the implentation | |
31 | * @dup: duplicate a sync_pt | |
32 | * @has_signaled: returns: | |
33 | * 1 if pt has signaled | |
34 | * 0 if pt has not signaled | |
35 | * <0 on error | |
36 | * @compare: returns: | |
37 | * 1 if b will signal before a | |
38 | * 0 if a and b will signal at the same time | |
39 | * -1 if a will signabl before b | |
40 | * @free_pt: called before sync_pt is freed | |
41 | * @release_obj: called before sync_timeline is freed | |
42 | */ | |
43 | struct sync_timeline_ops { | |
44 | const char *driver_name; | |
45 | ||
46 | /* required */ | |
47 | struct sync_pt *(*dup)(struct sync_pt *pt); | |
48 | ||
49 | /* required */ | |
50 | int (*has_signaled)(struct sync_pt *pt); | |
51 | ||
52 | /* required */ | |
53 | int (*compare)(struct sync_pt *a, struct sync_pt *b); | |
54 | ||
55 | /* optional */ | |
56 | void (*free_pt)(struct sync_pt *sync_pt); | |
57 | ||
58 | /* optional */ | |
59 | void (*release_obj)(struct sync_timeline *sync_timeline); | |
60 | }; | |
61 | ||
62 | /** | |
63 | * struct sync_timeline - sync object | |
64 | * @ops: ops that define the implementaiton of the sync_timeline | |
65 | * @name: name of the sync_timeline. Useful for debugging | |
66 | * @destoryed: set when sync_timeline is destroyed | |
67 | * @child_list_head: list of children sync_pts for this sync_timeline | |
68 | * @child_list_lock: lock protecting @child_list_head, destroyed, and | |
69 | * sync_pt.status | |
70 | * @active_list_head: list of active (unsignaled/errored) sync_pts | |
71 | */ | |
72 | struct sync_timeline { | |
73 | const struct sync_timeline_ops *ops; | |
74 | char name[32]; | |
75 | ||
76 | /* protected by child_list_lock */ | |
77 | bool destroyed; | |
78 | ||
79 | struct list_head child_list_head; | |
80 | spinlock_t child_list_lock; | |
81 | ||
82 | struct list_head active_list_head; | |
83 | spinlock_t active_list_lock; | |
84 | }; | |
85 | ||
86 | /** | |
87 | * struct sync_pt - sync point | |
88 | * @parent: sync_timeline to which this sync_pt belongs | |
89 | * @child_list: membership in sync_timeline.child_list_head | |
90 | * @active_list: membership in sync_timeline.active_list_head | |
91 | * @fence: sync_fence to which the sync_pt belongs | |
92 | * @pt_list: membership in sync_fence.pt_list_head | |
93 | * @status: 1: signaled, 0:active, <0: error | |
97a84843 EG |
94 | * @timestamp: time which sync_pt status transitioned from active to |
95 | * singaled or error. | |
7ad530bf EG |
96 | */ |
97 | struct sync_pt { | |
98 | struct sync_timeline *parent; | |
99 | struct list_head child_list; | |
100 | ||
101 | struct list_head active_list; | |
102 | ||
103 | struct sync_fence *fence; | |
104 | struct list_head pt_list; | |
105 | ||
106 | /* protected by parent->active_list_lock */ | |
107 | int status; | |
97a84843 EG |
108 | |
109 | ktime_t timestamp; | |
7ad530bf EG |
110 | }; |
111 | ||
112 | /** | |
113 | * struct sync_fence - sync fence | |
114 | * @file: file representing this fence | |
115 | * @name: name of sync_fence. Useful for debugging | |
116 | * @pt_list_head: list of sync_pts in ths fence. immutable once fence | |
117 | * is created | |
118 | * @waiter_list_head: list of asynchronous waiters on this fence | |
119 | * @waiter_list_lock: lock protecting @waiter_list_head and @status | |
120 | * @status: 1: signaled, 0:active, <0: error | |
121 | * | |
122 | * @wq: wait queue for fence signaling | |
123 | */ | |
124 | struct sync_fence { | |
125 | struct file *file; | |
126 | char name[32]; | |
127 | ||
128 | /* this list is immutable once the fence is created */ | |
129 | struct list_head pt_list_head; | |
130 | ||
131 | struct list_head waiter_list_head; | |
132 | spinlock_t waiter_list_lock; /* also protects status */ | |
133 | int status; | |
134 | ||
135 | wait_queue_head_t wq; | |
136 | }; | |
137 | ||
138 | /** | |
139 | * struct sync_fence_waiter - metadata for asynchronous waiter on a fence | |
140 | * @waiter_list: membership in sync_fence.waiter_list_head | |
141 | * @callback: function pointer to call when fence signals | |
142 | * @callback_data: pointer to pass to @callback | |
143 | */ | |
144 | struct sync_fence_waiter { | |
145 | struct list_head waiter_list; | |
146 | ||
147 | void (*callback)(struct sync_fence *fence, void *data); | |
148 | void *callback_data; | |
149 | }; | |
150 | ||
151 | /* | |
152 | * API for sync_timeline implementers | |
153 | */ | |
154 | ||
155 | /** | |
156 | * sync_timeline_create() - creates a sync object | |
157 | * @ops: specifies the implemention ops for the object | |
158 | * @size: size to allocate for this obj | |
159 | * @name: sync_timeline name | |
160 | * | |
161 | * Creates a new sync_timeline which will use the implemetation specified by | |
162 | * @ops. @size bytes will be allocated allowing for implemntation specific | |
163 | * data to be kept after the generic sync_timeline stuct. | |
164 | */ | |
165 | struct sync_timeline *sync_timeline_create(const struct sync_timeline_ops *ops, | |
166 | int size, const char *name); | |
167 | ||
168 | /** | |
169 | * sync_timeline_destory() - destorys a sync object | |
170 | * @obj: sync_timeline to destroy | |
171 | * | |
172 | * A sync implemntation should call this when the @obj is going away | |
173 | * (i.e. module unload.) @obj won't actually be freed until all its childern | |
174 | * sync_pts are freed. | |
175 | */ | |
176 | void sync_timeline_destroy(struct sync_timeline *obj); | |
177 | ||
178 | /** | |
179 | * sync_timeline_signal() - signal a status change on a sync_timeline | |
180 | * @obj: sync_timeline to signal | |
181 | * | |
182 | * A sync implemntation should call this any time one of it's sync_pts | |
183 | * has signaled or has an error condition. | |
184 | */ | |
185 | void sync_timeline_signal(struct sync_timeline *obj); | |
186 | ||
187 | /** | |
188 | * sync_pt_create() - creates a sync pt | |
189 | * @parent: sync_pt's parent sync_timeline | |
190 | * @size: size to allocate for this pt | |
191 | * | |
192 | * Creates a new sync_pt as a chiled of @parent. @size bytes will be | |
193 | * allocated allowing for implemntation specific data to be kept after | |
194 | * the generic sync_timeline struct. | |
195 | */ | |
196 | struct sync_pt *sync_pt_create(struct sync_timeline *parent, int size); | |
197 | ||
198 | /** | |
199 | * sync_pt_free() - frees a sync pt | |
200 | * @pt: sync_pt to free | |
201 | * | |
202 | * This should only be called on sync_pts which have been created but | |
203 | * not added to a fence. | |
204 | */ | |
205 | void sync_pt_free(struct sync_pt *pt); | |
206 | ||
207 | /** | |
208 | * sync_fence_create() - creates a sync fence | |
209 | * @name: name of fence to create | |
210 | * @pt: sync_pt to add to the fence | |
211 | * | |
212 | * Creates a fence containg @pt. Once this is called, the fence takes | |
213 | * ownership of @pt. | |
214 | */ | |
215 | struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt); | |
216 | ||
217 | /* | |
218 | * API for sync_fence consumers | |
219 | */ | |
220 | ||
221 | /** | |
222 | * sync_fence_merge() - merge two fences | |
223 | * @name: name of new fence | |
224 | * @a: fence a | |
225 | * @b: fence b | |
226 | * | |
227 | * Creates a new fence which contains copies of all the sync_pts in both | |
228 | * @a and @b. @a and @b remain valid, independent fences. | |
229 | */ | |
230 | struct sync_fence *sync_fence_merge(const char *name, | |
231 | struct sync_fence *a, struct sync_fence *b); | |
232 | ||
233 | /** | |
234 | * sync_fence_fdget() - get a fence from an fd | |
235 | * @fd: fd referencing a fence | |
236 | * | |
237 | * Ensures @fd references a valid fence, increments the refcount of the backing | |
238 | * file, and returns the fence. | |
239 | */ | |
240 | struct sync_fence *sync_fence_fdget(int fd); | |
241 | ||
242 | /** | |
243 | * sync_fence_put() - puts a refernnce of a sync fence | |
244 | * @fence: fence to put | |
245 | * | |
246 | * Puts a reference on @fence. If this is the last reference, the fence and | |
247 | * all it's sync_pts will be freed | |
248 | */ | |
249 | void sync_fence_put(struct sync_fence *fence); | |
250 | ||
251 | /** | |
252 | * sync_fence_install() - installs a fence into a file descriptor | |
253 | * @fence: fence to instal | |
254 | * @fd: file descriptor in which to install the fence | |
255 | * | |
256 | * Installs @fence into @fd. @fd's should be acquired through get_unused_fd(). | |
257 | */ | |
258 | void sync_fence_install(struct sync_fence *fence, int fd); | |
259 | ||
260 | /** | |
261 | * sync_fence_wait_async() - registers and async wait on the fence | |
262 | * @fence: fence to wait on | |
263 | * @callback: callback | |
264 | * @callback_data data to pass to the callback | |
265 | * | |
266 | * Returns 1 if @fence has already signaled. | |
267 | * | |
268 | * Registers a callback to be called when @fence signals or has an error | |
269 | */ | |
270 | int sync_fence_wait_async(struct sync_fence *fence, | |
271 | void (*callback)(struct sync_fence *, void *data), | |
272 | void *callback_data); | |
273 | ||
274 | /** | |
275 | * sync_fence_wait() - wait on fence | |
276 | * @fence: fence to wait on | |
277 | * @tiemout: timeout in ms | |
278 | * | |
279 | * Wait for @fence to be signaled or have an error. Waits indefintly | |
280 | * if @timeout = 0 | |
281 | */ | |
282 | int sync_fence_wait(struct sync_fence *fence, long timeout); | |
283 | ||
284 | /* useful for sync driver's debug print handlers */ | |
285 | const char *sync_status_str(int status); | |
286 | ||
287 | #endif /* __KERNEL__ */ | |
288 | ||
289 | /** | |
290 | * struct sync_merge_data - data passed to merge ioctl | |
291 | * @fd2: file descriptor of second fence | |
292 | * @name: name of new fence | |
293 | * @fence: returns the fd of the new fence to userspace | |
294 | */ | |
295 | struct sync_merge_data { | |
296 | __s32 fd2; /* fd of second fence */ | |
297 | char name[32]; /* name of new fence */ | |
298 | __s32 fence; /* fd on newly created fence */ | |
299 | }; | |
300 | ||
301 | #define SYNC_IOC_MAGIC '>' | |
302 | ||
303 | /** | |
304 | * DOC: SYNC_IOC_WAIT - wait for a fence to signal | |
305 | * | |
306 | * pass timeout in milliseconds. | |
307 | */ | |
308 | #define SYNC_IOC_WAIT _IOW(SYNC_IOC_MAGIC, 0, __u32) | |
309 | ||
310 | /** | |
311 | * DOC: SYNC_IOC_MERGE - merge two fences | |
312 | * | |
313 | * Takes a struct sync_merge_data. Creates a new fence containing copies of | |
314 | * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the | |
315 | * new fence's fd in sync_merge_data.fence | |
316 | */ | |
317 | #define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 1, struct sync_merge_data) | |
318 | ||
319 | #endif /* _LINUX_SYNC_H */ |