1*00c7fec1SAndroid Build Coastguard Worker /*
2*00c7fec1SAndroid Build Coastguard Worker * sync.c
3*00c7fec1SAndroid Build Coastguard Worker *
4*00c7fec1SAndroid Build Coastguard Worker * Copyright 2012 Google, Inc
5*00c7fec1SAndroid Build Coastguard Worker *
6*00c7fec1SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
7*00c7fec1SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
8*00c7fec1SAndroid Build Coastguard Worker * You may obtain a copy of the License at
9*00c7fec1SAndroid Build Coastguard Worker *
10*00c7fec1SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
11*00c7fec1SAndroid Build Coastguard Worker *
12*00c7fec1SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
13*00c7fec1SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
14*00c7fec1SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*00c7fec1SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
16*00c7fec1SAndroid Build Coastguard Worker * limitations under the License.
17*00c7fec1SAndroid Build Coastguard Worker */
18*00c7fec1SAndroid Build Coastguard Worker
19*00c7fec1SAndroid Build Coastguard Worker #include <errno.h>
20*00c7fec1SAndroid Build Coastguard Worker #include <fcntl.h>
21*00c7fec1SAndroid Build Coastguard Worker #include <malloc.h>
22*00c7fec1SAndroid Build Coastguard Worker #include <poll.h>
23*00c7fec1SAndroid Build Coastguard Worker #include <stdatomic.h>
24*00c7fec1SAndroid Build Coastguard Worker #include <stdint.h>
25*00c7fec1SAndroid Build Coastguard Worker #include <string.h>
26*00c7fec1SAndroid Build Coastguard Worker
27*00c7fec1SAndroid Build Coastguard Worker #include <sys/ioctl.h>
28*00c7fec1SAndroid Build Coastguard Worker #include <sys/stat.h>
29*00c7fec1SAndroid Build Coastguard Worker #include <sys/types.h>
30*00c7fec1SAndroid Build Coastguard Worker
31*00c7fec1SAndroid Build Coastguard Worker #include <android/sync.h>
32*00c7fec1SAndroid Build Coastguard Worker
33*00c7fec1SAndroid Build Coastguard Worker /* Prototypes for deprecated functions that used to be declared in the legacy
34*00c7fec1SAndroid Build Coastguard Worker * android/sync.h. They've been moved here to make sure new code does not use
35*00c7fec1SAndroid Build Coastguard Worker * them, but the functions are still defined to avoid breaking existing
36*00c7fec1SAndroid Build Coastguard Worker * binaries. Eventually they can be removed altogether.
37*00c7fec1SAndroid Build Coastguard Worker */
38*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data {
39*00c7fec1SAndroid Build Coastguard Worker uint32_t len;
40*00c7fec1SAndroid Build Coastguard Worker char name[32];
41*00c7fec1SAndroid Build Coastguard Worker int32_t status;
42*00c7fec1SAndroid Build Coastguard Worker uint8_t pt_info[0];
43*00c7fec1SAndroid Build Coastguard Worker };
44*00c7fec1SAndroid Build Coastguard Worker struct sync_pt_info {
45*00c7fec1SAndroid Build Coastguard Worker uint32_t len;
46*00c7fec1SAndroid Build Coastguard Worker char obj_name[32];
47*00c7fec1SAndroid Build Coastguard Worker char driver_name[32];
48*00c7fec1SAndroid Build Coastguard Worker int32_t status;
49*00c7fec1SAndroid Build Coastguard Worker uint64_t timestamp_ns;
50*00c7fec1SAndroid Build Coastguard Worker uint8_t driver_data[0];
51*00c7fec1SAndroid Build Coastguard Worker };
52*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data* sync_fence_info(int fd);
53*00c7fec1SAndroid Build Coastguard Worker struct sync_pt_info* sync_pt_info(struct sync_fence_info_data* info, struct sync_pt_info* itr);
54*00c7fec1SAndroid Build Coastguard Worker void sync_fence_info_free(struct sync_fence_info_data* info);
55*00c7fec1SAndroid Build Coastguard Worker
56*00c7fec1SAndroid Build Coastguard Worker /* Legacy Sync API */
57*00c7fec1SAndroid Build Coastguard Worker
58*00c7fec1SAndroid Build Coastguard Worker struct sync_legacy_merge_data {
59*00c7fec1SAndroid Build Coastguard Worker int32_t fd2;
60*00c7fec1SAndroid Build Coastguard Worker char name[32];
61*00c7fec1SAndroid Build Coastguard Worker int32_t fence;
62*00c7fec1SAndroid Build Coastguard Worker };
63*00c7fec1SAndroid Build Coastguard Worker
64*00c7fec1SAndroid Build Coastguard Worker /**
65*00c7fec1SAndroid Build Coastguard Worker * DOC: SYNC_IOC_MERGE - merge two fences
66*00c7fec1SAndroid Build Coastguard Worker *
67*00c7fec1SAndroid Build Coastguard Worker * Takes a struct sync_merge_data. Creates a new fence containing copies of
68*00c7fec1SAndroid Build Coastguard Worker * the sync_pts in both the calling fd and sync_merge_data.fd2. Returns the
69*00c7fec1SAndroid Build Coastguard Worker * new fence's fd in sync_merge_data.fence
70*00c7fec1SAndroid Build Coastguard Worker *
71*00c7fec1SAndroid Build Coastguard Worker * This is the legacy version of the Sync API before the de-stage that happened
72*00c7fec1SAndroid Build Coastguard Worker * on Linux kernel 4.7.
73*00c7fec1SAndroid Build Coastguard Worker */
74*00c7fec1SAndroid Build Coastguard Worker #define SYNC_IOC_LEGACY_MERGE _IOWR(SYNC_IOC_MAGIC, 1, \
75*00c7fec1SAndroid Build Coastguard Worker struct sync_legacy_merge_data)
76*00c7fec1SAndroid Build Coastguard Worker
77*00c7fec1SAndroid Build Coastguard Worker /**
78*00c7fec1SAndroid Build Coastguard Worker * DOC: SYNC_IOC_LEGACY_FENCE_INFO - get detailed information on a fence
79*00c7fec1SAndroid Build Coastguard Worker *
80*00c7fec1SAndroid Build Coastguard Worker * Takes a struct sync_fence_info_data with extra space allocated for pt_info.
81*00c7fec1SAndroid Build Coastguard Worker * Caller should write the size of the buffer into len. On return, len is
82*00c7fec1SAndroid Build Coastguard Worker * updated to reflect the total size of the sync_fence_info_data including
83*00c7fec1SAndroid Build Coastguard Worker * pt_info.
84*00c7fec1SAndroid Build Coastguard Worker *
85*00c7fec1SAndroid Build Coastguard Worker * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
86*00c7fec1SAndroid Build Coastguard Worker * To iterate over the sync_pt_infos, use the sync_pt_info.len field.
87*00c7fec1SAndroid Build Coastguard Worker *
88*00c7fec1SAndroid Build Coastguard Worker * This is the legacy version of the Sync API before the de-stage that happened
89*00c7fec1SAndroid Build Coastguard Worker * on Linux kernel 4.7.
90*00c7fec1SAndroid Build Coastguard Worker */
91*00c7fec1SAndroid Build Coastguard Worker #define SYNC_IOC_LEGACY_FENCE_INFO _IOWR(SYNC_IOC_MAGIC, 2,\
92*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data)
93*00c7fec1SAndroid Build Coastguard Worker
94*00c7fec1SAndroid Build Coastguard Worker /* SW Sync API */
95*00c7fec1SAndroid Build Coastguard Worker
96*00c7fec1SAndroid Build Coastguard Worker struct sw_sync_create_fence_data {
97*00c7fec1SAndroid Build Coastguard Worker __u32 value;
98*00c7fec1SAndroid Build Coastguard Worker char name[32];
99*00c7fec1SAndroid Build Coastguard Worker __s32 fence;
100*00c7fec1SAndroid Build Coastguard Worker };
101*00c7fec1SAndroid Build Coastguard Worker
102*00c7fec1SAndroid Build Coastguard Worker #define SW_SYNC_IOC_MAGIC 'W'
103*00c7fec1SAndroid Build Coastguard Worker #define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0, struct sw_sync_create_fence_data)
104*00c7fec1SAndroid Build Coastguard Worker #define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
105*00c7fec1SAndroid Build Coastguard Worker
106*00c7fec1SAndroid Build Coastguard Worker // ---------------------------------------------------------------------------
107*00c7fec1SAndroid Build Coastguard Worker // Support for caching the sync uapi version.
108*00c7fec1SAndroid Build Coastguard Worker //
109*00c7fec1SAndroid Build Coastguard Worker // This library supports both legacy (android/staging) uapi and modern
110*00c7fec1SAndroid Build Coastguard Worker // (mainline) sync uapi. Library calls first try one uapi, and if that fails,
111*00c7fec1SAndroid Build Coastguard Worker // try the other. Since any given kernel only supports one uapi version, after
112*00c7fec1SAndroid Build Coastguard Worker // the first successful syscall we know what the kernel supports and can skip
113*00c7fec1SAndroid Build Coastguard Worker // trying the other.
114*00c7fec1SAndroid Build Coastguard Worker
115*00c7fec1SAndroid Build Coastguard Worker enum uapi_version {
116*00c7fec1SAndroid Build Coastguard Worker UAPI_UNKNOWN,
117*00c7fec1SAndroid Build Coastguard Worker UAPI_MODERN,
118*00c7fec1SAndroid Build Coastguard Worker UAPI_LEGACY
119*00c7fec1SAndroid Build Coastguard Worker };
120*00c7fec1SAndroid Build Coastguard Worker static atomic_int g_uapi_version = ATOMIC_VAR_INIT(UAPI_UNKNOWN);
121*00c7fec1SAndroid Build Coastguard Worker
122*00c7fec1SAndroid Build Coastguard Worker // ---------------------------------------------------------------------------
123*00c7fec1SAndroid Build Coastguard Worker
sync_wait(int fd,int timeout)124*00c7fec1SAndroid Build Coastguard Worker int sync_wait(int fd, int timeout)
125*00c7fec1SAndroid Build Coastguard Worker {
126*00c7fec1SAndroid Build Coastguard Worker struct pollfd fds;
127*00c7fec1SAndroid Build Coastguard Worker int ret;
128*00c7fec1SAndroid Build Coastguard Worker
129*00c7fec1SAndroid Build Coastguard Worker if (fd < 0) {
130*00c7fec1SAndroid Build Coastguard Worker errno = EINVAL;
131*00c7fec1SAndroid Build Coastguard Worker return -1;
132*00c7fec1SAndroid Build Coastguard Worker }
133*00c7fec1SAndroid Build Coastguard Worker
134*00c7fec1SAndroid Build Coastguard Worker fds.fd = fd;
135*00c7fec1SAndroid Build Coastguard Worker fds.events = POLLIN;
136*00c7fec1SAndroid Build Coastguard Worker
137*00c7fec1SAndroid Build Coastguard Worker do {
138*00c7fec1SAndroid Build Coastguard Worker ret = poll(&fds, 1, timeout);
139*00c7fec1SAndroid Build Coastguard Worker if (ret > 0) {
140*00c7fec1SAndroid Build Coastguard Worker if (fds.revents & (POLLERR | POLLNVAL)) {
141*00c7fec1SAndroid Build Coastguard Worker errno = EINVAL;
142*00c7fec1SAndroid Build Coastguard Worker return -1;
143*00c7fec1SAndroid Build Coastguard Worker }
144*00c7fec1SAndroid Build Coastguard Worker return 0;
145*00c7fec1SAndroid Build Coastguard Worker } else if (ret == 0) {
146*00c7fec1SAndroid Build Coastguard Worker errno = ETIME;
147*00c7fec1SAndroid Build Coastguard Worker return -1;
148*00c7fec1SAndroid Build Coastguard Worker }
149*00c7fec1SAndroid Build Coastguard Worker } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
150*00c7fec1SAndroid Build Coastguard Worker
151*00c7fec1SAndroid Build Coastguard Worker return ret;
152*00c7fec1SAndroid Build Coastguard Worker }
153*00c7fec1SAndroid Build Coastguard Worker
legacy_sync_merge(const char * name,int fd1,int fd2)154*00c7fec1SAndroid Build Coastguard Worker static int legacy_sync_merge(const char *name, int fd1, int fd2)
155*00c7fec1SAndroid Build Coastguard Worker {
156*00c7fec1SAndroid Build Coastguard Worker struct sync_legacy_merge_data data;
157*00c7fec1SAndroid Build Coastguard Worker int ret;
158*00c7fec1SAndroid Build Coastguard Worker
159*00c7fec1SAndroid Build Coastguard Worker data.fd2 = fd2;
160*00c7fec1SAndroid Build Coastguard Worker strlcpy(data.name, name, sizeof(data.name));
161*00c7fec1SAndroid Build Coastguard Worker ret = ioctl(fd1, SYNC_IOC_LEGACY_MERGE, &data);
162*00c7fec1SAndroid Build Coastguard Worker if (ret < 0)
163*00c7fec1SAndroid Build Coastguard Worker return ret;
164*00c7fec1SAndroid Build Coastguard Worker return data.fence;
165*00c7fec1SAndroid Build Coastguard Worker }
166*00c7fec1SAndroid Build Coastguard Worker
modern_sync_merge(const char * name,int fd1,int fd2)167*00c7fec1SAndroid Build Coastguard Worker static int modern_sync_merge(const char *name, int fd1, int fd2)
168*00c7fec1SAndroid Build Coastguard Worker {
169*00c7fec1SAndroid Build Coastguard Worker struct sync_merge_data data;
170*00c7fec1SAndroid Build Coastguard Worker int ret;
171*00c7fec1SAndroid Build Coastguard Worker
172*00c7fec1SAndroid Build Coastguard Worker data.fd2 = fd2;
173*00c7fec1SAndroid Build Coastguard Worker strlcpy(data.name, name, sizeof(data.name));
174*00c7fec1SAndroid Build Coastguard Worker data.flags = 0;
175*00c7fec1SAndroid Build Coastguard Worker data.pad = 0;
176*00c7fec1SAndroid Build Coastguard Worker
177*00c7fec1SAndroid Build Coastguard Worker ret = ioctl(fd1, SYNC_IOC_MERGE, &data);
178*00c7fec1SAndroid Build Coastguard Worker if (ret < 0)
179*00c7fec1SAndroid Build Coastguard Worker return ret;
180*00c7fec1SAndroid Build Coastguard Worker return data.fence;
181*00c7fec1SAndroid Build Coastguard Worker }
182*00c7fec1SAndroid Build Coastguard Worker
sync_merge(const char * name,int fd1,int fd2)183*00c7fec1SAndroid Build Coastguard Worker int sync_merge(const char *name, int fd1, int fd2)
184*00c7fec1SAndroid Build Coastguard Worker {
185*00c7fec1SAndroid Build Coastguard Worker int uapi;
186*00c7fec1SAndroid Build Coastguard Worker int ret;
187*00c7fec1SAndroid Build Coastguard Worker
188*00c7fec1SAndroid Build Coastguard Worker uapi = atomic_load_explicit(&g_uapi_version, memory_order_acquire);
189*00c7fec1SAndroid Build Coastguard Worker
190*00c7fec1SAndroid Build Coastguard Worker if (uapi == UAPI_MODERN || uapi == UAPI_UNKNOWN) {
191*00c7fec1SAndroid Build Coastguard Worker ret = modern_sync_merge(name, fd1, fd2);
192*00c7fec1SAndroid Build Coastguard Worker if (ret >= 0 || errno != ENOTTY) {
193*00c7fec1SAndroid Build Coastguard Worker if (ret >= 0 && uapi == UAPI_UNKNOWN) {
194*00c7fec1SAndroid Build Coastguard Worker atomic_store_explicit(&g_uapi_version, UAPI_MODERN,
195*00c7fec1SAndroid Build Coastguard Worker memory_order_release);
196*00c7fec1SAndroid Build Coastguard Worker }
197*00c7fec1SAndroid Build Coastguard Worker return ret;
198*00c7fec1SAndroid Build Coastguard Worker }
199*00c7fec1SAndroid Build Coastguard Worker }
200*00c7fec1SAndroid Build Coastguard Worker
201*00c7fec1SAndroid Build Coastguard Worker ret = legacy_sync_merge(name, fd1, fd2);
202*00c7fec1SAndroid Build Coastguard Worker if (ret >= 0 && uapi == UAPI_UNKNOWN) {
203*00c7fec1SAndroid Build Coastguard Worker atomic_store_explicit(&g_uapi_version, UAPI_LEGACY,
204*00c7fec1SAndroid Build Coastguard Worker memory_order_release);
205*00c7fec1SAndroid Build Coastguard Worker }
206*00c7fec1SAndroid Build Coastguard Worker return ret;
207*00c7fec1SAndroid Build Coastguard Worker }
208*00c7fec1SAndroid Build Coastguard Worker
legacy_sync_fence_info(int fd)209*00c7fec1SAndroid Build Coastguard Worker static struct sync_fence_info_data *legacy_sync_fence_info(int fd)
210*00c7fec1SAndroid Build Coastguard Worker {
211*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data *legacy_info;
212*00c7fec1SAndroid Build Coastguard Worker struct sync_pt_info *legacy_pt_info;
213*00c7fec1SAndroid Build Coastguard Worker int err;
214*00c7fec1SAndroid Build Coastguard Worker
215*00c7fec1SAndroid Build Coastguard Worker legacy_info = malloc(4096);
216*00c7fec1SAndroid Build Coastguard Worker if (legacy_info == NULL)
217*00c7fec1SAndroid Build Coastguard Worker return NULL;
218*00c7fec1SAndroid Build Coastguard Worker
219*00c7fec1SAndroid Build Coastguard Worker legacy_info->len = 4096;
220*00c7fec1SAndroid Build Coastguard Worker err = ioctl(fd, SYNC_IOC_LEGACY_FENCE_INFO, legacy_info);
221*00c7fec1SAndroid Build Coastguard Worker if (err < 0) {
222*00c7fec1SAndroid Build Coastguard Worker free(legacy_info);
223*00c7fec1SAndroid Build Coastguard Worker return NULL;
224*00c7fec1SAndroid Build Coastguard Worker }
225*00c7fec1SAndroid Build Coastguard Worker return legacy_info;
226*00c7fec1SAndroid Build Coastguard Worker }
227*00c7fec1SAndroid Build Coastguard Worker
modern_sync_file_info(int fd)228*00c7fec1SAndroid Build Coastguard Worker static struct sync_file_info *modern_sync_file_info(int fd)
229*00c7fec1SAndroid Build Coastguard Worker {
230*00c7fec1SAndroid Build Coastguard Worker struct sync_file_info local_info;
231*00c7fec1SAndroid Build Coastguard Worker struct sync_file_info *info;
232*00c7fec1SAndroid Build Coastguard Worker int err;
233*00c7fec1SAndroid Build Coastguard Worker
234*00c7fec1SAndroid Build Coastguard Worker memset(&local_info, 0, sizeof(local_info));
235*00c7fec1SAndroid Build Coastguard Worker err = ioctl(fd, SYNC_IOC_FILE_INFO, &local_info);
236*00c7fec1SAndroid Build Coastguard Worker if (err < 0)
237*00c7fec1SAndroid Build Coastguard Worker return NULL;
238*00c7fec1SAndroid Build Coastguard Worker
239*00c7fec1SAndroid Build Coastguard Worker info = calloc(1, sizeof(struct sync_file_info) +
240*00c7fec1SAndroid Build Coastguard Worker local_info.num_fences * sizeof(struct sync_fence_info));
241*00c7fec1SAndroid Build Coastguard Worker if (!info)
242*00c7fec1SAndroid Build Coastguard Worker return NULL;
243*00c7fec1SAndroid Build Coastguard Worker
244*00c7fec1SAndroid Build Coastguard Worker info->num_fences = local_info.num_fences;
245*00c7fec1SAndroid Build Coastguard Worker info->sync_fence_info = (__u64)(uintptr_t)(info + 1);
246*00c7fec1SAndroid Build Coastguard Worker
247*00c7fec1SAndroid Build Coastguard Worker err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
248*00c7fec1SAndroid Build Coastguard Worker if (err < 0) {
249*00c7fec1SAndroid Build Coastguard Worker free(info);
250*00c7fec1SAndroid Build Coastguard Worker return NULL;
251*00c7fec1SAndroid Build Coastguard Worker }
252*00c7fec1SAndroid Build Coastguard Worker
253*00c7fec1SAndroid Build Coastguard Worker return info;
254*00c7fec1SAndroid Build Coastguard Worker }
255*00c7fec1SAndroid Build Coastguard Worker
sync_file_info_to_legacy_fence_info(const struct sync_file_info * info)256*00c7fec1SAndroid Build Coastguard Worker static struct sync_fence_info_data *sync_file_info_to_legacy_fence_info(
257*00c7fec1SAndroid Build Coastguard Worker const struct sync_file_info *info)
258*00c7fec1SAndroid Build Coastguard Worker {
259*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data *legacy_info;
260*00c7fec1SAndroid Build Coastguard Worker struct sync_pt_info *legacy_pt_info;
261*00c7fec1SAndroid Build Coastguard Worker const struct sync_fence_info *fence_info = sync_get_fence_info(info);
262*00c7fec1SAndroid Build Coastguard Worker const uint32_t num_fences = info->num_fences;
263*00c7fec1SAndroid Build Coastguard Worker
264*00c7fec1SAndroid Build Coastguard Worker legacy_info = malloc(4096);
265*00c7fec1SAndroid Build Coastguard Worker if (legacy_info == NULL)
266*00c7fec1SAndroid Build Coastguard Worker return NULL;
267*00c7fec1SAndroid Build Coastguard Worker legacy_info->len = sizeof(*legacy_info) +
268*00c7fec1SAndroid Build Coastguard Worker num_fences * sizeof(struct sync_pt_info);
269*00c7fec1SAndroid Build Coastguard Worker strlcpy(legacy_info->name, info->name, sizeof(legacy_info->name));
270*00c7fec1SAndroid Build Coastguard Worker legacy_info->status = info->status;
271*00c7fec1SAndroid Build Coastguard Worker
272*00c7fec1SAndroid Build Coastguard Worker legacy_pt_info = (struct sync_pt_info *)legacy_info->pt_info;
273*00c7fec1SAndroid Build Coastguard Worker for (uint32_t i = 0; i < num_fences; i++) {
274*00c7fec1SAndroid Build Coastguard Worker legacy_pt_info[i].len = sizeof(*legacy_pt_info);
275*00c7fec1SAndroid Build Coastguard Worker strlcpy(legacy_pt_info[i].obj_name, fence_info[i].obj_name,
276*00c7fec1SAndroid Build Coastguard Worker sizeof(legacy_pt_info->obj_name));
277*00c7fec1SAndroid Build Coastguard Worker strlcpy(legacy_pt_info[i].driver_name, fence_info[i].driver_name,
278*00c7fec1SAndroid Build Coastguard Worker sizeof(legacy_pt_info->driver_name));
279*00c7fec1SAndroid Build Coastguard Worker legacy_pt_info[i].status = fence_info[i].status;
280*00c7fec1SAndroid Build Coastguard Worker legacy_pt_info[i].timestamp_ns = fence_info[i].timestamp_ns;
281*00c7fec1SAndroid Build Coastguard Worker }
282*00c7fec1SAndroid Build Coastguard Worker
283*00c7fec1SAndroid Build Coastguard Worker return legacy_info;
284*00c7fec1SAndroid Build Coastguard Worker }
285*00c7fec1SAndroid Build Coastguard Worker
legacy_fence_info_to_sync_file_info(struct sync_fence_info_data * legacy_info)286*00c7fec1SAndroid Build Coastguard Worker static struct sync_file_info* legacy_fence_info_to_sync_file_info(
287*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data *legacy_info)
288*00c7fec1SAndroid Build Coastguard Worker {
289*00c7fec1SAndroid Build Coastguard Worker struct sync_file_info *info;
290*00c7fec1SAndroid Build Coastguard Worker struct sync_pt_info *pt;
291*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info *fence;
292*00c7fec1SAndroid Build Coastguard Worker size_t num_fences;
293*00c7fec1SAndroid Build Coastguard Worker int err;
294*00c7fec1SAndroid Build Coastguard Worker
295*00c7fec1SAndroid Build Coastguard Worker pt = NULL;
296*00c7fec1SAndroid Build Coastguard Worker num_fences = 0;
297*00c7fec1SAndroid Build Coastguard Worker while ((pt = sync_pt_info(legacy_info, pt)) != NULL)
298*00c7fec1SAndroid Build Coastguard Worker num_fences++;
299*00c7fec1SAndroid Build Coastguard Worker
300*00c7fec1SAndroid Build Coastguard Worker info = calloc(1, sizeof(struct sync_file_info) +
301*00c7fec1SAndroid Build Coastguard Worker num_fences * sizeof(struct sync_fence_info));
302*00c7fec1SAndroid Build Coastguard Worker if (!info) {
303*00c7fec1SAndroid Build Coastguard Worker return NULL;
304*00c7fec1SAndroid Build Coastguard Worker }
305*00c7fec1SAndroid Build Coastguard Worker info->sync_fence_info = (__u64)(uintptr_t)(info + 1);
306*00c7fec1SAndroid Build Coastguard Worker
307*00c7fec1SAndroid Build Coastguard Worker strlcpy(info->name, legacy_info->name, sizeof(info->name));
308*00c7fec1SAndroid Build Coastguard Worker info->status = legacy_info->status;
309*00c7fec1SAndroid Build Coastguard Worker info->num_fences = num_fences;
310*00c7fec1SAndroid Build Coastguard Worker
311*00c7fec1SAndroid Build Coastguard Worker pt = NULL;
312*00c7fec1SAndroid Build Coastguard Worker fence = sync_get_fence_info(info);
313*00c7fec1SAndroid Build Coastguard Worker while ((pt = sync_pt_info(legacy_info, pt)) != NULL) {
314*00c7fec1SAndroid Build Coastguard Worker strlcpy(fence->obj_name, pt->obj_name, sizeof(fence->obj_name));
315*00c7fec1SAndroid Build Coastguard Worker strlcpy(fence->driver_name, pt->driver_name,
316*00c7fec1SAndroid Build Coastguard Worker sizeof(fence->driver_name));
317*00c7fec1SAndroid Build Coastguard Worker fence->status = pt->status;
318*00c7fec1SAndroid Build Coastguard Worker fence->timestamp_ns = pt->timestamp_ns;
319*00c7fec1SAndroid Build Coastguard Worker fence++;
320*00c7fec1SAndroid Build Coastguard Worker }
321*00c7fec1SAndroid Build Coastguard Worker
322*00c7fec1SAndroid Build Coastguard Worker return info;
323*00c7fec1SAndroid Build Coastguard Worker }
324*00c7fec1SAndroid Build Coastguard Worker
sync_fence_info(int fd)325*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data *sync_fence_info(int fd)
326*00c7fec1SAndroid Build Coastguard Worker {
327*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data *legacy_info;
328*00c7fec1SAndroid Build Coastguard Worker int uapi;
329*00c7fec1SAndroid Build Coastguard Worker
330*00c7fec1SAndroid Build Coastguard Worker uapi = atomic_load_explicit(&g_uapi_version, memory_order_acquire);
331*00c7fec1SAndroid Build Coastguard Worker
332*00c7fec1SAndroid Build Coastguard Worker if (uapi == UAPI_LEGACY || uapi == UAPI_UNKNOWN) {
333*00c7fec1SAndroid Build Coastguard Worker legacy_info = legacy_sync_fence_info(fd);
334*00c7fec1SAndroid Build Coastguard Worker if (legacy_info || errno != ENOTTY) {
335*00c7fec1SAndroid Build Coastguard Worker if (legacy_info && uapi == UAPI_UNKNOWN) {
336*00c7fec1SAndroid Build Coastguard Worker atomic_store_explicit(&g_uapi_version, UAPI_LEGACY,
337*00c7fec1SAndroid Build Coastguard Worker memory_order_release);
338*00c7fec1SAndroid Build Coastguard Worker }
339*00c7fec1SAndroid Build Coastguard Worker return legacy_info;
340*00c7fec1SAndroid Build Coastguard Worker }
341*00c7fec1SAndroid Build Coastguard Worker }
342*00c7fec1SAndroid Build Coastguard Worker
343*00c7fec1SAndroid Build Coastguard Worker struct sync_file_info* file_info;
344*00c7fec1SAndroid Build Coastguard Worker file_info = modern_sync_file_info(fd);
345*00c7fec1SAndroid Build Coastguard Worker if (!file_info)
346*00c7fec1SAndroid Build Coastguard Worker return NULL;
347*00c7fec1SAndroid Build Coastguard Worker if (uapi == UAPI_UNKNOWN) {
348*00c7fec1SAndroid Build Coastguard Worker atomic_store_explicit(&g_uapi_version, UAPI_MODERN,
349*00c7fec1SAndroid Build Coastguard Worker memory_order_release);
350*00c7fec1SAndroid Build Coastguard Worker }
351*00c7fec1SAndroid Build Coastguard Worker legacy_info = sync_file_info_to_legacy_fence_info(file_info);
352*00c7fec1SAndroid Build Coastguard Worker sync_file_info_free(file_info);
353*00c7fec1SAndroid Build Coastguard Worker return legacy_info;
354*00c7fec1SAndroid Build Coastguard Worker }
355*00c7fec1SAndroid Build Coastguard Worker
sync_file_info(int32_t fd)356*00c7fec1SAndroid Build Coastguard Worker struct sync_file_info* sync_file_info(int32_t fd)
357*00c7fec1SAndroid Build Coastguard Worker {
358*00c7fec1SAndroid Build Coastguard Worker struct sync_file_info *info;
359*00c7fec1SAndroid Build Coastguard Worker int uapi;
360*00c7fec1SAndroid Build Coastguard Worker
361*00c7fec1SAndroid Build Coastguard Worker uapi = atomic_load_explicit(&g_uapi_version, memory_order_acquire);
362*00c7fec1SAndroid Build Coastguard Worker
363*00c7fec1SAndroid Build Coastguard Worker if (uapi == UAPI_MODERN || uapi == UAPI_UNKNOWN) {
364*00c7fec1SAndroid Build Coastguard Worker info = modern_sync_file_info(fd);
365*00c7fec1SAndroid Build Coastguard Worker if (info || errno != ENOTTY) {
366*00c7fec1SAndroid Build Coastguard Worker if (info && uapi == UAPI_UNKNOWN) {
367*00c7fec1SAndroid Build Coastguard Worker atomic_store_explicit(&g_uapi_version, UAPI_MODERN,
368*00c7fec1SAndroid Build Coastguard Worker memory_order_release);
369*00c7fec1SAndroid Build Coastguard Worker }
370*00c7fec1SAndroid Build Coastguard Worker return info;
371*00c7fec1SAndroid Build Coastguard Worker }
372*00c7fec1SAndroid Build Coastguard Worker }
373*00c7fec1SAndroid Build Coastguard Worker
374*00c7fec1SAndroid Build Coastguard Worker struct sync_fence_info_data *legacy_info;
375*00c7fec1SAndroid Build Coastguard Worker legacy_info = legacy_sync_fence_info(fd);
376*00c7fec1SAndroid Build Coastguard Worker if (!legacy_info)
377*00c7fec1SAndroid Build Coastguard Worker return NULL;
378*00c7fec1SAndroid Build Coastguard Worker if (uapi == UAPI_UNKNOWN) {
379*00c7fec1SAndroid Build Coastguard Worker atomic_store_explicit(&g_uapi_version, UAPI_LEGACY,
380*00c7fec1SAndroid Build Coastguard Worker memory_order_release);
381*00c7fec1SAndroid Build Coastguard Worker }
382*00c7fec1SAndroid Build Coastguard Worker info = legacy_fence_info_to_sync_file_info(legacy_info);
383*00c7fec1SAndroid Build Coastguard Worker sync_fence_info_free(legacy_info);
384*00c7fec1SAndroid Build Coastguard Worker return info;
385*00c7fec1SAndroid Build Coastguard Worker }
386*00c7fec1SAndroid Build Coastguard Worker
sync_pt_info(struct sync_fence_info_data * info,struct sync_pt_info * itr)387*00c7fec1SAndroid Build Coastguard Worker struct sync_pt_info *sync_pt_info(struct sync_fence_info_data *info,
388*00c7fec1SAndroid Build Coastguard Worker struct sync_pt_info *itr)
389*00c7fec1SAndroid Build Coastguard Worker {
390*00c7fec1SAndroid Build Coastguard Worker if (itr == NULL)
391*00c7fec1SAndroid Build Coastguard Worker itr = (struct sync_pt_info *) info->pt_info;
392*00c7fec1SAndroid Build Coastguard Worker else
393*00c7fec1SAndroid Build Coastguard Worker itr = (struct sync_pt_info *) ((__u8 *)itr + itr->len);
394*00c7fec1SAndroid Build Coastguard Worker
395*00c7fec1SAndroid Build Coastguard Worker if ((__u8 *)itr - (__u8 *)info >= (int)info->len)
396*00c7fec1SAndroid Build Coastguard Worker return NULL;
397*00c7fec1SAndroid Build Coastguard Worker
398*00c7fec1SAndroid Build Coastguard Worker return itr;
399*00c7fec1SAndroid Build Coastguard Worker }
400*00c7fec1SAndroid Build Coastguard Worker
sync_fence_info_free(struct sync_fence_info_data * info)401*00c7fec1SAndroid Build Coastguard Worker void sync_fence_info_free(struct sync_fence_info_data *info)
402*00c7fec1SAndroid Build Coastguard Worker {
403*00c7fec1SAndroid Build Coastguard Worker free(info);
404*00c7fec1SAndroid Build Coastguard Worker }
405*00c7fec1SAndroid Build Coastguard Worker
sync_file_info_free(struct sync_file_info * info)406*00c7fec1SAndroid Build Coastguard Worker void sync_file_info_free(struct sync_file_info *info)
407*00c7fec1SAndroid Build Coastguard Worker {
408*00c7fec1SAndroid Build Coastguard Worker free(info);
409*00c7fec1SAndroid Build Coastguard Worker }
410*00c7fec1SAndroid Build Coastguard Worker
411*00c7fec1SAndroid Build Coastguard Worker
sw_sync_timeline_create(void)412*00c7fec1SAndroid Build Coastguard Worker int sw_sync_timeline_create(void)
413*00c7fec1SAndroid Build Coastguard Worker {
414*00c7fec1SAndroid Build Coastguard Worker int ret;
415*00c7fec1SAndroid Build Coastguard Worker
416*00c7fec1SAndroid Build Coastguard Worker ret = open("/sys/kernel/debug/sync/sw_sync", O_RDWR);
417*00c7fec1SAndroid Build Coastguard Worker if (ret < 0)
418*00c7fec1SAndroid Build Coastguard Worker ret = open("/dev/sw_sync", O_RDWR);
419*00c7fec1SAndroid Build Coastguard Worker
420*00c7fec1SAndroid Build Coastguard Worker return ret;
421*00c7fec1SAndroid Build Coastguard Worker }
422*00c7fec1SAndroid Build Coastguard Worker
sw_sync_timeline_inc(int fd,unsigned count)423*00c7fec1SAndroid Build Coastguard Worker int sw_sync_timeline_inc(int fd, unsigned count)
424*00c7fec1SAndroid Build Coastguard Worker {
425*00c7fec1SAndroid Build Coastguard Worker __u32 arg = count;
426*00c7fec1SAndroid Build Coastguard Worker
427*00c7fec1SAndroid Build Coastguard Worker return ioctl(fd, SW_SYNC_IOC_INC, &arg);
428*00c7fec1SAndroid Build Coastguard Worker }
429*00c7fec1SAndroid Build Coastguard Worker
sw_sync_fence_create(int fd,const char * name,unsigned value)430*00c7fec1SAndroid Build Coastguard Worker int sw_sync_fence_create(int fd, const char *name, unsigned value)
431*00c7fec1SAndroid Build Coastguard Worker {
432*00c7fec1SAndroid Build Coastguard Worker struct sw_sync_create_fence_data data;
433*00c7fec1SAndroid Build Coastguard Worker int err;
434*00c7fec1SAndroid Build Coastguard Worker
435*00c7fec1SAndroid Build Coastguard Worker data.value = value;
436*00c7fec1SAndroid Build Coastguard Worker strlcpy(data.name, name, sizeof(data.name));
437*00c7fec1SAndroid Build Coastguard Worker
438*00c7fec1SAndroid Build Coastguard Worker err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data);
439*00c7fec1SAndroid Build Coastguard Worker if (err < 0)
440*00c7fec1SAndroid Build Coastguard Worker return err;
441*00c7fec1SAndroid Build Coastguard Worker
442*00c7fec1SAndroid Build Coastguard Worker return data.fence;
443*00c7fec1SAndroid Build Coastguard Worker }
444