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