18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * sync / sw_sync abstraction 38c2ecf20Sopenharmony_ci * Copyright 2015-2016 Collabora Ltd. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Based on the implementation from the Android Open Source Project, 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright 2012 Google, Inc 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 108c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 118c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 128c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 138c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 148c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 178c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 208c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 218c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 228c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 238c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 248c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 258c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include <fcntl.h> 298c2ecf20Sopenharmony_ci#include <malloc.h> 308c2ecf20Sopenharmony_ci#include <poll.h> 318c2ecf20Sopenharmony_ci#include <stdint.h> 328c2ecf20Sopenharmony_ci#include <string.h> 338c2ecf20Sopenharmony_ci#include <unistd.h> 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <sys/ioctl.h> 368c2ecf20Sopenharmony_ci#include <sys/stat.h> 378c2ecf20Sopenharmony_ci#include <sys/types.h> 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include "sync.h" 408c2ecf20Sopenharmony_ci#include "sw_sync.h" 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci#include <linux/sync_file.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* SW_SYNC ioctls */ 468c2ecf20Sopenharmony_cistruct sw_sync_create_fence_data { 478c2ecf20Sopenharmony_ci __u32 value; 488c2ecf20Sopenharmony_ci char name[32]; 498c2ecf20Sopenharmony_ci __s32 fence; 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define SW_SYNC_IOC_MAGIC 'W' 538c2ecf20Sopenharmony_ci#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ 548c2ecf20Sopenharmony_ci struct sw_sync_create_fence_data) 558c2ecf20Sopenharmony_ci#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ciint sync_wait(int fd, int timeout) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct pollfd fds; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci fds.fd = fd; 638c2ecf20Sopenharmony_ci fds.events = POLLIN | POLLERR; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci return poll(&fds, 1, timeout); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ciint sync_merge(const char *name, int fd1, int fd2) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci struct sync_merge_data data = {}; 718c2ecf20Sopenharmony_ci int err; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci data.fd2 = fd2; 748c2ecf20Sopenharmony_ci strncpy(data.name, name, sizeof(data.name) - 1); 758c2ecf20Sopenharmony_ci data.name[sizeof(data.name) - 1] = '\0'; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci err = ioctl(fd1, SYNC_IOC_MERGE, &data); 788c2ecf20Sopenharmony_ci if (err < 0) 798c2ecf20Sopenharmony_ci return err; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci return data.fence; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic struct sync_file_info *sync_file_info(int fd) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci struct sync_file_info *info; 878c2ecf20Sopenharmony_ci struct sync_fence_info *fence_info; 888c2ecf20Sopenharmony_ci int err, num_fences; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci info = calloc(1, sizeof(*info)); 918c2ecf20Sopenharmony_ci if (info == NULL) 928c2ecf20Sopenharmony_ci return NULL; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci err = ioctl(fd, SYNC_IOC_FILE_INFO, info); 958c2ecf20Sopenharmony_ci if (err < 0) { 968c2ecf20Sopenharmony_ci free(info); 978c2ecf20Sopenharmony_ci return NULL; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci num_fences = info->num_fences; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (num_fences) { 1038c2ecf20Sopenharmony_ci info->flags = 0; 1048c2ecf20Sopenharmony_ci info->num_fences = num_fences; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci fence_info = calloc(num_fences, sizeof(*fence_info)); 1078c2ecf20Sopenharmony_ci if (!fence_info) { 1088c2ecf20Sopenharmony_ci free(info); 1098c2ecf20Sopenharmony_ci return NULL; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci info->sync_fence_info = (uint64_t)(unsigned long)fence_info; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci err = ioctl(fd, SYNC_IOC_FILE_INFO, info); 1158c2ecf20Sopenharmony_ci if (err < 0) { 1168c2ecf20Sopenharmony_ci free(fence_info); 1178c2ecf20Sopenharmony_ci free(info); 1188c2ecf20Sopenharmony_ci return NULL; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci } 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci return info; 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic void sync_file_info_free(struct sync_file_info *info) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci free((void *)(unsigned long)info->sync_fence_info); 1288c2ecf20Sopenharmony_ci free(info); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ciint sync_fence_size(int fd) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci int count; 1348c2ecf20Sopenharmony_ci struct sync_file_info *info = sync_file_info(fd); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (!info) 1378c2ecf20Sopenharmony_ci return 0; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci count = info->num_fences; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci sync_file_info_free(info); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return count; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciint sync_fence_count_with_status(int fd, int status) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci unsigned int i, count = 0; 1498c2ecf20Sopenharmony_ci struct sync_fence_info *fence_info = NULL; 1508c2ecf20Sopenharmony_ci struct sync_file_info *info = sync_file_info(fd); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci if (!info) 1538c2ecf20Sopenharmony_ci return -1; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci fence_info = (struct sync_fence_info *)(unsigned long)info->sync_fence_info; 1568c2ecf20Sopenharmony_ci for (i = 0 ; i < info->num_fences ; i++) { 1578c2ecf20Sopenharmony_ci if (fence_info[i].status == status) 1588c2ecf20Sopenharmony_ci count++; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci sync_file_info_free(info); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci return count; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ciint sw_sync_timeline_create(void) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci return open("/sys/kernel/debug/sync/sw_sync", O_RDWR); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciint sw_sync_timeline_inc(int fd, unsigned int count) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci __u32 arg = count; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci return ioctl(fd, SW_SYNC_IOC_INC, &arg); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ciint sw_sync_timeline_is_valid(int fd) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci int status; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (fd == -1) 1838c2ecf20Sopenharmony_ci return 0; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci status = fcntl(fd, F_GETFD, 0); 1868c2ecf20Sopenharmony_ci return (status >= 0); 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_civoid sw_sync_timeline_destroy(int fd) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci if (sw_sync_timeline_is_valid(fd)) 1928c2ecf20Sopenharmony_ci close(fd); 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ciint sw_sync_fence_create(int fd, const char *name, unsigned int value) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci struct sw_sync_create_fence_data data = {}; 1988c2ecf20Sopenharmony_ci int err; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci data.value = value; 2018c2ecf20Sopenharmony_ci strncpy(data.name, name, sizeof(data.name) - 1); 2028c2ecf20Sopenharmony_ci data.name[sizeof(data.name) - 1] = '\0'; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data); 2058c2ecf20Sopenharmony_ci if (err < 0) 2068c2ecf20Sopenharmony_ci return err; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci return data.fence; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ciint sw_sync_fence_is_valid(int fd) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci /* Same code! */ 2148c2ecf20Sopenharmony_ci return sw_sync_timeline_is_valid(fd); 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_civoid sw_sync_fence_destroy(int fd) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci if (sw_sync_fence_is_valid(fd)) 2208c2ecf20Sopenharmony_ci close(fd); 2218c2ecf20Sopenharmony_ci} 222