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