4 * Copyright (C) 2012 Google, Inc.
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/debugfs.h>
18 #include <linux/export.h>
19 #include <linux/file.h>
21 #include <linux/kernel.h>
22 #include <linux/poll.h>
23 #include <linux/sched.h>
24 #include <linux/seq_file.h>
25 #include <linux/slab.h>
26 #include <linux/uaccess.h>
27 #include <linux/anon_inodes.h>
31 #define CREATE_TRACE_POINTS
32 #include "trace/sync.h"
34 static const struct fence_ops android_fence_ops
;
35 static const struct file_operations sync_file_fops
;
37 struct sync_timeline
*sync_timeline_create(const struct sync_timeline_ops
*ops
,
38 int size
, const char *name
)
40 struct sync_timeline
*obj
;
42 if (size
< sizeof(struct sync_timeline
))
45 obj
= kzalloc(size
, GFP_KERNEL
);
49 kref_init(&obj
->kref
);
51 obj
->context
= fence_context_alloc(1);
52 strlcpy(obj
->name
, name
, sizeof(obj
->name
));
54 INIT_LIST_HEAD(&obj
->child_list_head
);
55 INIT_LIST_HEAD(&obj
->active_list_head
);
56 spin_lock_init(&obj
->child_list_lock
);
58 sync_timeline_debug_add(obj
);
62 EXPORT_SYMBOL(sync_timeline_create
);
64 static void sync_timeline_free(struct kref
*kref
)
66 struct sync_timeline
*obj
=
67 container_of(kref
, struct sync_timeline
, kref
);
69 sync_timeline_debug_remove(obj
);
74 static void sync_timeline_get(struct sync_timeline
*obj
)
79 static void sync_timeline_put(struct sync_timeline
*obj
)
81 kref_put(&obj
->kref
, sync_timeline_free
);
84 void sync_timeline_destroy(struct sync_timeline
*obj
)
86 obj
->destroyed
= true;
88 * Ensure timeline is marked as destroyed before
89 * changing timeline's fences status.
93 sync_timeline_put(obj
);
95 EXPORT_SYMBOL(sync_timeline_destroy
);
97 void sync_timeline_signal(struct sync_timeline
*obj
)
100 struct fence
*fence
, *next
;
102 trace_sync_timeline(obj
);
104 spin_lock_irqsave(&obj
->child_list_lock
, flags
);
106 list_for_each_entry_safe(fence
, next
, &obj
->active_list_head
,
108 if (fence_is_signaled_locked(fence
))
109 list_del_init(&fence
->active_list
);
112 spin_unlock_irqrestore(&obj
->child_list_lock
, flags
);
114 EXPORT_SYMBOL(sync_timeline_signal
);
116 struct fence
*sync_pt_create(struct sync_timeline
*obj
, int size
)
121 if (size
< sizeof(*fence
))
124 fence
= kzalloc(size
, GFP_KERNEL
);
128 spin_lock_irqsave(&obj
->child_list_lock
, flags
);
129 sync_timeline_get(obj
);
130 fence_init(fence
, &android_fence_ops
, &obj
->child_list_lock
,
131 obj
->context
, ++obj
->value
);
132 list_add_tail(&fence
->child_list
, &obj
->child_list_head
);
133 INIT_LIST_HEAD(&fence
->active_list
);
134 spin_unlock_irqrestore(&obj
->child_list_lock
, flags
);
137 EXPORT_SYMBOL(sync_pt_create
);
139 static struct sync_file
*sync_file_alloc(int size
, const char *name
)
141 struct sync_file
*sync_file
;
143 sync_file
= kzalloc(size
, GFP_KERNEL
);
147 sync_file
->file
= anon_inode_getfile("sync_file", &sync_file_fops
,
149 if (IS_ERR(sync_file
->file
))
152 kref_init(&sync_file
->kref
);
153 strlcpy(sync_file
->name
, name
, sizeof(sync_file
->name
));
155 init_waitqueue_head(&sync_file
->wq
);
164 static void fence_check_cb_func(struct fence
*f
, struct fence_cb
*cb
)
166 struct sync_file_cb
*check
;
167 struct sync_file
*sync_file
;
169 check
= container_of(cb
, struct sync_file_cb
, cb
);
170 sync_file
= check
->sync_file
;
172 if (atomic_dec_and_test(&sync_file
->status
))
173 wake_up_all(&sync_file
->wq
);
176 /* TODO: implement a create which takes more that one fence */
177 struct sync_file
*sync_file_create(const char *name
, struct fence
*fence
)
179 struct sync_file
*sync_file
;
181 sync_file
= sync_file_alloc(offsetof(struct sync_file
, cbs
[1]),
186 sync_file
->num_fences
= 1;
187 atomic_set(&sync_file
->status
, 1);
189 sync_file
->cbs
[0].fence
= fence
;
190 sync_file
->cbs
[0].sync_file
= sync_file
;
191 if (fence_add_callback(fence
, &sync_file
->cbs
[0].cb
,
192 fence_check_cb_func
))
193 atomic_dec(&sync_file
->status
);
195 sync_file_debug_add(sync_file
);
199 EXPORT_SYMBOL(sync_file_create
);
201 struct sync_file
*sync_file_fdget(int fd
)
203 struct file
*file
= fget(fd
);
208 if (file
->f_op
!= &sync_file_fops
)
211 return file
->private_data
;
217 EXPORT_SYMBOL(sync_file_fdget
);
219 void sync_file_put(struct sync_file
*sync_file
)
221 fput(sync_file
->file
);
223 EXPORT_SYMBOL(sync_file_put
);
225 void sync_file_install(struct sync_file
*sync_file
, int fd
)
227 fd_install(fd
, sync_file
->file
);
229 EXPORT_SYMBOL(sync_file_install
);
231 static void sync_file_add_pt(struct sync_file
*sync_file
, int *i
,
234 sync_file
->cbs
[*i
].fence
= fence
;
235 sync_file
->cbs
[*i
].sync_file
= sync_file
;
237 if (!fence_add_callback(fence
, &sync_file
->cbs
[*i
].cb
,
238 fence_check_cb_func
)) {
244 struct sync_file
*sync_file_merge(const char *name
,
245 struct sync_file
*a
, struct sync_file
*b
)
247 int num_fences
= a
->num_fences
+ b
->num_fences
;
248 struct sync_file
*sync_file
;
250 unsigned long size
= offsetof(struct sync_file
, cbs
[num_fences
]);
252 sync_file
= sync_file_alloc(size
, name
);
256 atomic_set(&sync_file
->status
, num_fences
);
259 * Assume sync_file a and b are both ordered and have no
260 * duplicates with the same context.
262 * If a sync_file can only be created with sync_file_merge
263 * and sync_file_create, this is a reasonable assumption.
265 for (i
= i_a
= i_b
= 0; i_a
< a
->num_fences
&& i_b
< b
->num_fences
; ) {
266 struct fence
*pt_a
= a
->cbs
[i_a
].fence
;
267 struct fence
*pt_b
= b
->cbs
[i_b
].fence
;
269 if (pt_a
->context
< pt_b
->context
) {
270 sync_file_add_pt(sync_file
, &i
, pt_a
);
273 } else if (pt_a
->context
> pt_b
->context
) {
274 sync_file_add_pt(sync_file
, &i
, pt_b
);
278 if (pt_a
->seqno
- pt_b
->seqno
<= INT_MAX
)
279 sync_file_add_pt(sync_file
, &i
, pt_a
);
281 sync_file_add_pt(sync_file
, &i
, pt_b
);
288 for (; i_a
< a
->num_fences
; i_a
++)
289 sync_file_add_pt(sync_file
, &i
, a
->cbs
[i_a
].fence
);
291 for (; i_b
< b
->num_fences
; i_b
++)
292 sync_file_add_pt(sync_file
, &i
, b
->cbs
[i_b
].fence
);
295 atomic_sub(num_fences
- i
, &sync_file
->status
);
296 sync_file
->num_fences
= i
;
298 sync_file_debug_add(sync_file
);
301 EXPORT_SYMBOL(sync_file_merge
);
303 static const char *android_fence_get_driver_name(struct fence
*fence
)
305 struct sync_timeline
*parent
= fence_parent(fence
);
307 return parent
->ops
->driver_name
;
310 static const char *android_fence_get_timeline_name(struct fence
*fence
)
312 struct sync_timeline
*parent
= fence_parent(fence
);
317 static void android_fence_release(struct fence
*fence
)
319 struct sync_timeline
*parent
= fence_parent(fence
);
322 spin_lock_irqsave(fence
->lock
, flags
);
323 list_del(&fence
->child_list
);
324 if (WARN_ON_ONCE(!list_empty(&fence
->active_list
)))
325 list_del(&fence
->active_list
);
326 spin_unlock_irqrestore(fence
->lock
, flags
);
328 sync_timeline_put(parent
);
332 static bool android_fence_signaled(struct fence
*fence
)
334 struct sync_timeline
*parent
= fence_parent(fence
);
337 ret
= parent
->ops
->has_signaled(fence
);
343 static bool android_fence_enable_signaling(struct fence
*fence
)
345 struct sync_timeline
*parent
= fence_parent(fence
);
347 if (android_fence_signaled(fence
))
350 list_add_tail(&fence
->active_list
, &parent
->active_list_head
);
354 static void android_fence_value_str(struct fence
*fence
,
357 struct sync_timeline
*parent
= fence_parent(fence
);
359 if (!parent
->ops
->fence_value_str
) {
364 parent
->ops
->fence_value_str(fence
, str
, size
);
367 static void android_fence_timeline_value_str(struct fence
*fence
,
370 struct sync_timeline
*parent
= fence_parent(fence
);
372 if (!parent
->ops
->timeline_value_str
) {
377 parent
->ops
->timeline_value_str(parent
, str
, size
);
380 static const struct fence_ops android_fence_ops
= {
381 .get_driver_name
= android_fence_get_driver_name
,
382 .get_timeline_name
= android_fence_get_timeline_name
,
383 .enable_signaling
= android_fence_enable_signaling
,
384 .signaled
= android_fence_signaled
,
385 .wait
= fence_default_wait
,
386 .release
= android_fence_release
,
387 .fence_value_str
= android_fence_value_str
,
388 .timeline_value_str
= android_fence_timeline_value_str
,
391 static void sync_file_free(struct kref
*kref
)
393 struct sync_file
*sync_file
= container_of(kref
, struct sync_file
,
397 for (i
= 0; i
< sync_file
->num_fences
; ++i
) {
398 fence_remove_callback(sync_file
->cbs
[i
].fence
,
399 &sync_file
->cbs
[i
].cb
);
400 fence_put(sync_file
->cbs
[i
].fence
);
406 static int sync_file_release(struct inode
*inode
, struct file
*file
)
408 struct sync_file
*sync_file
= file
->private_data
;
410 sync_file_debug_remove(sync_file
);
412 kref_put(&sync_file
->kref
, sync_file_free
);
416 static unsigned int sync_file_poll(struct file
*file
, poll_table
*wait
)
418 struct sync_file
*sync_file
= file
->private_data
;
421 poll_wait(file
, &sync_file
->wq
, wait
);
423 status
= atomic_read(&sync_file
->status
);
432 static long sync_file_ioctl_merge(struct sync_file
*sync_file
,
435 int fd
= get_unused_fd_flags(O_CLOEXEC
);
437 struct sync_file
*fence2
, *fence3
;
438 struct sync_merge_data data
;
443 if (copy_from_user(&data
, (void __user
*)arg
, sizeof(data
))) {
448 fence2
= sync_file_fdget(data
.fd2
);
454 data
.name
[sizeof(data
.name
) - 1] = '\0';
455 fence3
= sync_file_merge(data
.name
, sync_file
, fence2
);
462 if (copy_to_user((void __user
*)arg
, &data
, sizeof(data
))) {
467 sync_file_install(fence3
, fd
);
468 sync_file_put(fence2
);
472 sync_file_put(fence3
);
475 sync_file_put(fence2
);
482 static int sync_fill_fence_info(struct fence
*fence
, void *data
, int size
)
484 struct sync_fence_info
*info
= data
;
486 if (size
< sizeof(*info
))
489 strlcpy(info
->obj_name
, fence
->ops
->get_timeline_name(fence
),
490 sizeof(info
->obj_name
));
491 strlcpy(info
->driver_name
, fence
->ops
->get_driver_name(fence
),
492 sizeof(info
->driver_name
));
493 if (fence_is_signaled(fence
))
494 info
->status
= fence
->status
>= 0 ? 1 : fence
->status
;
497 info
->timestamp_ns
= ktime_to_ns(fence
->timestamp
);
499 return sizeof(*info
);
502 static long sync_file_ioctl_fence_info(struct sync_file
*sync_file
,
505 struct sync_file_info
*info
;
510 if (copy_from_user(&size
, (void __user
*)arg
, sizeof(size
)))
513 if (size
< sizeof(struct sync_file_info
))
519 info
= kzalloc(size
, GFP_KERNEL
);
523 strlcpy(info
->name
, sync_file
->name
, sizeof(info
->name
));
524 info
->status
= atomic_read(&sync_file
->status
);
525 if (info
->status
>= 0)
526 info
->status
= !info
->status
;
528 len
= sizeof(struct sync_file_info
);
530 for (i
= 0; i
< sync_file
->num_fences
; ++i
) {
531 struct fence
*fence
= sync_file
->cbs
[i
].fence
;
533 ret
= sync_fill_fence_info(fence
, (u8
*)info
+ len
, size
- len
);
543 if (copy_to_user((void __user
*)arg
, info
, len
))
554 static long sync_file_ioctl(struct file
*file
, unsigned int cmd
,
557 struct sync_file
*sync_file
= file
->private_data
;
561 return sync_file_ioctl_merge(sync_file
, arg
);
563 case SYNC_IOC_FENCE_INFO
:
564 return sync_file_ioctl_fence_info(sync_file
, arg
);
571 static const struct file_operations sync_file_fops
= {
572 .release
= sync_file_release
,
573 .poll
= sync_file_poll
,
574 .unlocked_ioctl
= sync_file_ioctl
,
575 .compat_ioctl
= sync_file_ioctl
,