Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/util/libsync.h
4545 views
1
/*
2
* sync abstraction
3
* Copyright 2015-2016 Collabora Ltd.
4
*
5
* Based on the implementation from the Android Open Source Project,
6
*
7
* Copyright 2012 Google, Inc
8
*
9
* Permission is hereby granted, free of charge, to any person obtaining a
10
* copy of this software and associated documentation files (the "Software"),
11
* to deal in the Software without restriction, including without limitation
12
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
* and/or sell copies of the Software, and to permit persons to whom the
14
* Software is furnished to do so, subject to the following conditions:
15
*
16
* The above copyright notice and this permission notice shall be included in
17
* all copies or substantial portions of the Software.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
* OTHER DEALINGS IN THE SOFTWARE.
26
*/
27
28
#ifndef _LIBSYNC_H
29
#define _LIBSYNC_H
30
31
#include <assert.h>
32
#include <errno.h>
33
#include <stdbool.h>
34
#include <stdint.h>
35
#include <string.h>
36
#include <sys/ioctl.h>
37
#include <sys/poll.h>
38
#include <unistd.h>
39
40
#if defined(__cplusplus)
41
extern "C" {
42
#endif
43
44
//#ifdef ANDROID
45
#if ANDROID_API_LEVEL >= 26
46
/* On Android, rely on the system's libsync instead of rolling our own
47
* sync_wait() and sync_merge(). This gives us compatibility with pre-4.7
48
* Android kernels.
49
*/
50
#include <android/sync.h>
51
52
/**
53
* Check if the fd represents a valid fence-fd.
54
*
55
* The android variant of this debug helper is implemented on top of the
56
* system's libsync for compatibility with pre-4.7 android kernels.
57
*/
58
static inline bool
59
sync_valid_fd(int fd)
60
{
61
/* sync_file_info() only available in SDK 26. */
62
#if ANDROID_API_LEVEL >= 26
63
struct sync_file_info *info = sync_file_info(fd);
64
if (!info)
65
return false;
66
sync_file_info_free(info);
67
#endif
68
return true;
69
}
70
#else
71
72
#ifndef SYNC_IOC_MERGE
73
/* duplicated from linux/sync_file.h to avoid build-time dependency
74
* on new (v4.7) kernel headers. Once distro's are mostly using
75
* something newer than v4.7 drop this and #include <linux/sync_file.h>
76
* instead.
77
*/
78
struct sync_merge_data {
79
char name[32];
80
int32_t fd2;
81
int32_t fence;
82
uint32_t flags;
83
uint32_t pad;
84
};
85
86
struct sync_file_info {
87
char name[32];
88
int32_t status;
89
uint32_t flags;
90
uint32_t num_fences;
91
uint32_t pad;
92
93
uint64_t sync_fence_info;
94
};
95
96
#define SYNC_IOC_MAGIC '>'
97
#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
98
#define SYNC_IOC_FILE_INFO _IOWR(SYNC_IOC_MAGIC, 4, struct sync_file_info)
99
#endif
100
101
102
static inline int sync_wait(int fd, int timeout)
103
{
104
struct pollfd fds = {0};
105
int ret;
106
107
fds.fd = fd;
108
fds.events = POLLIN;
109
110
do {
111
ret = poll(&fds, 1, timeout);
112
if (ret > 0) {
113
if (fds.revents & (POLLERR | POLLNVAL)) {
114
errno = EINVAL;
115
return -1;
116
}
117
return 0;
118
} else if (ret == 0) {
119
errno = ETIME;
120
return -1;
121
}
122
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
123
124
return ret;
125
}
126
127
static inline int sync_merge(const char *name, int fd1, int fd2)
128
{
129
struct sync_merge_data data = {0};
130
int ret;
131
132
data.fd2 = fd2;
133
strncpy(data.name, name, sizeof(data.name));
134
135
do {
136
ret = ioctl(fd1, SYNC_IOC_MERGE, &data);
137
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
138
139
if (ret < 0)
140
return ret;
141
142
return data.fence;
143
}
144
145
/**
146
* Check if the fd represents a valid fence-fd.
147
*/
148
static inline bool
149
sync_valid_fd(int fd)
150
{
151
struct sync_file_info info = {{0}};
152
return ioctl(fd, SYNC_IOC_FILE_INFO, &info) >= 0;
153
}
154
155
#endif /* !ANDROID */
156
157
/* accumulate fd2 into fd1. If *fd1 is not a valid fd then dup fd2,
158
* otherwise sync_merge() and close the old *fd1. This can be used
159
* to implement the pattern:
160
*
161
* init()
162
* {
163
* batch.fence_fd = -1;
164
* }
165
*
166
* // does *NOT* take ownership of fd
167
* server_sync(int fd)
168
* {
169
* if (sync_accumulate("foo", &batch.fence_fd, fd)) {
170
* ... error ...
171
* }
172
* }
173
*/
174
static inline int sync_accumulate(const char *name, int *fd1, int fd2)
175
{
176
int ret;
177
178
assert(fd2 >= 0);
179
180
if (*fd1 < 0) {
181
*fd1 = dup(fd2);
182
return 0;
183
}
184
185
ret = sync_merge(name, *fd1, fd2);
186
if (ret < 0) {
187
/* leave *fd1 as it is */
188
return ret;
189
}
190
191
close(*fd1);
192
*fd1 = ret;
193
194
return 0;
195
}
196
197
#if defined(__cplusplus)
198
}
199
#endif
200
201
#endif
202
203