xref: /aosp_15_r20/external/libdrm/libsync.h (revision 7688df22e49036ff52a766b7101da3a49edadb8c)
1*7688df22SAndroid Build Coastguard Worker /*
2*7688df22SAndroid Build Coastguard Worker  *  sync abstraction
3*7688df22SAndroid Build Coastguard Worker  *  Copyright 2015-2016 Collabora Ltd.
4*7688df22SAndroid Build Coastguard Worker  *
5*7688df22SAndroid Build Coastguard Worker  *  Based on the implementation from the Android Open Source Project,
6*7688df22SAndroid Build Coastguard Worker  *
7*7688df22SAndroid Build Coastguard Worker  *  Copyright 2012 Google, Inc
8*7688df22SAndroid Build Coastguard Worker  *
9*7688df22SAndroid Build Coastguard Worker  *  Permission is hereby granted, free of charge, to any person obtaining a
10*7688df22SAndroid Build Coastguard Worker  *  copy of this software and associated documentation files (the "Software"),
11*7688df22SAndroid Build Coastguard Worker  *  to deal in the Software without restriction, including without limitation
12*7688df22SAndroid Build Coastguard Worker  *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
13*7688df22SAndroid Build Coastguard Worker  *  and/or sell copies of the Software, and to permit persons to whom the
14*7688df22SAndroid Build Coastguard Worker  *  Software is furnished to do so, subject to the following conditions:
15*7688df22SAndroid Build Coastguard Worker  *
16*7688df22SAndroid Build Coastguard Worker  *  The above copyright notice and this permission notice shall be included in
17*7688df22SAndroid Build Coastguard Worker  *  all copies or substantial portions of the Software.
18*7688df22SAndroid Build Coastguard Worker  *
19*7688df22SAndroid Build Coastguard Worker  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20*7688df22SAndroid Build Coastguard Worker  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21*7688df22SAndroid Build Coastguard Worker  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22*7688df22SAndroid Build Coastguard Worker  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23*7688df22SAndroid Build Coastguard Worker  *  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24*7688df22SAndroid Build Coastguard Worker  *  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25*7688df22SAndroid Build Coastguard Worker  *  OTHER DEALINGS IN THE SOFTWARE.
26*7688df22SAndroid Build Coastguard Worker  */
27*7688df22SAndroid Build Coastguard Worker 
28*7688df22SAndroid Build Coastguard Worker #ifndef _LIBSYNC_H
29*7688df22SAndroid Build Coastguard Worker #define _LIBSYNC_H
30*7688df22SAndroid Build Coastguard Worker 
31*7688df22SAndroid Build Coastguard Worker #include <assert.h>
32*7688df22SAndroid Build Coastguard Worker #include <errno.h>
33*7688df22SAndroid Build Coastguard Worker #include <stdint.h>
34*7688df22SAndroid Build Coastguard Worker #include <string.h>
35*7688df22SAndroid Build Coastguard Worker #include <sys/ioctl.h>
36*7688df22SAndroid Build Coastguard Worker #include <poll.h>
37*7688df22SAndroid Build Coastguard Worker #include <unistd.h>
38*7688df22SAndroid Build Coastguard Worker 
39*7688df22SAndroid Build Coastguard Worker #if defined(__cplusplus)
40*7688df22SAndroid Build Coastguard Worker extern "C" {
41*7688df22SAndroid Build Coastguard Worker #endif
42*7688df22SAndroid Build Coastguard Worker 
43*7688df22SAndroid Build Coastguard Worker #ifndef SYNC_IOC_MERGE
44*7688df22SAndroid Build Coastguard Worker /* duplicated from linux/sync_file.h to avoid build-time dependency
45*7688df22SAndroid Build Coastguard Worker  * on new (v4.7) kernel headers.  Once distro's are mostly using
46*7688df22SAndroid Build Coastguard Worker  * something newer than v4.7 drop this and #include <linux/sync_file.h>
47*7688df22SAndroid Build Coastguard Worker  * instead.
48*7688df22SAndroid Build Coastguard Worker  */
49*7688df22SAndroid Build Coastguard Worker struct sync_merge_data {
50*7688df22SAndroid Build Coastguard Worker 	char	name[32];
51*7688df22SAndroid Build Coastguard Worker 	int32_t	fd2;
52*7688df22SAndroid Build Coastguard Worker 	int32_t	fence;
53*7688df22SAndroid Build Coastguard Worker 	uint32_t	flags;
54*7688df22SAndroid Build Coastguard Worker 	uint32_t	pad;
55*7688df22SAndroid Build Coastguard Worker };
56*7688df22SAndroid Build Coastguard Worker #define SYNC_IOC_MAGIC		'>'
57*7688df22SAndroid Build Coastguard Worker #define SYNC_IOC_MERGE		_IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
58*7688df22SAndroid Build Coastguard Worker #endif
59*7688df22SAndroid Build Coastguard Worker 
60*7688df22SAndroid Build Coastguard Worker 
sync_wait(int fd,int timeout)61*7688df22SAndroid Build Coastguard Worker static inline int sync_wait(int fd, int timeout)
62*7688df22SAndroid Build Coastguard Worker {
63*7688df22SAndroid Build Coastguard Worker 	struct pollfd fds = {0};
64*7688df22SAndroid Build Coastguard Worker 	int ret;
65*7688df22SAndroid Build Coastguard Worker 
66*7688df22SAndroid Build Coastguard Worker 	fds.fd = fd;
67*7688df22SAndroid Build Coastguard Worker 	fds.events = POLLIN;
68*7688df22SAndroid Build Coastguard Worker 
69*7688df22SAndroid Build Coastguard Worker 	do {
70*7688df22SAndroid Build Coastguard Worker 		ret = poll(&fds, 1, timeout);
71*7688df22SAndroid Build Coastguard Worker 		if (ret > 0) {
72*7688df22SAndroid Build Coastguard Worker 			if (fds.revents & (POLLERR | POLLNVAL)) {
73*7688df22SAndroid Build Coastguard Worker 				errno = EINVAL;
74*7688df22SAndroid Build Coastguard Worker 				return -1;
75*7688df22SAndroid Build Coastguard Worker 			}
76*7688df22SAndroid Build Coastguard Worker 			return 0;
77*7688df22SAndroid Build Coastguard Worker 		} else if (ret == 0) {
78*7688df22SAndroid Build Coastguard Worker 			errno = ETIME;
79*7688df22SAndroid Build Coastguard Worker 			return -1;
80*7688df22SAndroid Build Coastguard Worker 		}
81*7688df22SAndroid Build Coastguard Worker 	} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
82*7688df22SAndroid Build Coastguard Worker 
83*7688df22SAndroid Build Coastguard Worker 	return ret;
84*7688df22SAndroid Build Coastguard Worker }
85*7688df22SAndroid Build Coastguard Worker 
sync_merge(const char * name,int fd1,int fd2)86*7688df22SAndroid Build Coastguard Worker static inline int sync_merge(const char *name, int fd1, int fd2)
87*7688df22SAndroid Build Coastguard Worker {
88*7688df22SAndroid Build Coastguard Worker 	struct sync_merge_data data = {0};
89*7688df22SAndroid Build Coastguard Worker 	int ret;
90*7688df22SAndroid Build Coastguard Worker 
91*7688df22SAndroid Build Coastguard Worker 	data.fd2 = fd2;
92*7688df22SAndroid Build Coastguard Worker 	strncpy(data.name, name, sizeof(data.name));
93*7688df22SAndroid Build Coastguard Worker 
94*7688df22SAndroid Build Coastguard Worker 	do {
95*7688df22SAndroid Build Coastguard Worker 		ret = ioctl(fd1, SYNC_IOC_MERGE, &data);
96*7688df22SAndroid Build Coastguard Worker 	} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
97*7688df22SAndroid Build Coastguard Worker 
98*7688df22SAndroid Build Coastguard Worker 	if (ret < 0)
99*7688df22SAndroid Build Coastguard Worker 		return ret;
100*7688df22SAndroid Build Coastguard Worker 
101*7688df22SAndroid Build Coastguard Worker 	return data.fence;
102*7688df22SAndroid Build Coastguard Worker }
103*7688df22SAndroid Build Coastguard Worker 
104*7688df22SAndroid Build Coastguard Worker /* accumulate fd2 into fd1.  If *fd1 is not a valid fd then dup fd2,
105*7688df22SAndroid Build Coastguard Worker  * otherwise sync_merge() and close the old *fd1.  This can be used
106*7688df22SAndroid Build Coastguard Worker  * to implement the pattern:
107*7688df22SAndroid Build Coastguard Worker  *
108*7688df22SAndroid Build Coastguard Worker  *    init()
109*7688df22SAndroid Build Coastguard Worker  *    {
110*7688df22SAndroid Build Coastguard Worker  *       batch.fence_fd = -1;
111*7688df22SAndroid Build Coastguard Worker  *    }
112*7688df22SAndroid Build Coastguard Worker  *
113*7688df22SAndroid Build Coastguard Worker  *    // does *NOT* take ownership of fd
114*7688df22SAndroid Build Coastguard Worker  *    server_sync(int fd)
115*7688df22SAndroid Build Coastguard Worker  *    {
116*7688df22SAndroid Build Coastguard Worker  *       if (sync_accumulate("foo", &batch.fence_fd, fd)) {
117*7688df22SAndroid Build Coastguard Worker  *          ... error ...
118*7688df22SAndroid Build Coastguard Worker  *       }
119*7688df22SAndroid Build Coastguard Worker  *    }
120*7688df22SAndroid Build Coastguard Worker  */
sync_accumulate(const char * name,int * fd1,int fd2)121*7688df22SAndroid Build Coastguard Worker static inline int sync_accumulate(const char *name, int *fd1, int fd2)
122*7688df22SAndroid Build Coastguard Worker {
123*7688df22SAndroid Build Coastguard Worker 	int ret;
124*7688df22SAndroid Build Coastguard Worker 
125*7688df22SAndroid Build Coastguard Worker 	assert(fd2 >= 0);
126*7688df22SAndroid Build Coastguard Worker 
127*7688df22SAndroid Build Coastguard Worker 	if (*fd1 < 0) {
128*7688df22SAndroid Build Coastguard Worker 		*fd1 = dup(fd2);
129*7688df22SAndroid Build Coastguard Worker 		return 0;
130*7688df22SAndroid Build Coastguard Worker 	}
131*7688df22SAndroid Build Coastguard Worker 
132*7688df22SAndroid Build Coastguard Worker 	ret = sync_merge(name, *fd1, fd2);
133*7688df22SAndroid Build Coastguard Worker 	if (ret < 0) {
134*7688df22SAndroid Build Coastguard Worker 		/* leave *fd1 as it is */
135*7688df22SAndroid Build Coastguard Worker 		return ret;
136*7688df22SAndroid Build Coastguard Worker 	}
137*7688df22SAndroid Build Coastguard Worker 
138*7688df22SAndroid Build Coastguard Worker 	close(*fd1);
139*7688df22SAndroid Build Coastguard Worker 	*fd1 = ret;
140*7688df22SAndroid Build Coastguard Worker 
141*7688df22SAndroid Build Coastguard Worker 	return 0;
142*7688df22SAndroid Build Coastguard Worker }
143*7688df22SAndroid Build Coastguard Worker 
144*7688df22SAndroid Build Coastguard Worker #if defined(__cplusplus)
145*7688df22SAndroid Build Coastguard Worker }
146*7688df22SAndroid Build Coastguard Worker #endif
147*7688df22SAndroid Build Coastguard Worker 
148*7688df22SAndroid Build Coastguard Worker #endif
149