threaded.c revision 9bd392ad
1e6188e58Smrg/* 2e6188e58Smrg * Copyright © 2015 Canonical Ltd. (Maarten Lankhorst) 3e6188e58Smrg * 4e6188e58Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5e6188e58Smrg * copy of this software and associated documentation files (the "Software"), 6e6188e58Smrg * to deal in the Software without restriction, including without limitation 7e6188e58Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8e6188e58Smrg * and/or sell copies of the Software, and to permit persons to whom the 9e6188e58Smrg * Software is furnished to do so, subject to the following conditions: 10e6188e58Smrg * 11e6188e58Smrg * The above copyright notice and this permission notice shall be included in 12e6188e58Smrg * all copies or substantial portions of the Software. 13e6188e58Smrg * 14e6188e58Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15e6188e58Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16e6188e58Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17e6188e58Smrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18e6188e58Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19e6188e58Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20e6188e58Smrg * OTHER DEALINGS IN THE SOFTWARE. 21e6188e58Smrg */ 22e6188e58Smrg 23e6188e58Smrg#include <sys/ioctl.h> 24e6188e58Smrg#include <dlfcn.h> 25e6188e58Smrg#include <fcntl.h> 26e6188e58Smrg#include <stdio.h> 27e6188e58Smrg#include <unistd.h> 28e6188e58Smrg#include <errno.h> 29e6188e58Smrg#include <pthread.h> 30e6188e58Smrg 31e6188e58Smrg#include "xf86drm.h" 32e6188e58Smrg#include "nouveau.h" 33e6188e58Smrg 34e6188e58Smrgstatic typeof(ioctl) *old_ioctl; 35e6188e58Smrgstatic int failed; 36e6188e58Smrg 37e6188e58Smrgstatic int import_fd; 38e6188e58Smrg 399bd392adSmrg#if defined(__GLIBC__) || defined(__FreeBSD__) 40e6188e58Smrgint ioctl(int fd, unsigned long request, ...) 419bd392adSmrg#else 429bd392adSmrgint ioctl(int fd, int request, ...) 439bd392adSmrg#endif 44e6188e58Smrg{ 45e6188e58Smrg va_list va; 46e6188e58Smrg int ret; 47e6188e58Smrg void *arg; 48e6188e58Smrg 49e6188e58Smrg va_start(va, request); 50e6188e58Smrg arg = va_arg(va, void *); 51e6188e58Smrg ret = old_ioctl(fd, request, arg); 52e6188e58Smrg va_end(va); 53e6188e58Smrg 54e6188e58Smrg if (ret < 0 && request == DRM_IOCTL_GEM_CLOSE && errno == EINVAL) 55e6188e58Smrg failed = 1; 56e6188e58Smrg 57e6188e58Smrg return ret; 58e6188e58Smrg} 59e6188e58Smrg 60e6188e58Smrgstatic void * 61e6188e58Smrgopenclose(void *dev) 62e6188e58Smrg{ 63e6188e58Smrg struct nouveau_device *nvdev = dev; 64e6188e58Smrg struct nouveau_bo *bo = NULL; 65e6188e58Smrg int i; 66e6188e58Smrg 67e6188e58Smrg for (i = 0; i < 100000; ++i) { 68e6188e58Smrg if (!nouveau_bo_prime_handle_ref(nvdev, import_fd, &bo)) 69e6188e58Smrg nouveau_bo_ref(NULL, &bo); 70e6188e58Smrg } 71e6188e58Smrg return NULL; 72e6188e58Smrg} 73e6188e58Smrg 74e6188e58Smrgint main(int argc, char *argv[]) 75e6188e58Smrg{ 76e6188e58Smrg drmVersionPtr version; 77e6188e58Smrg const char *device = NULL; 78e6188e58Smrg int err, fd, fd2; 79e6188e58Smrg struct nouveau_device *nvdev, *nvdev2; 80e6188e58Smrg struct nouveau_bo *bo; 81e6188e58Smrg pthread_t t1, t2; 82e6188e58Smrg 83e6188e58Smrg old_ioctl = dlsym(RTLD_NEXT, "ioctl"); 84e6188e58Smrg 85e6188e58Smrg if (argc < 2) { 86e6188e58Smrg fd = drmOpenWithType("nouveau", NULL, DRM_NODE_RENDER); 87e6188e58Smrg if (fd >= 0) 88e6188e58Smrg fd2 = drmOpenWithType("nouveau", NULL, DRM_NODE_RENDER); 89e6188e58Smrg } else { 90e6188e58Smrg device = argv[1]; 91e6188e58Smrg 92e6188e58Smrg fd = open(device, O_RDWR); 93e6188e58Smrg if (fd >= 0) 94e6188e58Smrg fd2 = open(device, O_RDWR); 95e6188e58Smrg else 96e6188e58Smrg fd2 = fd = -errno; 97e6188e58Smrg } 98e6188e58Smrg 99e6188e58Smrg if (fd < 0) { 100e6188e58Smrg fprintf(stderr, "Opening nouveau render node failed with %i\n", fd); 101e6188e58Smrg return device ? -fd : 77; 102e6188e58Smrg } 103e6188e58Smrg 104e6188e58Smrg if (fd2 < 0) { 105e6188e58Smrg fprintf(stderr, "Opening second nouveau render node failed with %i\n", -errno); 106e6188e58Smrg return errno; 107e6188e58Smrg } 108e6188e58Smrg 109e6188e58Smrg version = drmGetVersion(fd); 110e6188e58Smrg if (version) { 111e6188e58Smrg printf("Version: %d.%d.%d\n", version->version_major, 112e6188e58Smrg version->version_minor, version->version_patchlevel); 113e6188e58Smrg printf(" Name: %s\n", version->name); 114e6188e58Smrg printf(" Date: %s\n", version->date); 115e6188e58Smrg printf(" Description: %s\n", version->desc); 116e6188e58Smrg 117e6188e58Smrg drmFreeVersion(version); 118e6188e58Smrg } 119e6188e58Smrg 120e6188e58Smrg err = nouveau_device_wrap(fd, 0, &nvdev); 121e6188e58Smrg if (!err) 122e6188e58Smrg err = nouveau_device_wrap(fd2, 0, &nvdev2); 123e6188e58Smrg if (err < 0) 124e6188e58Smrg return 1; 125e6188e58Smrg 126e6188e58Smrg err = nouveau_bo_new(nvdev2, NOUVEAU_BO_GART, 0, 4096, NULL, &bo); 127e6188e58Smrg if (!err) 128e6188e58Smrg err = nouveau_bo_set_prime(bo, &import_fd); 129e6188e58Smrg 130e6188e58Smrg if (!err) { 131e6188e58Smrg pthread_create(&t1, NULL, openclose, nvdev); 132e6188e58Smrg pthread_create(&t2, NULL, openclose, nvdev); 133e6188e58Smrg } 134e6188e58Smrg 135e6188e58Smrg pthread_join(t1, NULL); 136e6188e58Smrg pthread_join(t2, NULL); 137e6188e58Smrg 138e6188e58Smrg close(import_fd); 139e6188e58Smrg nouveau_bo_ref(NULL, &bo); 140e6188e58Smrg 141e6188e58Smrg nouveau_device_del(&nvdev2); 142e6188e58Smrg nouveau_device_del(&nvdev); 143e6188e58Smrg if (device) { 144e6188e58Smrg close(fd2); 145e6188e58Smrg close(fd); 146e6188e58Smrg } else { 147e6188e58Smrg drmClose(fd2); 148e6188e58Smrg drmClose(fd); 149e6188e58Smrg } 150e6188e58Smrg 151e6188e58Smrg if (failed) 152e6188e58Smrg fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed with EINVAL,\n" 153e6188e58Smrg "race in opening/closing bo is likely.\n"); 154e6188e58Smrg 155e6188e58Smrg return failed; 156e6188e58Smrg} 157