1 /* 2 * Copyright 2013 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23 #if HAVE_CONFIG_H 24 #include "config.h" 25 #endif 26 27 #include "xshmfenceint.h" 28 29 #include <fcntl.h> 30 31 #if !HAVE_MEMFD_CREATE 32 #if HAVE_DECL___NR_MEMFD_CREATE 33 #include <asm/unistd.h> 34 static int memfd_create(const char *name, 35 unsigned int flags) 36 { 37 return syscall(__NR_memfd_create, name, flags); 38 } 39 #define HAVE_MEMFD_CREATE 1 40 #endif 41 #endif 42 43 #if HAVE_MEMFD_CREATE 44 45 /* Get defines for the memfd_create syscall, using the 46 * header if available, or just defining the constants otherwise 47 */ 48 49 #if HAVE_MEMFD_H 50 #include <sys/memfd.h> 51 #else 52 /* flags for memfd_create(2) (unsigned int) */ 53 #define MFD_CLOEXEC 0x0001U 54 #define MFD_ALLOW_SEALING 0x0002U 55 #endif 56 57 #endif 58 59 /** 60 * xshmfence_alloc_shm: 61 * 62 * Allocates a shared memory object large enough to hold a single 63 * fence. 64 * 65 * Return value: the file descriptor of the object, or -1 on failure 66 * (in which case, errno will be set as appropriate). 67 **/ 68 int 69 xshmfence_alloc_shm(void) 70 { 71 char template[] = SHMDIR "/shmfd-XXXXXX"; 72 int fd; 73 #ifndef HAVE_MKOSTEMP 74 int flags; 75 #endif 76 77 #if HAVE_MEMFD_CREATE 78 fd = memfd_create("xshmfence", MFD_CLOEXEC|MFD_ALLOW_SEALING); 79 if (fd < 0) 80 #endif 81 #ifdef SHM_ANON 82 fd = shm_open(SHM_ANON, O_RDWR|O_CLOEXEC, 0600); 83 if (fd < 0) 84 #endif 85 { 86 #ifdef O_TMPFILE 87 fd = open(SHMDIR, O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666); 88 if (fd < 0) 89 #endif 90 { 91 #ifdef HAVE_MKOSTEMP 92 fd = mkostemp(template, O_CLOEXEC); 93 #else 94 fd = mkstemp(template); 95 #endif 96 if (fd < 0) 97 return fd; 98 unlink(template); 99 #ifndef HAVE_MKOSTEMP 100 flags = fcntl(fd, F_GETFD); 101 if (flags != -1) { 102 flags |= FD_CLOEXEC; 103 fcntl(fd, F_SETFD, &flags); 104 } 105 #endif 106 } 107 } 108 if (ftruncate(fd, sizeof (struct xshmfence)) < 0) { 109 close(fd); 110 return -1; 111 } 112 xshmfence_init(fd); 113 return fd; 114 } 115 116 /** 117 * xshmfence_map_shm: 118 * 119 * Map a shared memory fence referenced by @fd. 120 * 121 * Return value: the fence or NULL (in which case, errno will be set 122 * as appropriate). 123 **/ 124 struct xshmfence * 125 xshmfence_map_shm(int fd) 126 { 127 struct xshmfence *addr; 128 addr = mmap (NULL, sizeof (struct xshmfence) , PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 129 if (addr == MAP_FAILED) { 130 close (fd); 131 return 0; 132 } 133 #ifdef HAVE_SEMAPHORE 134 xshmfence_open_semaphore(addr); 135 #endif 136 return addr; 137 } 138 139 /** 140 * xshmfence_unmap_shm: 141 * 142 * Unap a shared memory fence @f. 143 **/ 144 void 145 xshmfence_unmap_shm(struct xshmfence *f) 146 { 147 #ifdef HAVE_SEMAPHORE 148 xshmfence_close_semaphore(f); 149 #endif 150 munmap(f, sizeof (struct xshmfence)); 151 } 152