summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Hall2017-02-18 23:51:04 -0600
committerJesse Hall2017-03-08 19:34:14 -0600
commit6cd0fc56c0a2cb8fdf897f49f013f86dc698d793 (patch)
tree95b08eab695324bf4b9ba22c3940857ff74e5097 /libsync/sync.c
parentdec150ff58e0c48fc96c9e0222bda6c2afd23869 (diff)
downloadplatform-system-core-6cd0fc56c0a2cb8fdf897f49f013f86dc698d793.tar.gz
platform-system-core-6cd0fc56c0a2cb8fdf897f49f013f86dc698d793.tar.xz
platform-system-core-6cd0fc56c0a2cb8fdf897f49f013f86dc698d793.zip
sync: Cache knowledge of kernel uapi version
Previously all libsync calls would try first the modern/mainline uapi and if that failed try the legacy uapi, or vice versa. This is inefficient, and confusing when looking at strace. With this change, after the first successful syscall, libsync know's what uapi version the kernel supports, and will only try that version in the future. Test: sync-unit-tests on bullhead Change-Id: I8b5de0194da0cfc6c080c0180318e16bb673d3c9
Diffstat (limited to 'libsync/sync.c')
-rw-r--r--libsync/sync.c116
1 files changed, 95 insertions, 21 deletions
diff --git a/libsync/sync.c b/libsync/sync.c
index 27dab832f..baeccda47 100644
--- a/libsync/sync.c
+++ b/libsync/sync.c
@@ -16,12 +16,13 @@
16 * limitations under the License. 16 * limitations under the License.
17 */ 17 */
18 18
19#include <errno.h>
19#include <fcntl.h> 20#include <fcntl.h>
20#include <malloc.h> 21#include <malloc.h>
22#include <poll.h>
23#include <stdatomic.h>
21#include <stdint.h> 24#include <stdint.h>
22#include <string.h> 25#include <string.h>
23#include <errno.h>
24#include <poll.h>
25 26
26#include <sys/ioctl.h> 27#include <sys/ioctl.h>
27#include <sys/stat.h> 28#include <sys/stat.h>
@@ -79,6 +80,24 @@ struct sw_sync_create_fence_data {
79#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0, struct sw_sync_create_fence_data) 80#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0, struct sw_sync_create_fence_data)
80#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) 81#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
81 82
83// ---------------------------------------------------------------------------
84// Support for caching the sync uapi version.
85//
86// This library supports both legacy (android/staging) uapi and modern
87// (mainline) sync uapi. Library calls first try one uapi, and if that fails,
88// try the other. Since any given kernel only supports one uapi version, after
89// the first successful syscall we know what the kernel supports and can skip
90// trying the other.
91
92enum uapi_version {
93 UAPI_UNKNOWN,
94 UAPI_MODERN,
95 UAPI_LEGACY
96};
97static atomic_int g_uapi_version = ATOMIC_VAR_INIT(UAPI_UNKNOWN);
98
99// ---------------------------------------------------------------------------
100
82int sync_wait(int fd, int timeout) 101int sync_wait(int fd, int timeout)
83{ 102{
84 struct pollfd fds; 103 struct pollfd fds;
@@ -109,9 +128,21 @@ int sync_wait(int fd, int timeout)
109 return ret; 128 return ret;
110} 129}
111 130
112int sync_merge(const char *name, int fd1, int fd2) 131static int legacy_sync_merge(const char *name, int fd1, int fd2)
132{
133 struct sync_legacy_merge_data data;
134 int ret;
135
136 data.fd2 = fd2;
137 strlcpy(data.name, name, sizeof(data.name));
138 ret = ioctl(fd1, SYNC_IOC_LEGACY_MERGE, &data);
139 if (ret < 0)
140 return ret;
141 return data.fence;
142}
143
144static int modern_sync_merge(const char *name, int fd1, int fd2)
113{ 145{
114 struct sync_legacy_merge_data legacy_data;
115 struct sync_merge_data data; 146 struct sync_merge_data data;
116 int ret; 147 int ret;
117 148
@@ -121,20 +152,35 @@ int sync_merge(const char *name, int fd1, int fd2)
121 data.pad = 0; 152 data.pad = 0;
122 153
123 ret = ioctl(fd1, SYNC_IOC_MERGE, &data); 154 ret = ioctl(fd1, SYNC_IOC_MERGE, &data);
124 if (ret < 0 && errno == ENOTTY) { 155 if (ret < 0)
125 legacy_data.fd2 = fd2; 156 return ret;
126 strlcpy(legacy_data.name, name, sizeof(legacy_data.name)); 157 return data.fence;
158}
127 159
128 ret = ioctl(fd1, SYNC_IOC_LEGACY_MERGE, &legacy_data); 160int sync_merge(const char *name, int fd1, int fd2)
129 if (ret < 0) 161{
130 return ret; 162 int uapi;
163 int ret;
131 164
132 return legacy_data.fence; 165 uapi = atomic_load_explicit(&g_uapi_version, memory_order_acquire);
133 } else if (ret < 0) { 166
134 return ret; 167 if (uapi == UAPI_MODERN || uapi == UAPI_UNKNOWN) {
168 ret = modern_sync_merge(name, fd1, fd2);
169 if (ret >= 0 || errno != ENOTTY) {
170 if (ret >= 0 && uapi == UAPI_UNKNOWN) {
171 atomic_store_explicit(&g_uapi_version, UAPI_MODERN,
172 memory_order_release);
173 }
174 return ret;
175 }
135 } 176 }
136 177
137 return data.fence; 178 ret = legacy_sync_merge(name, fd1, fd2);
179 if (ret >= 0 && uapi == UAPI_UNKNOWN) {
180 atomic_store_explicit(&g_uapi_version, UAPI_LEGACY,
181 memory_order_release);
182 }
183 return ret;
138} 184}
139 185
140static struct sync_fence_info_data *legacy_sync_fence_info(int fd) 186static struct sync_fence_info_data *legacy_sync_fence_info(int fd)
@@ -255,15 +301,29 @@ static struct sync_file_info* legacy_fence_info_to_sync_file_info(
255struct sync_fence_info_data *sync_fence_info(int fd) 301struct sync_fence_info_data *sync_fence_info(int fd)
256{ 302{
257 struct sync_fence_info_data *legacy_info; 303 struct sync_fence_info_data *legacy_info;
304 int uapi;
258 305
259 legacy_info = legacy_sync_fence_info(fd); 306 uapi = atomic_load_explicit(&g_uapi_version, memory_order_acquire);
260 if (legacy_info || errno != ENOTTY) 307
261 return legacy_info; 308 if (uapi == UAPI_LEGACY || uapi == UAPI_UNKNOWN) {
309 legacy_info = legacy_sync_fence_info(fd);
310 if (legacy_info || errno != ENOTTY) {
311 if (legacy_info && uapi == UAPI_UNKNOWN) {
312 atomic_store_explicit(&g_uapi_version, UAPI_LEGACY,
313 memory_order_release);
314 }
315 return legacy_info;
316 }
317 }
262 318
263 struct sync_file_info* file_info; 319 struct sync_file_info* file_info;
264 file_info = modern_sync_file_info(fd); 320 file_info = modern_sync_file_info(fd);
265 if (!file_info) 321 if (!file_info)
266 return NULL; 322 return NULL;
323 if (uapi == UAPI_UNKNOWN) {
324 atomic_store_explicit(&g_uapi_version, UAPI_MODERN,
325 memory_order_release);
326 }
267 legacy_info = sync_file_info_to_legacy_fence_info(file_info); 327 legacy_info = sync_file_info_to_legacy_fence_info(file_info);
268 sync_file_info_free(file_info); 328 sync_file_info_free(file_info);
269 return legacy_info; 329 return legacy_info;
@@ -272,15 +332,29 @@ struct sync_fence_info_data *sync_fence_info(int fd)
272struct sync_file_info* sync_file_info(int32_t fd) 332struct sync_file_info* sync_file_info(int32_t fd)
273{ 333{
274 struct sync_file_info *info; 334 struct sync_file_info *info;
275 struct sync_fence_info_data *legacy_info; 335 int uapi;
276 336
277 info = modern_sync_file_info(fd); 337 uapi = atomic_load_explicit(&g_uapi_version, memory_order_acquire);
278 if (info || errno != ENOTTY)
279 return info;
280 338
339 if (uapi == UAPI_MODERN || uapi == UAPI_UNKNOWN) {
340 info = modern_sync_file_info(fd);
341 if (info || errno != ENOTTY) {
342 if (info && uapi == UAPI_UNKNOWN) {
343 atomic_store_explicit(&g_uapi_version, UAPI_MODERN,
344 memory_order_release);
345 }
346 return info;
347 }
348 }
349
350 struct sync_fence_info_data *legacy_info;
281 legacy_info = legacy_sync_fence_info(fd); 351 legacy_info = legacy_sync_fence_info(fd);
282 if (!legacy_info) 352 if (!legacy_info)
283 return NULL; 353 return NULL;
354 if (uapi == UAPI_UNKNOWN) {
355 atomic_store_explicit(&g_uapi_version, UAPI_LEGACY,
356 memory_order_release);
357 }
284 info = legacy_fence_info_to_sync_file_info(legacy_info); 358 info = legacy_fence_info_to_sync_file_info(legacy_info);
285 sync_fence_info_free(legacy_info); 359 sync_fence_info_free(legacy_info);
286 return info; 360 return info;