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/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/seq_file.h>
22 #include <linux/slab.h>
23 #include <linux/uaccess.h>
24 #include <linux/anon_inodes.h>
28 #define CREATE_TRACE_POINTS
29 #include "trace/sync.h"
31 static const struct fence_ops android_fence_ops
;
33 struct sync_timeline
*sync_timeline_create(const struct sync_timeline_ops
*ops
,
34 int size
, const char *name
)
36 struct sync_timeline
*obj
;
38 if (size
< sizeof(struct sync_timeline
))
41 obj
= kzalloc(size
, GFP_KERNEL
);
45 kref_init(&obj
->kref
);
47 obj
->context
= fence_context_alloc(1);
48 strlcpy(obj
->name
, name
, sizeof(obj
->name
));
50 INIT_LIST_HEAD(&obj
->child_list_head
);
51 INIT_LIST_HEAD(&obj
->active_list_head
);
52 spin_lock_init(&obj
->child_list_lock
);
54 sync_timeline_debug_add(obj
);
58 EXPORT_SYMBOL(sync_timeline_create
);
60 static void sync_timeline_free(struct kref
*kref
)
62 struct sync_timeline
*obj
=
63 container_of(kref
, struct sync_timeline
, kref
);
65 sync_timeline_debug_remove(obj
);
70 static void sync_timeline_get(struct sync_timeline
*obj
)
75 static void sync_timeline_put(struct sync_timeline
*obj
)
77 kref_put(&obj
->kref
, sync_timeline_free
);
80 void sync_timeline_destroy(struct sync_timeline
*obj
)
82 obj
->destroyed
= true;
84 * Ensure timeline is marked as destroyed before
85 * changing timeline's fences status.
89 sync_timeline_put(obj
);
91 EXPORT_SYMBOL(sync_timeline_destroy
);
93 void sync_timeline_signal(struct sync_timeline
*obj
)
96 struct fence
*fence
, *next
;
98 trace_sync_timeline(obj
);
100 spin_lock_irqsave(&obj
->child_list_lock
, flags
);
102 list_for_each_entry_safe(fence
, next
, &obj
->active_list_head
,
104 if (fence_is_signaled_locked(fence
))
105 list_del_init(&fence
->active_list
);
108 spin_unlock_irqrestore(&obj
->child_list_lock
, flags
);
110 EXPORT_SYMBOL(sync_timeline_signal
);
112 struct fence
*sync_pt_create(struct sync_timeline
*obj
, int size
)
117 if (size
< sizeof(*fence
))
120 fence
= kzalloc(size
, GFP_KERNEL
);
124 spin_lock_irqsave(&obj
->child_list_lock
, flags
);
125 sync_timeline_get(obj
);
126 fence_init(fence
, &android_fence_ops
, &obj
->child_list_lock
,
127 obj
->context
, ++obj
->value
);
128 list_add_tail(&fence
->child_list
, &obj
->child_list_head
);
129 INIT_LIST_HEAD(&fence
->active_list
);
130 spin_unlock_irqrestore(&obj
->child_list_lock
, flags
);
133 EXPORT_SYMBOL(sync_pt_create
);
135 static const char *android_fence_get_driver_name(struct fence
*fence
)
137 struct sync_timeline
*parent
= fence_parent(fence
);
139 return parent
->ops
->driver_name
;
142 static const char *android_fence_get_timeline_name(struct fence
*fence
)
144 struct sync_timeline
*parent
= fence_parent(fence
);
149 static void android_fence_release(struct fence
*fence
)
151 struct sync_timeline
*parent
= fence_parent(fence
);
154 spin_lock_irqsave(fence
->lock
, flags
);
155 list_del(&fence
->child_list
);
156 if (WARN_ON_ONCE(!list_empty(&fence
->active_list
)))
157 list_del(&fence
->active_list
);
158 spin_unlock_irqrestore(fence
->lock
, flags
);
160 sync_timeline_put(parent
);
164 static bool android_fence_signaled(struct fence
*fence
)
166 struct sync_timeline
*parent
= fence_parent(fence
);
169 ret
= parent
->ops
->has_signaled(fence
);
175 static bool android_fence_enable_signaling(struct fence
*fence
)
177 struct sync_timeline
*parent
= fence_parent(fence
);
179 if (android_fence_signaled(fence
))
182 list_add_tail(&fence
->active_list
, &parent
->active_list_head
);
186 static void android_fence_value_str(struct fence
*fence
,
189 struct sync_timeline
*parent
= fence_parent(fence
);
191 if (!parent
->ops
->fence_value_str
) {
196 parent
->ops
->fence_value_str(fence
, str
, size
);
199 static void android_fence_timeline_value_str(struct fence
*fence
,
202 struct sync_timeline
*parent
= fence_parent(fence
);
204 if (!parent
->ops
->timeline_value_str
) {
209 parent
->ops
->timeline_value_str(parent
, str
, size
);
212 static const struct fence_ops android_fence_ops
= {
213 .get_driver_name
= android_fence_get_driver_name
,
214 .get_timeline_name
= android_fence_get_timeline_name
,
215 .enable_signaling
= android_fence_enable_signaling
,
216 .signaled
= android_fence_signaled
,
217 .wait
= fence_default_wait
,
218 .release
= android_fence_release
,
219 .fence_value_str
= android_fence_value_str
,
220 .timeline_value_str
= android_fence_timeline_value_str
,