Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *  sync / sw_sync abstraction
0003  *  Copyright 2015-2016 Collabora Ltd.
0004  *
0005  *  Based on the implementation from the Android Open Source Project,
0006  *
0007  *  Copyright 2012 Google, Inc
0008  *
0009  *  Permission is hereby granted, free of charge, to any person obtaining a
0010  *  copy of this software and associated documentation files (the "Software"),
0011  *  to deal in the Software without restriction, including without limitation
0012  *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
0013  *  and/or sell copies of the Software, and to permit persons to whom the
0014  *  Software is furnished to do so, subject to the following conditions:
0015  *
0016  *  The above copyright notice and this permission notice shall be included in
0017  *  all copies or substantial portions of the Software.
0018  *
0019  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0020  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0021  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
0022  *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
0023  *  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0024  *  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0025  *  OTHER DEALINGS IN THE SOFTWARE.
0026  */
0027 
0028 #include <fcntl.h>
0029 #include <malloc.h>
0030 #include <poll.h>
0031 #include <stdint.h>
0032 #include <string.h>
0033 #include <unistd.h>
0034 
0035 #include <sys/ioctl.h>
0036 #include <sys/stat.h>
0037 #include <sys/types.h>
0038 
0039 #include "sync.h"
0040 #include "sw_sync.h"
0041 
0042 #include <linux/sync_file.h>
0043 
0044 
0045 /* SW_SYNC ioctls */
0046 struct sw_sync_create_fence_data {
0047     __u32   value;
0048     char    name[32];
0049     __s32   fence;
0050 };
0051 
0052 #define SW_SYNC_IOC_MAGIC       'W'
0053 #define SW_SYNC_IOC_CREATE_FENCE    _IOWR(SW_SYNC_IOC_MAGIC, 0,\
0054                           struct sw_sync_create_fence_data)
0055 #define SW_SYNC_IOC_INC         _IOW(SW_SYNC_IOC_MAGIC, 1, __u32)
0056 
0057 
0058 int sync_wait(int fd, int timeout)
0059 {
0060     struct pollfd fds;
0061 
0062     fds.fd = fd;
0063     fds.events = POLLIN | POLLERR;
0064 
0065     return poll(&fds, 1, timeout);
0066 }
0067 
0068 int sync_merge(const char *name, int fd1, int fd2)
0069 {
0070     struct sync_merge_data data = {};
0071     int err;
0072 
0073     data.fd2 = fd2;
0074     strncpy(data.name, name, sizeof(data.name) - 1);
0075     data.name[sizeof(data.name) - 1] = '\0';
0076 
0077     err = ioctl(fd1, SYNC_IOC_MERGE, &data);
0078     if (err < 0)
0079         return err;
0080 
0081     return data.fence;
0082 }
0083 
0084 static struct sync_file_info *sync_file_info(int fd)
0085 {
0086     struct sync_file_info *info;
0087     struct sync_fence_info *fence_info;
0088     int err, num_fences;
0089 
0090     info = calloc(1, sizeof(*info));
0091     if (info == NULL)
0092         return NULL;
0093 
0094     err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
0095     if (err < 0) {
0096         free(info);
0097         return NULL;
0098     }
0099 
0100     num_fences = info->num_fences;
0101 
0102     if (num_fences) {
0103         info->flags = 0;
0104         info->num_fences = num_fences;
0105 
0106         fence_info = calloc(num_fences, sizeof(*fence_info));
0107         if (!fence_info) {
0108             free(info);
0109             return NULL;
0110         }
0111 
0112         info->sync_fence_info = (uint64_t)(unsigned long)fence_info;
0113 
0114         err = ioctl(fd, SYNC_IOC_FILE_INFO, info);
0115         if (err < 0) {
0116             free(fence_info);
0117             free(info);
0118             return NULL;
0119         }
0120     }
0121 
0122     return info;
0123 }
0124 
0125 static void sync_file_info_free(struct sync_file_info *info)
0126 {
0127     free((void *)(unsigned long)info->sync_fence_info);
0128     free(info);
0129 }
0130 
0131 int sync_fence_size(int fd)
0132 {
0133     int count;
0134     struct sync_file_info *info = sync_file_info(fd);
0135 
0136     if (!info)
0137         return 0;
0138 
0139     count = info->num_fences;
0140 
0141     sync_file_info_free(info);
0142 
0143     return count;
0144 }
0145 
0146 int sync_fence_count_with_status(int fd, int status)
0147 {
0148     unsigned int i, count = 0;
0149     struct sync_fence_info *fence_info = NULL;
0150     struct sync_file_info *info = sync_file_info(fd);
0151 
0152     if (!info)
0153         return -1;
0154 
0155     fence_info = (struct sync_fence_info *)(unsigned long)info->sync_fence_info;
0156     for (i = 0 ; i < info->num_fences ; i++) {
0157         if (fence_info[i].status == status)
0158             count++;
0159     }
0160 
0161     sync_file_info_free(info);
0162 
0163     return count;
0164 }
0165 
0166 int sw_sync_timeline_create(void)
0167 {
0168     return open("/sys/kernel/debug/sync/sw_sync", O_RDWR);
0169 }
0170 
0171 int sw_sync_timeline_inc(int fd, unsigned int count)
0172 {
0173     __u32 arg = count;
0174 
0175     return ioctl(fd, SW_SYNC_IOC_INC, &arg);
0176 }
0177 
0178 int sw_sync_timeline_is_valid(int fd)
0179 {
0180     int status;
0181 
0182     if (fd == -1)
0183         return 0;
0184 
0185     status = fcntl(fd, F_GETFD, 0);
0186     return (status >= 0);
0187 }
0188 
0189 void sw_sync_timeline_destroy(int fd)
0190 {
0191     if (sw_sync_timeline_is_valid(fd))
0192         close(fd);
0193 }
0194 
0195 int sw_sync_fence_create(int fd, const char *name, unsigned int value)
0196 {
0197     struct sw_sync_create_fence_data data = {};
0198     int err;
0199 
0200     data.value = value;
0201     strncpy(data.name, name, sizeof(data.name) - 1);
0202     data.name[sizeof(data.name) - 1] = '\0';
0203 
0204     err = ioctl(fd, SW_SYNC_IOC_CREATE_FENCE, &data);
0205     if (err < 0)
0206         return err;
0207 
0208     return data.fence;
0209 }
0210 
0211 int sw_sync_fence_is_valid(int fd)
0212 {
0213     /* Same code! */
0214     return sw_sync_timeline_is_valid(fd);
0215 }
0216 
0217 void sw_sync_fence_destroy(int fd)
0218 {
0219     if (sw_sync_fence_is_valid(fd))
0220         close(fd);
0221 }