Home | History | Annotate | Line # | Download | only in src
      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