xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/sync/sync.c (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
1*053f45beSAndroid Build Coastguard Worker /*
2*053f45beSAndroid Build Coastguard Worker  *  sync / sw_sync abstraction
3*053f45beSAndroid Build Coastguard Worker  *  Copyright 2015-2016 Collabora Ltd.
4*053f45beSAndroid Build Coastguard Worker  *
5*053f45beSAndroid Build Coastguard Worker  *  Based on the implementation from the Android Open Source Project,
6*053f45beSAndroid Build Coastguard Worker  *
7*053f45beSAndroid Build Coastguard Worker  *  Copyright 2012 Google, Inc
8*053f45beSAndroid Build Coastguard Worker  *
9*053f45beSAndroid Build Coastguard Worker  *  Permission is hereby granted, free of charge, to any person obtaining a
10*053f45beSAndroid Build Coastguard Worker  *  copy of this software and associated documentation files (the "Software"),
11*053f45beSAndroid Build Coastguard Worker  *  to deal in the Software without restriction, including without limitation
12*053f45beSAndroid Build Coastguard Worker  *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
13*053f45beSAndroid Build Coastguard Worker  *  and/or sell copies of the Software, and to permit persons to whom the
14*053f45beSAndroid Build Coastguard Worker  *  Software is furnished to do so, subject to the following conditions:
15*053f45beSAndroid Build Coastguard Worker  *
16*053f45beSAndroid Build Coastguard Worker  *  The above copyright notice and this permission notice shall be included in
17*053f45beSAndroid Build Coastguard Worker  *  all copies or substantial portions of the Software.
18*053f45beSAndroid Build Coastguard Worker  *
19*053f45beSAndroid Build Coastguard Worker  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20*053f45beSAndroid Build Coastguard Worker  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21*053f45beSAndroid Build Coastguard Worker  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22*053f45beSAndroid Build Coastguard Worker  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23*053f45beSAndroid Build Coastguard Worker  *  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24*053f45beSAndroid Build Coastguard Worker  *  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25*053f45beSAndroid Build Coastguard Worker  *  OTHER DEALINGS IN THE SOFTWARE.
26*053f45beSAndroid Build Coastguard Worker  */
27*053f45beSAndroid Build Coastguard Worker 
28*053f45beSAndroid Build Coastguard Worker #include <fcntl.h>
29*053f45beSAndroid Build Coastguard Worker #include <malloc.h>
30*053f45beSAndroid Build Coastguard Worker #include <poll.h>
31*053f45beSAndroid Build Coastguard Worker #include <stdint.h>
32*053f45beSAndroid Build Coastguard Worker #include <string.h>
33*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
34*053f45beSAndroid Build Coastguard Worker 
35*053f45beSAndroid Build Coastguard Worker #include <sys/ioctl.h>
36*053f45beSAndroid Build Coastguard Worker #include <sys/stat.h>
37*053f45beSAndroid Build Coastguard Worker #include <sys/types.h>
38*053f45beSAndroid Build Coastguard Worker 
39*053f45beSAndroid Build Coastguard Worker #include "sync.h"
40*053f45beSAndroid Build Coastguard Worker #include "sw_sync.h"
41*053f45beSAndroid Build Coastguard Worker 
42*053f45beSAndroid Build Coastguard Worker #include <linux/sync_file.h>
43*053f45beSAndroid Build Coastguard Worker 
44*053f45beSAndroid Build Coastguard Worker 
45*053f45beSAndroid Build Coastguard Worker /* SW_SYNC ioctls */
46*053f45beSAndroid Build Coastguard Worker struct sw_sync_create_fence_data {
47*053f45beSAndroid Build Coastguard Worker 	__u32	value;
48*053f45beSAndroid Build Coastguard Worker 	char	name[32];
49*053f45beSAndroid Build Coastguard Worker 	__s32	fence;
50*053f45beSAndroid Build Coastguard Worker };
51*053f45beSAndroid Build Coastguard Worker 
52*053f45beSAndroid Build Coastguard Worker #define SW_SYNC_IOC_MAGIC		'W'
53*053f45beSAndroid Build Coastguard Worker #define SW_SYNC_IOC_CREATE_FENCE	_IOWR(SW_SYNC_IOC_MAGIC, 0,\
54*053f45beSAndroid Build Coastguard Worker 					      struct sw_sync_create_fence_data)
55*053f45beSAndroid Build Coastguard Worker #define SW_SYNC_IOC_INC			_IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
56*053f45beSAndroid Build Coastguard Worker 
57*053f45beSAndroid Build Coastguard Worker 
sync_wait(int fd,int timeout)58*053f45beSAndroid Build Coastguard Worker int sync_wait(int fd, int timeout)
59*053f45beSAndroid Build Coastguard Worker {
60*053f45beSAndroid Build Coastguard Worker 	struct pollfd fds;
61*053f45beSAndroid Build Coastguard Worker 
62*053f45beSAndroid Build Coastguard Worker 	fds.fd = fd;
63*053f45beSAndroid Build Coastguard Worker 	fds.events = POLLIN | POLLERR;
64*053f45beSAndroid Build Coastguard Worker 
65*053f45beSAndroid Build Coastguard Worker 	return poll(&fds, 1, timeout);
66*053f45beSAndroid Build Coastguard Worker }
67*053f45beSAndroid Build Coastguard Worker 
sync_merge(const char * name,int fd1,int fd2)68*053f45beSAndroid Build Coastguard Worker int sync_merge(const char *name, int fd1, int fd2)
69*053f45beSAndroid Build Coastguard Worker {
70*053f45beSAndroid Build Coastguard Worker 	struct sync_merge_data data = {};
71*053f45beSAndroid Build Coastguard Worker 	int err;
72*053f45beSAndroid Build Coastguard Worker 
73*053f45beSAndroid Build Coastguard Worker 	data.fd2 = fd2;
74*053f45beSAndroid Build Coastguard Worker 	strncpy(data.name, name, sizeof(data.name) - 1);
75*053f45beSAndroid Build Coastguard Worker 	data.name[sizeof(data.name) - 1] = '\0';
76*053f45beSAndroid Build Coastguard Worker 
77*053f45beSAndroid Build Coastguard Worker 	err = ioctl(fd1, SYNC_IOC_MERGE, &data);
78*053f45beSAndroid Build Coastguard Worker 	if (err < 0)
79*053f45beSAndroid Build Coastguard Worker 		return err;
80*053f45beSAndroid Build Coastguard Worker 
81*053f45beSAndroid Build Coastguard Worker 	return data.fence;
82*053f45beSAndroid Build Coastguard Worker }
83*053f45beSAndroid Build Coastguard Worker 
sync_file_info(int fd)84*053f45beSAndroid Build Coastguard Worker static struct sync_file_info *sync_file_info(int fd)
85*053f45beSAndroid Build Coastguard Worker {
86*053f45beSAndroid Build Coastguard Worker 	struct sync_file_info *info;
87*053f45beSAndroid Build Coastguard Worker 	struct sync_fence_info *fence_info;
88*053f45beSAndroid Build Coastguard Worker 	int err, num_fences;
89*053f45beSAndroid Build Coastguard Worker 
90*053f45beSAndroid Build Coastguard Worker 	info = calloc(1, sizeof(*info));
91*053f45beSAndroid Build Coastguard Worker 	if (info == NULL)
92*053f45beSAndroid Build Coastguard Worker 		return NULL;
93*053f45beSAndroid Build Coastguard Worker 
94*053f45beSAndroid Build Coastguard Worker 	err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
95*053f45beSAndroid Build Coastguard Worker 	if (err < 0) {
96*053f45beSAndroid Build Coastguard Worker 		free(info);
97*053f45beSAndroid Build Coastguard Worker 		return NULL;
98*053f45beSAndroid Build Coastguard Worker 	}
99*053f45beSAndroid Build Coastguard Worker 
100*053f45beSAndroid Build Coastguard Worker 	num_fences = info->num_fences;
101*053f45beSAndroid Build Coastguard Worker 
102*053f45beSAndroid Build Coastguard Worker 	if (num_fences) {
103*053f45beSAndroid Build Coastguard Worker 		info->flags = 0;
104*053f45beSAndroid Build Coastguard Worker 		info->num_fences = num_fences;
105*053f45beSAndroid Build Coastguard Worker 
106*053f45beSAndroid Build Coastguard Worker 		fence_info = calloc(num_fences, sizeof(*fence_info));
107*053f45beSAndroid Build Coastguard Worker 		if (!fence_info) {
108*053f45beSAndroid Build Coastguard Worker 			free(info);
109*053f45beSAndroid Build Coastguard Worker 			return NULL;
110*053f45beSAndroid Build Coastguard Worker 		}
111*053f45beSAndroid Build Coastguard Worker 
112*053f45beSAndroid Build Coastguard Worker 		info->sync_fence_info = (uint64_t)(unsigned long)fence_info;
113*053f45beSAndroid Build Coastguard Worker 
114*053f45beSAndroid Build Coastguard Worker 		err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
115*053f45beSAndroid Build Coastguard Worker 		if (err < 0) {
116*053f45beSAndroid Build Coastguard Worker 			free(fence_info);
117*053f45beSAndroid Build Coastguard Worker 			free(info);
118*053f45beSAndroid Build Coastguard Worker 			return NULL;
119*053f45beSAndroid Build Coastguard Worker 		}
120*053f45beSAndroid Build Coastguard Worker 	}
121*053f45beSAndroid Build Coastguard Worker 
122*053f45beSAndroid Build Coastguard Worker 	return info;
123*053f45beSAndroid Build Coastguard Worker }
124*053f45beSAndroid Build Coastguard Worker 
sync_file_info_free(struct sync_file_info * info)125*053f45beSAndroid Build Coastguard Worker static void sync_file_info_free(struct sync_file_info *info)
126*053f45beSAndroid Build Coastguard Worker {
127*053f45beSAndroid Build Coastguard Worker 	free((void *)(unsigned long)info->sync_fence_info);
128*053f45beSAndroid Build Coastguard Worker 	free(info);
129*053f45beSAndroid Build Coastguard Worker }
130*053f45beSAndroid Build Coastguard Worker 
sync_fence_size(int fd)131*053f45beSAndroid Build Coastguard Worker int sync_fence_size(int fd)
132*053f45beSAndroid Build Coastguard Worker {
133*053f45beSAndroid Build Coastguard Worker 	int count;
134*053f45beSAndroid Build Coastguard Worker 	struct sync_file_info *info = sync_file_info(fd);
135*053f45beSAndroid Build Coastguard Worker 
136*053f45beSAndroid Build Coastguard Worker 	if (!info)
137*053f45beSAndroid Build Coastguard Worker 		return 0;
138*053f45beSAndroid Build Coastguard Worker 
139*053f45beSAndroid Build Coastguard Worker 	count = info->num_fences;
140*053f45beSAndroid Build Coastguard Worker 
141*053f45beSAndroid Build Coastguard Worker 	sync_file_info_free(info);
142*053f45beSAndroid Build Coastguard Worker 
143*053f45beSAndroid Build Coastguard Worker 	return count;
144*053f45beSAndroid Build Coastguard Worker }
145*053f45beSAndroid Build Coastguard Worker 
sync_fence_count_with_status(int fd,int status)146*053f45beSAndroid Build Coastguard Worker int sync_fence_count_with_status(int fd, int status)
147*053f45beSAndroid Build Coastguard Worker {
148*053f45beSAndroid Build Coastguard Worker 	unsigned int i, count = 0;
149*053f45beSAndroid Build Coastguard Worker 	struct sync_fence_info *fence_info = NULL;
150*053f45beSAndroid Build Coastguard Worker 	struct sync_file_info *info = sync_file_info(fd);
151*053f45beSAndroid Build Coastguard Worker 
152*053f45beSAndroid Build Coastguard Worker 	if (!info)
153*053f45beSAndroid Build Coastguard Worker 		return -1;
154*053f45beSAndroid Build Coastguard Worker 
155*053f45beSAndroid Build Coastguard Worker 	fence_info = (struct sync_fence_info *)(unsigned long)info->sync_fence_info;
156*053f45beSAndroid Build Coastguard Worker 	for (i = 0 ; i < info->num_fences ; i++) {
157*053f45beSAndroid Build Coastguard Worker 		if (fence_info[i].status == status)
158*053f45beSAndroid Build Coastguard Worker 			count++;
159*053f45beSAndroid Build Coastguard Worker 	}
160*053f45beSAndroid Build Coastguard Worker 
161*053f45beSAndroid Build Coastguard Worker 	sync_file_info_free(info);
162*053f45beSAndroid Build Coastguard Worker 
163*053f45beSAndroid Build Coastguard Worker 	return count;
164*053f45beSAndroid Build Coastguard Worker }
165*053f45beSAndroid Build Coastguard Worker 
sw_sync_timeline_create(void)166*053f45beSAndroid Build Coastguard Worker int sw_sync_timeline_create(void)
167*053f45beSAndroid Build Coastguard Worker {
168*053f45beSAndroid Build Coastguard Worker 	return open("/sys/kernel/debug/sync/sw_sync", O_RDWR);
169*053f45beSAndroid Build Coastguard Worker }
170*053f45beSAndroid Build Coastguard Worker 
sw_sync_timeline_inc(int fd,unsigned int count)171*053f45beSAndroid Build Coastguard Worker int sw_sync_timeline_inc(int fd, unsigned int count)
172*053f45beSAndroid Build Coastguard Worker {
173*053f45beSAndroid Build Coastguard Worker 	__u32 arg = count;
174*053f45beSAndroid Build Coastguard Worker 
175*053f45beSAndroid Build Coastguard Worker 	return ioctl(fd, SW_SYNC_IOC_INC, &arg);
176*053f45beSAndroid Build Coastguard Worker }
177*053f45beSAndroid Build Coastguard Worker 
sw_sync_timeline_is_valid(int fd)178*053f45beSAndroid Build Coastguard Worker int sw_sync_timeline_is_valid(int fd)
179*053f45beSAndroid Build Coastguard Worker {
180*053f45beSAndroid Build Coastguard Worker 	int status;
181*053f45beSAndroid Build Coastguard Worker 
182*053f45beSAndroid Build Coastguard Worker 	if (fd == -1)
183*053f45beSAndroid Build Coastguard Worker 		return 0;
184*053f45beSAndroid Build Coastguard Worker 
185*053f45beSAndroid Build Coastguard Worker 	status = fcntl(fd, F_GETFD, 0);
186*053f45beSAndroid Build Coastguard Worker 	return (status >= 0);
187*053f45beSAndroid Build Coastguard Worker }
188*053f45beSAndroid Build Coastguard Worker 
sw_sync_timeline_destroy(int fd)189*053f45beSAndroid Build Coastguard Worker void sw_sync_timeline_destroy(int fd)
190*053f45beSAndroid Build Coastguard Worker {
191*053f45beSAndroid Build Coastguard Worker 	if (sw_sync_timeline_is_valid(fd))
192*053f45beSAndroid Build Coastguard Worker 		close(fd);
193*053f45beSAndroid Build Coastguard Worker }
194*053f45beSAndroid Build Coastguard Worker 
sw_sync_fence_create(int fd,const char * name,unsigned int value)195*053f45beSAndroid Build Coastguard Worker int sw_sync_fence_create(int fd, const char *name, unsigned int value)
196*053f45beSAndroid Build Coastguard Worker {
197*053f45beSAndroid Build Coastguard Worker 	struct sw_sync_create_fence_data data = {};
198*053f45beSAndroid Build Coastguard Worker 	int err;
199*053f45beSAndroid Build Coastguard Worker 
200*053f45beSAndroid Build Coastguard Worker 	data.value = value;
201*053f45beSAndroid Build Coastguard Worker 	strncpy(data.name, name, sizeof(data.name) - 1);
202*053f45beSAndroid Build Coastguard Worker 	data.name[sizeof(data.name) - 1] = '\0';
203*053f45beSAndroid Build Coastguard Worker 
204*053f45beSAndroid Build Coastguard Worker 	err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data);
205*053f45beSAndroid Build Coastguard Worker 	if (err < 0)
206*053f45beSAndroid Build Coastguard Worker 		return err;
207*053f45beSAndroid Build Coastguard Worker 
208*053f45beSAndroid Build Coastguard Worker 	return data.fence;
209*053f45beSAndroid Build Coastguard Worker }
210*053f45beSAndroid Build Coastguard Worker 
sw_sync_fence_is_valid(int fd)211*053f45beSAndroid Build Coastguard Worker int sw_sync_fence_is_valid(int fd)
212*053f45beSAndroid Build Coastguard Worker {
213*053f45beSAndroid Build Coastguard Worker 	/* Same code! */
214*053f45beSAndroid Build Coastguard Worker 	return sw_sync_timeline_is_valid(fd);
215*053f45beSAndroid Build Coastguard Worker }
216*053f45beSAndroid Build Coastguard Worker 
sw_sync_fence_destroy(int fd)217*053f45beSAndroid Build Coastguard Worker void sw_sync_fence_destroy(int fd)
218*053f45beSAndroid Build Coastguard Worker {
219*053f45beSAndroid Build Coastguard Worker 	if (sw_sync_fence_is_valid(fd))
220*053f45beSAndroid Build Coastguard Worker 		close(fd);
221*053f45beSAndroid Build Coastguard Worker }
222