222 lines · c
1/*2 * sync / sw_sync abstraction3 * Copyright 2015-2016 Collabora Ltd.4 *5 * Based on the implementation from the Android Open Source Project,6 *7 * Copyright 2012 Google, Inc8 *9 * Permission is hereby granted, free of charge, to any person obtaining a10 * copy of this software and associated documentation files (the "Software"),11 * to deal in the Software without restriction, including without limitation12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,13 * and/or sell copies of the Software, and to permit persons to whom the14 * Software is furnished to do so, subject to the following conditions:15 *16 * The above copyright notice and this permission notice shall be included in17 * all copies or substantial portions of the Software.18 *19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR23 * 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 OR25 * OTHER DEALINGS IN THE SOFTWARE.26 */27 28#include <fcntl.h>29#include <malloc.h>30#include <poll.h>31#include <stdint.h>32#include <string.h>33#include <unistd.h>34 35#include <sys/ioctl.h>36#include <sys/stat.h>37#include <sys/types.h>38 39#include "sync.h"40#include "sw_sync.h"41 42#include <linux/sync_file.h>43 44 45/* SW_SYNC ioctls */46struct sw_sync_create_fence_data {47 __u32 value;48 char name[32];49 __s32 fence;50};51 52#define SW_SYNC_IOC_MAGIC 'W'53#define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\54 struct sw_sync_create_fence_data)55#define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)56 57 58int sync_wait(int fd, int timeout)59{60 struct pollfd fds;61 62 fds.fd = fd;63 fds.events = POLLIN | POLLERR;64 65 return poll(&fds, 1, timeout);66}67 68int sync_merge(const char *name, int fd1, int fd2)69{70 struct sync_merge_data data = {};71 int err;72 73 data.fd2 = fd2;74 strncpy(data.name, name, sizeof(data.name) - 1);75 data.name[sizeof(data.name) - 1] = '\0';76 77 err = ioctl(fd1, SYNC_IOC_MERGE, &data);78 if (err < 0)79 return err;80 81 return data.fence;82}83 84static struct sync_file_info *sync_file_info(int fd)85{86 struct sync_file_info *info;87 struct sync_fence_info *fence_info;88 int err, num_fences;89 90 info = calloc(1, sizeof(*info));91 if (info == NULL)92 return NULL;93 94 err = ioctl(fd, SYNC_IOC_FILE_INFO, info);95 if (err < 0) {96 free(info);97 return NULL;98 }99 100 num_fences = info->num_fences;101 102 if (num_fences) {103 info->flags = 0;104 info->num_fences = num_fences;105 106 fence_info = calloc(num_fences, sizeof(*fence_info));107 if (!fence_info) {108 free(info);109 return NULL;110 }111 112 info->sync_fence_info = (uint64_t)(unsigned long)fence_info;113 114 err = ioctl(fd, SYNC_IOC_FILE_INFO, info);115 if (err < 0) {116 free(fence_info);117 free(info);118 return NULL;119 }120 }121 122 return info;123}124 125static void sync_file_info_free(struct sync_file_info *info)126{127 free((void *)(unsigned long)info->sync_fence_info);128 free(info);129}130 131int sync_fence_size(int fd)132{133 int count;134 struct sync_file_info *info = sync_file_info(fd);135 136 if (!info)137 return 0;138 139 count = info->num_fences;140 141 sync_file_info_free(info);142 143 return count;144}145 146int sync_fence_count_with_status(int fd, int status)147{148 unsigned int i, count = 0;149 struct sync_fence_info *fence_info = NULL;150 struct sync_file_info *info = sync_file_info(fd);151 152 if (!info)153 return -1;154 155 fence_info = (struct sync_fence_info *)(unsigned long)info->sync_fence_info;156 for (i = 0 ; i < info->num_fences ; i++) {157 if (fence_info[i].status == status)158 count++;159 }160 161 sync_file_info_free(info);162 163 return count;164}165 166int sw_sync_timeline_create(void)167{168 return open("/sys/kernel/debug/sync/sw_sync", O_RDWR);169}170 171int sw_sync_timeline_inc(int fd, unsigned int count)172{173 __u32 arg = count;174 175 return ioctl(fd, SW_SYNC_IOC_INC, &arg);176}177 178int sw_sync_timeline_is_valid(int fd)179{180 int status;181 182 if (fd == -1)183 return 0;184 185 status = fcntl(fd, F_GETFD, 0);186 return (status >= 0);187}188 189void sw_sync_timeline_destroy(int fd)190{191 if (sw_sync_timeline_is_valid(fd))192 close(fd);193}194 195int sw_sync_fence_create(int fd, const char *name, unsigned int value)196{197 struct sw_sync_create_fence_data data = {};198 int err;199 200 data.value = value;201 strncpy(data.name, name, sizeof(data.name) - 1);202 data.name[sizeof(data.name) - 1] = '\0';203 204 err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data);205 if (err < 0)206 return err;207 208 return data.fence;209}210 211int sw_sync_fence_is_valid(int fd)212{213 /* Same code! */214 return sw_sync_timeline_is_valid(fd);215}216 217void sw_sync_fence_destroy(int fd)218{219 if (sw_sync_fence_is_valid(fd))220 close(fd);221}222