brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · 7741c05 Raw
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