xref: /OK3568_Linux_fs/external/linux-rga/core/rga_sync.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *  sync.c
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *   Copyright 2012 Google, Inc
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  *  Licensed under the Apache License, Version 2.0 (the "License");
7*4882a593Smuzhiyun  *  you may not use this file except in compliance with the License.
8*4882a593Smuzhiyun  *  You may obtain a copy of the License at
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  *      http://www.apache.org/licenses/LICENSE-2.0
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  *  Unless required by applicable law or agreed to in writing, software
13*4882a593Smuzhiyun  *  distributed under the License is distributed on an "AS IS" BASIS,
14*4882a593Smuzhiyun  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*4882a593Smuzhiyun  *  See the License for the specific language governing permissions and
16*4882a593Smuzhiyun  *  limitations under the License.
17*4882a593Smuzhiyun  */
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <errno.h>
20*4882a593Smuzhiyun #include <fcntl.h>
21*4882a593Smuzhiyun #include <malloc.h>
22*4882a593Smuzhiyun #include <poll.h>
23*4882a593Smuzhiyun #include <stdint.h>
24*4882a593Smuzhiyun #include <string.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #include <sys/ioctl.h>
27*4882a593Smuzhiyun #include <sys/stat.h>
28*4882a593Smuzhiyun #include <sys/types.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <linux/sync_file.h>
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun #ifndef __cplusplus
33*4882a593Smuzhiyun # include <stdatomic.h>
34*4882a593Smuzhiyun #else
35*4882a593Smuzhiyun # include <atomic>
36*4882a593Smuzhiyun # define _Atomic(X) std::atomic< X >
37*4882a593Smuzhiyun using namespace std;
38*4882a593Smuzhiyun #endif
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #include "rga_sync.h"
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /* Legacy Sync API */
43*4882a593Smuzhiyun struct sync_legacy_merge_data {
44*4882a593Smuzhiyun  int32_t fd2;
45*4882a593Smuzhiyun  char name[32];
46*4882a593Smuzhiyun  int32_t fence;
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun /**
50*4882a593Smuzhiyun  * DOC: SYNC_IOC_MERGE - merge two fences
51*4882a593Smuzhiyun  *
52*4882a593Smuzhiyun  * Takes a struct sync_merge_data.  Creates a new fence containing copies of
53*4882a593Smuzhiyun  * the sync_pts in both the calling fd and sync_merge_data.fd2.  Returns the
54*4882a593Smuzhiyun  * new fence's fd in sync_merge_data.fence
55*4882a593Smuzhiyun  *
56*4882a593Smuzhiyun  * This is the legacy version of the Sync API before the de-stage that happened
57*4882a593Smuzhiyun  * on Linux kernel 4.7.
58*4882a593Smuzhiyun  */
59*4882a593Smuzhiyun #define SYNC_IOC_LEGACY_MERGE   _IOWR(SYNC_IOC_MAGIC, 1, \
60*4882a593Smuzhiyun     struct sync_legacy_merge_data)
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun // ---------------------------------------------------------------------------
63*4882a593Smuzhiyun // Support for caching the sync uapi version.
64*4882a593Smuzhiyun //
65*4882a593Smuzhiyun // This library supports both legacy (android/staging) uapi and modern
66*4882a593Smuzhiyun // (mainline) sync uapi. Library calls first try one uapi, and if that fails,
67*4882a593Smuzhiyun // try the other. Since any given kernel only supports one uapi version, after
68*4882a593Smuzhiyun // the first successful syscall we know what the kernel supports and can skip
69*4882a593Smuzhiyun // trying the other.
70*4882a593Smuzhiyun enum uapi_version {
71*4882a593Smuzhiyun     UAPI_UNKNOWN,
72*4882a593Smuzhiyun     UAPI_MODERN,
73*4882a593Smuzhiyun     UAPI_LEGACY
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun static atomic_int g_uapi_version = ATOMIC_VAR_INIT(UAPI_UNKNOWN);
76*4882a593Smuzhiyun 
rga_strlcpy(char * dest,const char * src,size_t size)77*4882a593Smuzhiyun static size_t rga_strlcpy(char *dest, const char *src, size_t size) {
78*4882a593Smuzhiyun     size_t src_len = strlen(src);
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun     if (size) {
81*4882a593Smuzhiyun         size_t len = src_len >= size ? (size - 1) : src_len;
82*4882a593Smuzhiyun         // strncpy(dest, src, len);
83*4882a593Smuzhiyun         memcpy(dest, src, len);
84*4882a593Smuzhiyun         dest[len] = '\0';
85*4882a593Smuzhiyun     }
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun     return src_len;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun /* sync wait */
rga_sync_wait(int fd,int timeout)91*4882a593Smuzhiyun int rga_sync_wait(int fd, int timeout)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun     struct pollfd fds;
94*4882a593Smuzhiyun     int ret;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun     if (fd < 0) {
97*4882a593Smuzhiyun         errno = EINVAL;
98*4882a593Smuzhiyun         return -1;
99*4882a593Smuzhiyun     }
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun     fds.fd = fd;
102*4882a593Smuzhiyun     fds.events = POLLIN;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun     do {
105*4882a593Smuzhiyun         ret = poll(&fds, 1, timeout);
106*4882a593Smuzhiyun         if (ret > 0) {
107*4882a593Smuzhiyun             if (fds.revents & (POLLERR | POLLNVAL)) {
108*4882a593Smuzhiyun                 errno = EINVAL;
109*4882a593Smuzhiyun                 return -1;
110*4882a593Smuzhiyun             }
111*4882a593Smuzhiyun             return 0;
112*4882a593Smuzhiyun         } else if (ret == 0) {
113*4882a593Smuzhiyun             errno = ETIME;
114*4882a593Smuzhiyun             return -1;
115*4882a593Smuzhiyun         }
116*4882a593Smuzhiyun     } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun     return ret;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun /* sync merge */
legacy_sync_merge(const char * name,int fd1,int fd2)122*4882a593Smuzhiyun static int legacy_sync_merge(const char *name, int fd1, int fd2)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun     struct sync_legacy_merge_data data;
125*4882a593Smuzhiyun     int ret;
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun     data.fd2 = fd2;
128*4882a593Smuzhiyun     rga_strlcpy(data.name, name, sizeof(data.name));
129*4882a593Smuzhiyun     ret = ioctl(fd1, SYNC_IOC_LEGACY_MERGE, &data);
130*4882a593Smuzhiyun     if (ret < 0)
131*4882a593Smuzhiyun         return ret;
132*4882a593Smuzhiyun     return data.fence;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
modern_sync_merge(const char * name,int fd1,int fd2)135*4882a593Smuzhiyun static int modern_sync_merge(const char *name, int fd1, int fd2)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun     struct sync_merge_data data;
138*4882a593Smuzhiyun     int ret;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun     data.fd2 = fd2;
141*4882a593Smuzhiyun     rga_strlcpy(data.name, name, sizeof(data.name));
142*4882a593Smuzhiyun     data.flags = 0;
143*4882a593Smuzhiyun     data.pad = 0;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun     ret = ioctl(fd1, SYNC_IOC_MERGE, &data);
146*4882a593Smuzhiyun     if (ret < 0)
147*4882a593Smuzhiyun         return ret;
148*4882a593Smuzhiyun     return data.fence;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
rga_sync_merge(const char * name,int fd1,int fd2)151*4882a593Smuzhiyun int rga_sync_merge(const char *name, int fd1, int fd2)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun     int uapi;
154*4882a593Smuzhiyun     int ret;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun     uapi = atomic_load_explicit(&g_uapi_version, memory_order_acquire);
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun     if (uapi == UAPI_MODERN || uapi == UAPI_UNKNOWN) {
159*4882a593Smuzhiyun         ret = modern_sync_merge(name, fd1, fd2);
160*4882a593Smuzhiyun         if (ret >= 0 || errno != ENOTTY) {
161*4882a593Smuzhiyun             if (ret >= 0 && uapi == UAPI_UNKNOWN) {
162*4882a593Smuzhiyun                 atomic_store_explicit(&g_uapi_version, (int)UAPI_MODERN,
163*4882a593Smuzhiyun                                       memory_order_release);
164*4882a593Smuzhiyun             }
165*4882a593Smuzhiyun             return ret;
166*4882a593Smuzhiyun         }
167*4882a593Smuzhiyun     }
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun     ret = legacy_sync_merge(name, fd1, fd2);
170*4882a593Smuzhiyun     if (ret >= 0 && uapi == UAPI_UNKNOWN) {
171*4882a593Smuzhiyun         atomic_store_explicit(&g_uapi_version, (int)UAPI_LEGACY,
172*4882a593Smuzhiyun                               memory_order_release);
173*4882a593Smuzhiyun     }
174*4882a593Smuzhiyun     return ret;
175*4882a593Smuzhiyun }
176