xshmfence_alloc.c revision 875bea1a
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#if !HAVE_MEMFD_CREATE
30#if HAVE_DECL___NR_MEMFD_CREATE
31#include <asm/unistd.h>
32static int memfd_create(const char *name,
33			    unsigned int flags)
34{
35	return syscall(__NR_memfd_create, name, flags);
36}
37#define HAVE_MEMFD_CREATE	1
38#endif
39#endif
40
41#if HAVE_MEMFD_CREATE
42
43/* Get defines for the memfd_create syscall, using the
44 * header if available, or just defining the constants otherwise
45 */
46
47#if HAVE_MEMFD_H
48#include <sys/memfd.h>
49#else
50/* flags for memfd_create(2) (unsigned int) */
51#define MFD_CLOEXEC		0x0001U
52#define MFD_ALLOW_SEALING	0x0002U
53#endif
54
55#endif
56
57/**
58 * xshmfence_alloc_shm:
59 *
60 * Allocates a shared memory object large enough to hold a single
61 * fence.
62 *
63 * Return value: the file descriptor of the object, or -1 on failure
64 * (in which case, errno will be set as appropriate).
65 **/
66int
67xshmfence_alloc_shm(void)
68{
69	char	template[] = SHMDIR "/shmfd-XXXXXX";
70	int	fd;
71
72#if HAVE_MEMFD_CREATE
73	fd = memfd_create("xshmfence", MFD_CLOEXEC|MFD_ALLOW_SEALING);
74	if (fd < 0)
75#endif
76	{
77#ifdef O_TMPFILE
78		fd = open(SHMDIR, O_TMPFILE|O_RDWR|O_CLOEXEC|O_EXCL, 0666);
79		if (fd < 0)
80#endif
81		{
82			fd = mkstemp(template);
83			if (fd < 0)
84				return fd;
85			unlink(template);
86		}
87	}
88	if (ftruncate(fd, sizeof (struct xshmfence)) < 0) {
89            close(fd);
90            return -1;
91        }
92        xshmfence_init(fd);
93	return fd;
94}
95
96/**
97 * xshmfence_map_shm:
98 *
99 * Map a shared memory fence referenced by @fd.
100 *
101 * Return value: the fence or NULL (in which case, errno will be set
102 * as appropriate).
103 **/
104struct xshmfence *
105xshmfence_map_shm(int fd)
106{
107	struct xshmfence *addr;
108	addr = mmap (NULL, sizeof (struct xshmfence) , PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
109	if (addr == MAP_FAILED) {
110		close (fd);
111		return 0;
112	}
113#ifdef HAVE_SEMAPHORE
114	xshmfence_open_semaphore(addr);
115#endif
116	return addr;
117}
118
119/**
120 * xshmfence_unmap_shm:
121 *
122 * Unap a shared memory fence @f.
123 **/
124void
125xshmfence_unmap_shm(struct xshmfence *f)
126{
127#ifdef HAVE_SEMAPHORE
128	xshmfence_close_semaphore(f);
129#endif
130        munmap(f, sizeof (struct xshmfence));
131}
132