3 * Copyright 2015-2016 Collabora Ltd.
5 * Based on the implementation from the Android Open Source Project,
7 * Copyright 2012 Google, Inc
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:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
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.
35 #include <sys/ioctl.h>
39 #if defined(__cplusplus)
43 #ifndef SYNC_IOC_MERGE
44 /* duplicated from linux/sync_file.h to avoid build-time dependency
45 * on new (v4.7) kernel headers. Once distro's are mostly using
46 * something newer than v4.7 drop this and #include <linux/sync_file.h>
49 struct sync_merge_data
{
56 #define SYNC_IOC_MAGIC '>'
57 #define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
61 static inline int sync_wait(int fd
, int timeout
)
63 struct pollfd fds
= {0};
70 ret
= poll(&fds
, 1, timeout
);
72 if (fds
.revents
& (POLLERR
| POLLNVAL
)) {
77 } else if (ret
== 0) {
81 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
86 static inline int sync_merge(const char *name
, int fd1
, int fd2
)
88 struct sync_merge_data data
= {0};
92 strncpy(data
.name
, name
, sizeof(data
.name
));
95 ret
= ioctl(fd1
, SYNC_IOC_MERGE
, &data
);
96 } while (ret
== -1 && (errno
== EINTR
|| errno
== EAGAIN
));
104 /* accumulate fd2 into fd1. If *fd1 is not a valid fd then dup fd2,
105 * otherwise sync_merge() and close the old *fd1. This can be used
106 * to implement the pattern:
110 * batch.fence_fd = -1;
113 * // does *NOT* take ownership of fd
114 * server_sync(int fd)
116 * if (sync_accumulate("foo", &batch.fence_fd, fd)) {
121 static inline int sync_accumulate(const char *name
, int *fd1
, int fd2
)
132 ret
= sync_merge(name
, *fd1
, fd2
);
134 /* leave *fd1 as it is */
144 #if defined(__cplusplus)