1d722e3fbSopenharmony_ci/* 2d722e3fbSopenharmony_ci * sync abstraction 3d722e3fbSopenharmony_ci * Copyright 2015-2016 Collabora Ltd. 4d722e3fbSopenharmony_ci * 5d722e3fbSopenharmony_ci * Based on the implementation from the Android Open Source Project, 6d722e3fbSopenharmony_ci * 7d722e3fbSopenharmony_ci * Copyright 2012 Google, Inc 8d722e3fbSopenharmony_ci * 9d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 10d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"), 11d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation 12d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 14d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions: 15d722e3fbSopenharmony_ci * 16d722e3fbSopenharmony_ci * The above copyright notice and this permission notice shall be included in 17d722e3fbSopenharmony_ci * all copies or substantial portions of the Software. 18d722e3fbSopenharmony_ci * 19d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22d722e3fbSopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 26d722e3fbSopenharmony_ci */ 27d722e3fbSopenharmony_ci 28d722e3fbSopenharmony_ci#ifndef _LIBSYNC_H 29d722e3fbSopenharmony_ci#define _LIBSYNC_H 30d722e3fbSopenharmony_ci 31d722e3fbSopenharmony_ci#include <assert.h> 32d722e3fbSopenharmony_ci#include <errno.h> 33d722e3fbSopenharmony_ci#include <stdint.h> 34d722e3fbSopenharmony_ci#include <string.h> 35d722e3fbSopenharmony_ci#include <sys/ioctl.h> 36d722e3fbSopenharmony_ci#include <sys/poll.h> 37d722e3fbSopenharmony_ci#include <unistd.h> 38d722e3fbSopenharmony_ci 39d722e3fbSopenharmony_ci#if defined(__cplusplus) 40d722e3fbSopenharmony_ciextern "C" { 41d722e3fbSopenharmony_ci#endif 42d722e3fbSopenharmony_ci 43d722e3fbSopenharmony_ci#ifndef SYNC_IOC_MERGE 44d722e3fbSopenharmony_ci/* duplicated from linux/sync_file.h to avoid build-time dependency 45d722e3fbSopenharmony_ci * on new (v4.7) kernel headers. Once distro's are mostly using 46d722e3fbSopenharmony_ci * something newer than v4.7 drop this and #include <linux/sync_file.h> 47d722e3fbSopenharmony_ci * instead. 48d722e3fbSopenharmony_ci */ 49d722e3fbSopenharmony_cistruct sync_merge_data { 50d722e3fbSopenharmony_ci char name[32]; 51d722e3fbSopenharmony_ci int32_t fd2; 52d722e3fbSopenharmony_ci int32_t fence; 53d722e3fbSopenharmony_ci uint32_t flags; 54d722e3fbSopenharmony_ci uint32_t pad; 55d722e3fbSopenharmony_ci}; 56d722e3fbSopenharmony_ci#define SYNC_IOC_MAGIC '>' 57d722e3fbSopenharmony_ci#define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) 58d722e3fbSopenharmony_ci#endif 59d722e3fbSopenharmony_ci 60d722e3fbSopenharmony_ci 61d722e3fbSopenharmony_cistatic inline int sync_wait(int fd, int timeout) 62d722e3fbSopenharmony_ci{ 63d722e3fbSopenharmony_ci struct pollfd fds = {0}; 64d722e3fbSopenharmony_ci int ret; 65d722e3fbSopenharmony_ci 66d722e3fbSopenharmony_ci fds.fd = fd; 67d722e3fbSopenharmony_ci fds.events = POLLIN; 68d722e3fbSopenharmony_ci 69d722e3fbSopenharmony_ci do { 70d722e3fbSopenharmony_ci ret = poll(&fds, 1, timeout); 71d722e3fbSopenharmony_ci if (ret > 0) { 72d722e3fbSopenharmony_ci if (fds.revents & (POLLERR | POLLNVAL)) { 73d722e3fbSopenharmony_ci errno = EINVAL; 74d722e3fbSopenharmony_ci return -1; 75d722e3fbSopenharmony_ci } 76d722e3fbSopenharmony_ci return 0; 77d722e3fbSopenharmony_ci } else if (ret == 0) { 78d722e3fbSopenharmony_ci errno = ETIME; 79d722e3fbSopenharmony_ci return -1; 80d722e3fbSopenharmony_ci } 81d722e3fbSopenharmony_ci } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 82d722e3fbSopenharmony_ci 83d722e3fbSopenharmony_ci return ret; 84d722e3fbSopenharmony_ci} 85d722e3fbSopenharmony_ci 86d722e3fbSopenharmony_cistatic inline int sync_merge(const char *name, int fd1, int fd2) 87d722e3fbSopenharmony_ci{ 88d722e3fbSopenharmony_ci struct sync_merge_data data = {0}; 89d722e3fbSopenharmony_ci int ret; 90d722e3fbSopenharmony_ci 91d722e3fbSopenharmony_ci data.fd2 = fd2; 92d722e3fbSopenharmony_ci strncpy(data.name, name, sizeof(data.name)); 93d722e3fbSopenharmony_ci 94d722e3fbSopenharmony_ci do { 95d722e3fbSopenharmony_ci ret = ioctl(fd1, SYNC_IOC_MERGE, &data); 96d722e3fbSopenharmony_ci } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 97d722e3fbSopenharmony_ci 98d722e3fbSopenharmony_ci if (ret < 0) 99d722e3fbSopenharmony_ci return ret; 100d722e3fbSopenharmony_ci 101d722e3fbSopenharmony_ci return data.fence; 102d722e3fbSopenharmony_ci} 103d722e3fbSopenharmony_ci 104d722e3fbSopenharmony_ci/* accumulate fd2 into fd1. If *fd1 is not a valid fd then dup fd2, 105d722e3fbSopenharmony_ci * otherwise sync_merge() and close the old *fd1. This can be used 106d722e3fbSopenharmony_ci * to implement the pattern: 107d722e3fbSopenharmony_ci * 108d722e3fbSopenharmony_ci * init() 109d722e3fbSopenharmony_ci * { 110d722e3fbSopenharmony_ci * batch.fence_fd = -1; 111d722e3fbSopenharmony_ci * } 112d722e3fbSopenharmony_ci * 113d722e3fbSopenharmony_ci * // does *NOT* take ownership of fd 114d722e3fbSopenharmony_ci * server_sync(int fd) 115d722e3fbSopenharmony_ci * { 116d722e3fbSopenharmony_ci * if (sync_accumulate("foo", &batch.fence_fd, fd)) { 117d722e3fbSopenharmony_ci * ... error ... 118d722e3fbSopenharmony_ci * } 119d722e3fbSopenharmony_ci * } 120d722e3fbSopenharmony_ci */ 121d722e3fbSopenharmony_cistatic inline int sync_accumulate(const char *name, int *fd1, int fd2) 122d722e3fbSopenharmony_ci{ 123d722e3fbSopenharmony_ci int ret; 124d722e3fbSopenharmony_ci 125d722e3fbSopenharmony_ci assert(fd2 >= 0); 126d722e3fbSopenharmony_ci 127d722e3fbSopenharmony_ci if (*fd1 < 0) { 128d722e3fbSopenharmony_ci *fd1 = dup(fd2); 129d722e3fbSopenharmony_ci return 0; 130d722e3fbSopenharmony_ci } 131d722e3fbSopenharmony_ci 132d722e3fbSopenharmony_ci ret = sync_merge(name, *fd1, fd2); 133d722e3fbSopenharmony_ci if (ret < 0) { 134d722e3fbSopenharmony_ci /* leave *fd1 as it is */ 135d722e3fbSopenharmony_ci return ret; 136d722e3fbSopenharmony_ci } 137d722e3fbSopenharmony_ci 138d722e3fbSopenharmony_ci close(*fd1); 139d722e3fbSopenharmony_ci *fd1 = ret; 140d722e3fbSopenharmony_ci 141d722e3fbSopenharmony_ci return 0; 142d722e3fbSopenharmony_ci} 143d722e3fbSopenharmony_ci 144d722e3fbSopenharmony_ci#if defined(__cplusplus) 145d722e3fbSopenharmony_ci} 146d722e3fbSopenharmony_ci#endif 147d722e3fbSopenharmony_ci 148d722e3fbSopenharmony_ci#endif 149