linux/tools/testing/selftests/sync/sync.c
<<
>>
Prefs
   1/*
   2 *  sync / sw_sync abstraction
   3 *  Copyright 2015-2016 Collabora Ltd.
   4 *
   5 *  Based on the implementation from the Android Open Source Project,
   6 *
   7 *  Copyright 2012 Google, Inc
   8 *
   9 *  Permission is hereby granted, free of charge, to any person obtaining a
  10 *  copy of this software and associated documentation files (the "Software"),
  11 *  to deal in the Software without restriction, including without limitation
  12 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13 *  and/or sell copies of the Software, and to permit persons to whom the
  14 *  Software is furnished to do so, subject to the following conditions:
  15 *
  16 *  The above copyright notice and this permission notice shall be included in
  17 *  all copies or substantial portions of the Software.
  18 *
  19 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  22 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23 *  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 OR
  25 *  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